Button Group
A set of related buttons arranged as a visual unit. Supports attached (fused pill) and detached (spaced) layouts, with shared variant, size, and density propagated via context.
Installation#
Usage#
import { ButtonGroup, ButtonGroupItem } from "@/components/ui/button-group"
export function Example() {
return (
<ButtonGroup>
<ButtonGroupItem>Day</ButtonGroupItem>
<ButtonGroupItem>Week</ButtonGroupItem>
<ButtonGroupItem>Month</ButtonGroupItem>
</ButtonGroup>
)
}Anatomy#
import { ButtonGroup, ButtonGroupItem } from "@/components/ui/button-group"
<ButtonGroup>
<ButtonGroupItem />
<ButtonGroupItem />
</ButtonGroup>Attached vs Detached#
By default, attached fuses buttons into a single pill: interior border radii are stripped and every item after the first drops its left border, so neighbours share one 1px stroke instead of stacking two. Set attached={false} for a spaced layout where each button keeps its own rounding.
Variants#
The variant prop on ButtonGroup is inherited by every ButtonGroupItem inside it. Supports all the same variants as Button.
Sizes#
Inherits Button's sizes - xs (28px, for a toolbar of row actions in a dense table), sm (32px), md (36px, the default), and lg (40px). The marketing xl is not offered on a group.
Density#
With no size, density picks the height: compact is sm, comfortable is md. An explicit size still wins. Like a Button, the group ignores an ambient DensityProvider and stays md. See Density.
Icon-only#
Set iconOnly on each item to collapse it to a square. Always pass an aria-label - Koala warns in development if one is missing.
Per-item overrides#
Any prop set directly on a ButtonGroupItem overrides the group context. Mix variants within the same group to give one action more visual weight - keep all items the same surface style (both bordered, or both filled) so the joined edges look intentional.
API reference#
ButtonGroup
A <div role="group"> whose variant and size flow to every item. Forwards all native <div> props. Every part accepts className, merged last.
| Prop | Type | Default | Description |
|---|---|---|---|
| attached | boolean | true | Fuses the items into one pill: inner corners squared, neighbours sharing one stroke. false spaces them with a 4px gap. |
| variant | "primary" | "secondary" | "neutral" | "outline" | "ghost" | "overlay" | "destructive" | "destructiveGhost" | "link" | "outline" | The Button variant every item takes. |
| size | "xs" | "sm" | "md" | "lg" | "md" | The height every item takes: 28, 32, 36 or 40px. Unset, it follows density, then the size a container imposes. |
| density | "comfortable" | "compact" | - | Picks the size when none is set: compact is sm, comfortable is md. An explicit size wins. |
ButtonGroupItem
One button in the group. Forwards all native <button> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "primary" | "secondary" | "neutral" | "outline" | "ghost" | "overlay" | "destructive" | "destructiveGhost" | "link" | - | Overrides the group's variant for this item. |
| size | "xs" | "sm" | "md" | "lg" | - | Overrides the group's size for this item. |
| density | "comfortable" | "compact" | - | Overrides the group's density for this item; beats the group's size too. |
| iconOnly | boolean | false | A square icon button. Pass aria-label; development warns without one. |
| asChild | boolean | false | Renders its single child as the button (Radix Slot). |