ButtonGroup
Groups several attached buttons.
Installation
npx axiom add button-grouppnpm dlx axiom add button-groupyarn dlx axiom add button-groupbun x axiom add button-groupAlso copies: button. No tokens: the buttons keep their own.
Usage
import { Button } from "@/components/ui/button";
import { ButtonGroup } from "@/components/ui/button-group";
<ButtonGroup>
<Button variant="outline">Day</Button>
<Button variant="outline">Week</Button>
<Button variant="outline">Month</Button>
</ButtonGroup>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The Button or IconButton elements to group. |
attached | boolean | true | Merges adjacent borders and keeps only the outer corners rounded. false lays the buttons out with a gap instead. |
orientation | 'horizontal' | 'vertical' | 'horizontal' | Direction of the group. Vertical groups merge top and bottom edges. |
gap | SpacingToken | 2 | Space between buttons when attached is false, from the spacing scale (8pt by default). |
size | 'sm' | 'md' | 'lg' | — | Applied to every child that doesn’t set its own size, so the heights match. |
variant | 'solid' | 'outline' | 'ghost' | — | Applied to every child that doesn’t set its own variant. |
fullWidth | boolean | false | Stretches the group and splits its width evenly between the buttons. |
disabled | boolean | false | Disables every button in the group. |
style | StyleProp<ViewStyle> | — | Extra styles for the container. |
ButtonGroup only handles layout. It doesn’t track a selection: for one choice among several, use SegmentedControl.
Use ButtonGroup.Item for an action wrapped by another component. Its render callback provides containerStyle for the wrapper and buttonStyle for the visible button. Set grow={false} to keep that action compact in a full-width group.
Use cases
Split button
The main action and a chevron that opens a Menu of alternatives.
<Menu.Root>
<ButtonGroup fullWidth>
<Button onPress={downloadPdf}>Download PDF</Button>
<ButtonGroup.Item
grow={false}
render={({ containerStyle, buttonStyle, size, disabled }) => (
<Menu.Trigger action="press" asChild style={containerStyle}>
<IconButton
icon="chevron-down"
accessibilityLabel="Other formats"
variant="solid"
shape="square"
size={size}
disabled={disabled}
style={buttonStyle}
/>
</Menu.Trigger>
)}
/>
</ButtonGroup>
<Menu.Content>…</Menu.Content>
</Menu.Root>Stepper
Minus and plus around a value, read as one control.
<ButtonGroup variant="outline" size="sm">
<IconButton
icon="minus"
accessibilityLabel="Remove one"
onPress={decrement}
/>
<Button disabled>{quantity}</Button>
<IconButton icon="plus" accessibilityLabel="Add one" onPress={increment} />
</ButtonGroup>Dialog actions
attached={false} with fullWidth: two equal buttons with a gap, for a confirmation.
<Dialog.Actions>
<ButtonGroup attached={false} fullWidth style={{ flex: 1 }}>
<Dialog.Cancel>Stay</Dialog.Cancel>
<Dialog.Action onPress={leave}>Leave</Dialog.Action>
</ButtonGroup>
</Dialog.Actions>Related
- Button
- SegmentedControl, for a single selection among options