Button group
Buttons side by side as one control: attached into one pill sharing a hairline, or split a hair apart for an action and its options.
ui.button-group
components/ui/group.tsxUse case
Use it when buttons belong together and should read as one thing: Previous, Today and Next above a delivery schedule, or a split button where Send Invoice is the action and a chevron beside it opens the other ways to send. Attached (the default) joins them into one pill; attached={false} keeps each its own shape so a chevron reads centred.
Use it when
- Paging through dates or records: previous, the current one, next
- A split button: the main action and a chevron for its options
- A short row of related actions that read as one control
Use something else when
- One of several options stays selected (Day, Week, Month): Segmented control
- Formatting switches that stay pressed: Toggle group
- A whole bar of tools with separators: Toolbar
Examples
Attached: one pill, one hairline between
Split: the action and its options, a hair apart
Code
Import
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "@/components/icons"
import { Button } from "@/components/ui/button"
import { Group } from "@/components/ui/group"Usage
<Group>
<Button variant="secondary" size="icon" aria-label="Previous Week">
<ChevronLeftIcon />
</Button>
<Button variant="secondary">Today</Button>
<Button variant="secondary" size="icon" aria-label="Next Week">
<ChevronRightIcon />
</Button>
</Group>
<Group attached={false}>
<Button>Send Invoice</Button>
<Button size="icon" aria-label="More Ways to Send">
<ChevronDownIcon />
</Button>
</Group>Rules
- The buttons of one group share a variant and a size.
- An icon-only button in the group carries aria-label.
- The Buttons are direct children of Group: its corners and shared hairline reach only direct children with data-slot="button".
- attached={false} makes a split button; orientation="vertical" stacks the buttons.