---
import ArchiveIcon from "@lucide/astro/icons/archive"
import MailIcon from "@lucide/astro/icons/mail"
import TrashIcon from "@lucide/astro/icons/trash-2"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
---
<ButtonGroup aria-label="Message actions">
<Button variant="outline"><ArchiveIcon /> Archive</Button>
<Button variant="outline"><MailIcon /> Mark unread</Button>
<Button variant="outline" size="icon" aria-label="Delete"
><TrashIcon /></Button
>
</ButtonGroup>Installation
npx shadcn@latest add @fulldev/button-group
Usage
---
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
---
<ButtonGroup aria-label="Document actions">
<Button variant="outline">Save</Button>
<Button variant="outline">Publish</Button>
</ButtonGroup>
Give each group an accessible name with aria-label or aria-labelledby.
Examples
Sizes
Button sizes continue to work inside a group.
---
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
---
<div class="flex flex-col items-start gap-4">
<ButtonGroup aria-label="Small view controls">
<Button variant="outline" size="sm">List</Button>
<Button variant="outline" size="sm">Grid</Button>
</ButtonGroup>
<ButtonGroup aria-label="Default view controls">
<Button variant="outline">List</Button>
<Button variant="outline">Grid</Button>
</ButtonGroup>
</div>Vertical
---
import CopyIcon from "@lucide/astro/icons/copy"
import SearchIcon from "@lucide/astro/icons/search"
import SettingsIcon from "@lucide/astro/icons/settings"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
---
<ButtonGroup orientation="vertical" aria-label="Document tools">
<Button variant="outline" size="icon" aria-label="Search"
><SearchIcon /></Button
>
<Button variant="outline" size="icon" aria-label="Copy"><CopyIcon /></Button>
<Button variant="outline" size="icon" aria-label="Settings"
><SettingsIcon /></Button
>
</ButtonGroup>With Text
ButtonGroupText is polymorphic. Render it as a label when it describes a form control.
---
import { ButtonGroup, ButtonGroupText } from "@/components/ui/button-group"
import { Input } from "@/components/ui/input"
---
<ButtonGroup class="w-full max-w-sm" aria-label="Repository owner">
<ButtonGroupText as="label" for="repository-name">full.dev/</ButtonGroupText>
<Input id="repository-name" value="ui" aria-label="Repository name" />
</ButtonGroup>Nested Groups
Nested groups keep a gap between related sets while preserving connected controls inside each set.
---
import ChevronLeftIcon from "@lucide/astro/icons/chevron-left"
import ChevronRightIcon from "@lucide/astro/icons/chevron-right"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
---
<ButtonGroup aria-label="Pagination controls">
<ButtonGroup aria-label="Pages">
<Button as="a" href="?page=1" variant="outline">1</Button>
<Button as="a" href="?page=2" variant="outline">2</Button>
<Button as="a" href="?page=3" variant="outline">3</Button>
</ButtonGroup>
<ButtonGroup aria-label="Previous and next page">
<Button
as="a"
href="?page=1"
variant="outline"
size="icon-xs"
aria-label="Previous page"><ChevronLeftIcon /></Button
>
<Button
as="a"
href="?page=3"
variant="outline"
size="icon-xs"
aria-label="Next page"><ChevronRightIcon /></Button
>
</ButtonGroup>
</ButtonGroup>API Reference
ButtonGroup
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" | Controls the layout and connected edges. |
as | HTMLTag | "div" | Changes the rendered element. |
ButtonGroupText
Accepts as and the attributes for that HTML element.
ButtonGroupSeparator
Uses the Separator API. Its orientation defaults to "vertical".
See the GitHub source code for the component source.