Install
Pull Button Group from the barrel for everyday use, or the granular path when you want a tighter bundle.
import { ButtonGroup } from "@brika/clay";import { ButtonGroup } from "@brika/clay/components/button-group";A minimal example
Drop this into a page. Native HTML attributes pass through to the underlying primitive.
import { Button } from '@brika/clay/components/button';
import { ButtonGroup } from '@brika/clay/components/button-group';
/** Three related action buttons joined in a shared frame, each click fires once, no selection state. */
export default function ButtonGroupDefaultDemo() {
return (
<ButtonGroup>
<Button variant="outline">Reply</Button>
<Button variant="outline">Reply all</Button>
<Button variant="outline">Forward</Button>
</ButtonGroup>
);
}Button Group, every way
Filled
Filled default variant inside a group, good for primary action clusters.
Icons
Icon-only action buttons for a compact toolbar, every button needs an `aria-label`.
Split Button
Primary action plus a dropdown chevron for related variants.
Vertical
Vertical orientation stacks buttons top-to-bottom with shared dividers.
With Input
Input + trailing button, classic copy-URL pattern.
Accessibility
- The wrapper carries
role="group", addaria-labelwhen the group's purpose is not clear from context. - Each button inside the group keeps its individual focus ring and keyboard behavior.
- Icon-only buttons inside the group still require
aria-label.
Theme tokens
Every CSS variable Button Group reads, with its default and the
dotted path you'd write in a ThemeConfig JSON
to override it. Set any of these in your theme to retune Button Group
without touching component code.
Button Group tokens
4 tokens--button-group-frame-containercolorvar(--input-container)components.buttonGroup.frameContainerBackground fill of the button-group frame. Defaults to the `--input-container` role so a group reads as a single grouped control matching other inputs.
--button-group-frame-bordercolorvar(--input-border)components.buttonGroup.frameBorderBorder color of the button-group outer frame. Defaults to the `--input-border` role so the frame matches other input edges.
--button-group-divider-colorcolorvar(--input-border)components.buttonGroup.dividerColorColor of the 1px separator drawn between adjacent buttons in the group, and of the explicit `ButtonGroupSeparator` bar. Defaults to `--input-border` so dividers blend with the frame.
--button-group-text-colorcolorvar(--muted-foreground)components.buttonGroup.textColorForeground color of the inline `ButtonGroupText` label slot. Defaults to the muted-foreground role so plain text inside a group reads as supporting content.
Override in a theme
Authoring a theme is plain JSON. Drop overrides under
components.buttonGroup, the names
are camelCase versions of the variable suffix.
{
"id": "my-theme",
"name": "My Theme",
"description": "...",
"accentSwatches": ["#000"],
"components": {
"buttonGroup": {
"frameContainer": "var(--input-container)"
}
}
}
Then apply with applyTheme(myTheme)
(see the theming guide),
scope it to a subtree with themeToCssVars(myTheme, mode),
or consume any token directly in your own JSX with the matching Tailwind utility
(e.g. bg-button-group-…) — see the
chips on each token row.
API reference
Props specific to Button Group. Native HTML attributes pass through to the underlying primitive, see the component source on GitHub for the full type signature.
<ButtonGroup />
1 prop- 'horizontal' | 'vertical'Lay buttons out horizontally or vertically.
<ButtonGroupSeparator />
passthroughNo wrapper-specific props, all attributes pass through to the underlying primitive.
<ButtonGroupText />
1 prop- asChilddefault
falsebooleanWhen true, render the child element instead of the default DOM node and merge props. Lets you compose with<a>,<Link>, or another primitive while keeping behavior and styling.