ButtonGroup
Pre-alphaThe registry and the CLI are not published yet.Roadmap

ButtonGroup

Groups several attached buttons.

Calendar
Attached outline buttons

Day

Week

Month

Split button
Export
Small, with icons

Today

Spaced

Cancel

Confirm

Installation

npx axiom add button-group
pnpm dlx axiom add button-group
yarn dlx axiom add button-group
bun x axiom add button-group

Also 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

PropTypeDefaultDescription
childrenReactNodeThe Button or IconButton elements to group.
attachedbooleantrueMerges 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.
gapSpacingToken2Space 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.
fullWidthbooleanfalseStretches the group and splits its width evenly between the buttons.
disabledbooleanfalseDisables every button in the group.
styleStyleProp<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.

Q3 report
q3-report.pdf12 pages · 2.4 MB
Download PDF
Download CSVDownload XLSX
<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.

Cold brew$4.50 each
Quantity

2

Add · $9.00

<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.

Leave the call?

The others can keep talking.

Stay

Leave
<Dialog.Actions>
	<ButtonGroup attached={false} fullWidth style={{ flex: 1 }}>
		<Dialog.Cancel>Stay</Dialog.Cancel>
		<Dialog.Action onPress={leave}>Leave</Dialog.Action>
	</ButtonGroup>
</Dialog.Actions>