Button Group
A container that groups related buttons together with consistent styling.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupExample() -> impl IntoView { let label = RwSignal::new("personal".to_string()); view! { <ButtonGroup> <ButtonGroup class="flex"> <Button variant="outline" size="icon" aria_label="Go Back"> {icon!(icondata::LuArrowLeft)} </Button> </ButtonGroup> <ButtonGroup> <Button variant="outline">"Archive"</Button> <Button variant="outline">"Report"</Button> </ButtonGroup> <ButtonGroup> <Button variant="outline">"Snooze"</Button> <DropdownMenu> <DropdownMenuTrigger> <Button variant="outline" size="icon" aria_label="More Options"> {icon!(icondata::FiMoreHorizontal)} </Button> </DropdownMenuTrigger> <DropdownMenuContent align="end"> <DropdownMenuGroup> <DropdownMenuItem> {icon!(icondata::LuMailCheck)} "Mark as Read" </DropdownMenuItem> <DropdownMenuItem> {icon!(icondata::LuArchive)} "Archive" </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem>{icon!(icondata::LuClock)} "Snooze"</DropdownMenuItem> <DropdownMenuItem> {icon!(icondata::LuCalendarPlus)} "Add to Calendar" </DropdownMenuItem> <DropdownMenuItem> {icon!(icondata::LuListPlus)} "Add to List" </DropdownMenuItem> <DropdownMenuSub> <DropdownMenuSubTrigger> {icon!(icondata::LuTag)} "Label As..." </DropdownMenuSubTrigger> <DropdownMenuSubContent> <DropdownMenuRadioGroup value=label> <DropdownMenuRadioItem value="personal"> "Personal" </DropdownMenuRadioItem> <DropdownMenuRadioItem value="work"> "Work" </DropdownMenuRadioItem> <DropdownMenuRadioItem value="other"> "Other" </DropdownMenuRadioItem> </DropdownMenuRadioGroup> </DropdownMenuSubContent> </DropdownMenuSub> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem variant="destructive"> {icon!(icondata::LuTrash2)} "Trash" </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </ButtonGroup> </ButtonGroup> } }
Orientation
Set the orientation prop to change the button group layout.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupOrientationExample() -> impl IntoView { view! { <ButtonGroup vertical=true aria_label="Media controls" class="h-fit"> <Button variant="outline" size="icon"> {icon!(icondata::LuPlus)} </Button> <Button variant="outline" size="icon"> {icon!(icondata::LuMinus)} </Button> </ButtonGroup> } }
Size
Control the size of buttons using the size prop on individual buttons.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupSizeExample() -> impl IntoView { view! { <div class="flex flex-col items-start gap-8"> <ButtonGroup> <Button variant="outline" size="sm"> "Small" </Button> <Button variant="outline" size="sm"> "Button" </Button> <Button variant="outline" size="sm"> "Group" </Button> <Button variant="outline" size="icon-sm"> {icon!(icondata::LuPlus)} </Button> </ButtonGroup> <ButtonGroup> <Button variant="outline">"Default"</Button> <Button variant="outline">"Button"</Button> <Button variant="outline">"Group"</Button> <Button variant="outline" size="icon"> {icon!(icondata::LuPlus)} </Button> </ButtonGroup> <ButtonGroup> <Button variant="outline" size="lg"> "Large" </Button> <Button variant="outline" size="lg"> "Button" </Button> <Button variant="outline" size="lg"> "Group" </Button> <Button variant="outline" size="icon-lg"> {icon!(icondata::LuPlus)} </Button> </ButtonGroup> </div> } }
Nested
Nest
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupNestedExample() -> impl IntoView { view! { <ButtonGroup> <ButtonGroup> <Button variant="outline" size="sm"> "1" </Button> <Button variant="outline" size="sm"> "2" </Button> <Button variant="outline" size="sm"> "3" </Button> <Button variant="outline" size="sm"> "4" </Button> <Button variant="outline" size="sm"> "5" </Button> </ButtonGroup> <ButtonGroup> <Button variant="outline" size="icon-sm" aria_label="Previous"> {icon!(icondata::LuArrowLeft)} </Button> <Button variant="outline" size="icon-sm" aria_label="Next"> {icon!(icondata::LuArrowRight)} </Button> </ButtonGroup> </ButtonGroup> } }
Separator
Some buttons don't need a separator since they have a border. For other variants use a Separator to improve the visual hierarchy.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupSeparatorExample() -> impl IntoView { view! { <ButtonGroup> <Button variant="secondary" size="sm"> "Copy" </Button> <ButtonGroupSeparator /> <Button variant="secondary" size="sm"> "Paste" </Button> </ButtonGroup> } }
Split
Create a split button group using a Separator.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupSplitExample() -> impl IntoView { view! { <ButtonGroup> <Button variant="secondary">"Button"</Button> <ButtonGroupSeparator /> <Button size="icon" variant="secondary"> {icon!(icondata::LuPlus)} </Button> </ButtonGroup> } }
Input
Wrap an Input component with buttons.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupInputExample() -> impl IntoView { view! { <ButtonGroup> <Input placeholder="Search..." /> <Button variant="outline" aria_label="Search"> {icon!(icondata::LuSearch)} </Button> </ButtonGroup> } }
Input Group
Wrap an InputGroup component to create complex input layouts.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupInputGroupExample() -> impl IntoView { let theme = expect_context::<ThemeProviderContext>(); let voice_enabled = RwSignal::new(false); let class = RwSignal::new("rounded-full".to_string()); let placeholder = RwSignal::new("Send a message...".to_string()); Effect::new(move || { class.set(format!( "rounded-full {}", if voice_enabled.get() { // TODO: make a reactive signal for the current preferred mode match theme.mode.get() { Mode::Dark => "bg-orange-800 text-orange-100", Mode::Light => "bg-orange-100 text-orange-700", _ => "bg-orange-100 text-orange-700 dark:bg-orange-800 dark:text-orange-100", } } else { "" } )); }); Effect::new(move || { placeholder.set( if voice_enabled.get() { "Record and send audio..." } else { "Send a message..." } .to_string(), ); }); view! { <ButtonGroup> <ButtonGroup> <Button class="rounded-full" variant="outline" size="icon"> {icon!(icondata::LuPlus)} </Button> </ButtonGroup> <ButtonGroup> <InputGroup class="rounded-full"> <Input placeholder disabled=voice_enabled /> <InputGroupAddon align="inline-end"> <Tooltip> <TooltipTrigger> <Button on:click=move |_| voice_enabled.set(!voice_enabled.get_untracked()) size="icon-xs" class > {icon!(icondata::LuAudioLines)} </Button> </TooltipTrigger> <TooltipContent> <p>"Voice Mode"</p> </TooltipContent> </Tooltip> </InputGroupAddon> </InputGroup> </ButtonGroup> </ButtonGroup> } }
Dropdown Menu
Create a split button group with a DropdownMenu component.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupDropdownExample() -> impl IntoView { view! { <ButtonGroup> <Button variant="outline">"Follow"</Button> <DropdownMenu> <DropdownMenuTrigger> <Button variant="outline" class="!px-2"> {icon!(icondata::LuChevronDown)} </Button> </DropdownMenuTrigger> <DropdownMenuContent align="end"> <DropdownMenuGroup> <DropdownMenuItem> {icon!(icondata::BiVolumeMuteRegular)} "Mute Conversation" </DropdownMenuItem> <DropdownMenuItem> {icon!(icondata::LuCheck)} "Mark as Read" </DropdownMenuItem> <DropdownMenuItem> {icon!(icondata::FiAlertTriangle)} "Report Conversation" </DropdownMenuItem> <DropdownMenuItem>{icon!(icondata::LuUserX)} "Block User"</DropdownMenuItem> <DropdownMenuItem> {icon!(icondata::LuShare)} "Share Conversation" </DropdownMenuItem> <DropdownMenuItem> {icon!(icondata::LuCopy)} "Copy Conversation" </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem variant="destructive"> {icon!(icondata::LuTrash)}"Delete Conversation" </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </ButtonGroup> } }
Select
Pair with a Select component.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupSelectExample() -> impl IntoView { let currency = RwSignal::new("$".to_string()); view! { <ButtonGroup> <ButtonGroup> <Select value=currency> <SelectOptGroup label="Currency"> <SelectOption value="$">"$"</SelectOption> <SelectOption value="€">"€"</SelectOption> <SelectOption value="£">"£"</SelectOption> </SelectOptGroup> </Select> <Input placeholder="10.00" pattern="[0-9]*" /> </ButtonGroup> <ButtonGroup> <Button aria_label="Send" size="icon" variant="outline"> {icon!(icondata::LuArrowRight)} </Button> </ButtonGroup> </ButtonGroup> } }
Popover
Use with a Popover component.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupPopoverExample() -> impl IntoView { view! { <ButtonGroup> <Button variant="outline">{icon!(icondata::LuBot)} "Copilot"</Button> <Popover> <PopoverTrigger> <Button variant="outline" size="icon" aria_label="Open Popover"> {icon!(icondata::LuChevronDown)} </Button> </PopoverTrigger> <PopoverContent align="end"> <PopoverHeader> <PopoverTitle>"Start a new task with Copilot"</PopoverTitle> <PopoverDescription> "Describe your task in natural language." </PopoverDescription> </PopoverHeader> <Field> <FieldLabel label_for="task" class="sr-only"> "Task Description" </FieldLabel> <Textarea id="task" placeholder="I need to..." class="resize-none" /> <FieldDescription> "Copilot will open a pull request for review." </FieldDescription> </Field> </PopoverContent> </Popover> </ButtonGroup> } }
Anatomy
Import all parts and piece them together.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupAnatomy() -> impl IntoView { view! { <ButtonGroup> <Button /> <ButtonGroupSeparator /> <ButtonGroupText /> </ButtonGroup> } }
API Reference
ButtonGroup
Contains the Buttons that make up the ButtonGroup.
| Name | Type | Default | Description |
|---|---|---|---|
| vertical | bool | false | Sets the display direction of the ButtonGroup. |
ButtonGroupSeparator
Visually separates button group buttons.
| Name | Type | Default | Description |
|---|---|---|---|
| vertical | bool | false | Toggle whether or not the separator should display vertically. |
ButtonGroupText
Creates a styled text element for use in the ButtonGroup.