Button Group
A container that groups related buttons together with consistent styling.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ButtonGroupExample() -> impl IntoView { view! { <ButtonGroup> <ButtonGroup class="flex"> <Button variant="outline" size="icon" aria_label="Go Back"> {icon!(icondata::LuArrowLeft, width=24, height=24)} </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 class="w-52"> <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> </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
The ButtonGroupSeparator component visually divides buttons within a group. Buttons with variant outline do not need a separator since they have a border. For other variants, a separator is recommended 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 by adding two buttons separated by a ButtonGroupSeparator.
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() { 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 value="Voice Mode"> <Button on:click=move |_| voice_enabled.set(!voice_enabled.get()) size="icon-xs" class > {icon!(icondata::LuAudioLines)} </Button> </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="!pl-2"> {icon!(icondata::LuChevronDown)} </Button> </DropdownMenuTrigger> <DropdownMenuContent class="[--radius:1rem]"> <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> <SelectContent label="Currency"> <SelectItem value="$">"$"</SelectItem> <SelectItem value="€">"€"</SelectItem> <SelectItem value="£">"£"</SelectItem> </SelectContent> </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 class="rounded-xl p-0 text-sm max-w-72"> <p class="px-4 pt-3 text-sm font-medium">"Agent Tasks"</p> <Separator /> <div class="p-4 pt-0 text-sm *:[p:not(:last-child)]:mb-2"> <Textarea placeholder="Describe your task in natural language." class="mb-4 resize-none" /> <p class="font-medium">"Start a new task with Copilot"</p> <p class="text-(--muted-foreground)"> "Describe your task in natural language. Copilot will work in the background and open a pull request for your review." </p> </div> </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. |
ButtonGroupText
Creates a styled text element for use in the ButtonGroup.