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

ButtonGroup

Rounds and clips a row of buttons into one control.

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. The group reads the button radius token for its corners, unless you pass radius.

Usage

import { Button } from "@/components/ui/button";
import { ButtonGroup } from "@/components/ui/button-group";
import { Separator } from "@/components/ui/separator";

<ButtonGroup bordered>
	<Button variant="ghost" style={{ borderRadius: 0 }}>
		Day
	</Button>
	<Separator orientation="vertical" />
	<Button variant="ghost" style={{ borderRadius: 0 }}>
		Week
	</Button>
	<Separator orientation="vertical" />
	<Button variant="ghost" style={{ borderRadius: 0 }}>
		Month
	</Button>
</ButtonGroup>;

The group is a View that rounds its corners and clips what’s inside. It doesn’t touch its children: every button keeps its own size, variant and disabled, and it can sit inside a wrapper such as Menu.Trigger. Square the buttons with style={{ borderRadius: 0 }} so only the outer corners stay round, and put a Separator where you want a line.

Props

PropTypeDefaultDescription
childrenReactNode—Buttons, and a Separator between them where you want a line.
orientation'horizontal' | 'vertical''horizontal'Direction of the group.
borderedbooleanfalseDraws a hairline around the group, so ghost buttons read as one outlined control.
radiusnumberbutton radiusRadius of the group’s outer corners. Defaults to components.button.radius.
styleStyleProp<ViewStyle>—Extra styles for the container. alignSelf: 'stretch' makes it fill the row.

The group hugs its content. To fill the row, stretch it with style and give the button that should grow flex: 1.

ButtonGroup only handles the shape. It doesn’t track a selection: for one choice among several, use SegmentedControl. For two spaced buttons, such as dialog actions, use a plain row: there’s nothing to clip.

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 style={{ alignSelf: "stretch" }}>
		<Button style={{ borderRadius: 0, flex: 1 }} onPress={downloadPdf}>
			Download PDF
		</Button>
		<Separator orientation="vertical" />
		<Menu.Trigger asChild>
			<IconButton
				icon="chevron-down"
				accessibilityLabel="Other formats"
				variant="solid"
				shape="square"
				style={{ borderRadius: 0 }}
			/>
		</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 bordered>
	<IconButton
		icon="minus"
		variant="ghost"
		shape="square"
		size="sm"
		accessibilityLabel="Remove one"
		style={{ borderRadius: 0 }}
		onPress={decrement}
	/>
	<Separator orientation="vertical" />
	<Button variant="ghost" size="sm" disabled style={{ borderRadius: 0 }}>
		{quantity}
	</Button>
	<Separator orientation="vertical" />
	<IconButton
		icon="plus"
		variant="ghost"
		shape="square"
		size="sm"
		accessibilityLabel="Add one"
		style={{ borderRadius: 0 }}
		onPress={increment}
	/>
</ButtonGroup>

Pill

A large radius turns the group into a pill. The buttons stay square: the group clips them.

<ButtonGroup radius={999} bordered>
	<Button variant="ghost" style={{ borderRadius: 0 }}>
		Day
	</Button>
	<Separator orientation="vertical" />
	<Button variant="ghost" style={{ borderRadius: 0 }}>
		Week
	</Button>
	<Separator orientation="vertical" />
	<Button variant="ghost" style={{ borderRadius: 0 }}>
		Month
	</Button>
</ButtonGroup>