Button Group
A container that groups related buttons into a segmented control.
import { Button } from '@/components/ui/button';
import { ButtonGroup } from '@/components/ui/button-group';
export default function ButtonGroupDemo() {
return (
<ButtonGroup>
<Button variant="outline">Archive</Button>
<Button variant="outline">Report</Button>
<Button variant="outline">Snooze</Button>
</ButtonGroup>
);
}
Install
npx shadcn@latest add @madeui/button-group
Usage
import {
ButtonGroup,
ButtonGroupSeparator,
ButtonGroupText,
} from '@/components/ui/button-group';
Composition
<ButtonGroup>
<Button />
<Button />
</ButtonGroup>
Orientation
import { Button } from '@/components/ui/button';
import { ButtonGroup } from '@/components/ui/button-group';
export default function ButtonGroupOrientation() {
return (
<ButtonGroup orientation="vertical">
<Button variant="outline">Archive</Button>
<Button variant="outline">Report</Button>
<Button variant="outline">Snooze</Button>
</ButtonGroup>
);
}
Split button
Nest a DropdownMenu whose trigger renders as a Button — ButtonGroup fuses the primary action and the trigger into one control.
import { Button } from '@/components/ui/button';
import { ButtonGroup } from '@/components/ui/button-group';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
// The trigger's `render` swaps it for a Button — ButtonGroup then fuses both
// the primary action and the trigger into one segmented control.
export default function ButtonGroupSplit() {
return (
<ButtonGroup>
<Button>Deploy</Button>
<DropdownMenu>
<DropdownMenuTrigger render={<Button size="icon" aria-label="More deploy options" />}>
<svg
width="14"
height="14"
viewBox={`0 0 14 14`}
fill="none"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden
>
<path d={`m3.5 5.5 3.5 3.5 3.5-3.5`} />
</svg>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>Deploy to staging</DropdownMenuItem>
<DropdownMenuItem>Roll back last deploy</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</ButtonGroup>
);
}
Text
Filter
import { Button } from '@/components/ui/button';
import { ButtonGroup, ButtonGroupSeparator, ButtonGroupText } from '@/components/ui/button-group';
export default function ButtonGroupTextExample() {
return (
<ButtonGroup>
<ButtonGroupText>Filter</ButtonGroupText>
<ButtonGroupSeparator />
<Button variant="outline">Open</Button>
<Button variant="outline">Closed</Button>
<Button variant="outline">All</Button>
</ButtonGroup>
);
}
Input
import { Button } from '@/components/ui/button';
import { ButtonGroup } from '@/components/ui/button-group';
import { Input } from '@/components/ui/input';
export default function ButtonGroupInput() {
return (
<ButtonGroup>
<Input type="email" placeholder="Email address" />
<Button variant="outline">Subscribe</Button>
</ButtonGroup>
);
}
API reference
ButtonGroup
| Prop | Type | Default | Description |
|---|---|---|---|
orientation |
'horizontal' | 'vertical' |
'horizontal' |
|
style |
StyleXStyles |
— | StyleX styles merged last — always win over the component’s own styles. |
StyleX has no child selectors, so the group clones its direct children and merges position styles (end radii, collapsed inner borders) through each child’s style prop — children must be components that accept style (every component in this library does). ButtonGroupText renders a muted label segment; ButtonGroupSeparator divides segments of a filled group.