Source-owned primitivesProtocol / 0.1.0

Button Group

Button Group arranges closely related controls into one horizontal or vertical unit. Connected borders make the relationship visible while each button keeps its own action.

Use a group for actions that operate on the same object or represent one compact tool set. Unrelated primary actions should remain separate.

Live previewInteractive / Local
Release 24

Installation

Sourcebash
pnpm dlx shadcn@latest add http://ui.argv-tech.dev/r/button-group.json

Usage

Sourcetsx
import {
    ButtonGroup,
    ButtonGroupButton
} from "@/components/ui/argv/button-group"

<ButtonGroup aria-label="Editor actions">
    <ButtonGroupButton variant="outline">Save</ButtonGroupButton>
    <ButtonGroupButton>Publish</ButtonGroupButton>
</ButtonGroup>

Composition

Sourcetext
ButtonGroup
├── ButtonGroupText (optional)
├── ButtonGroupButton
├── ButtonGroupSeparator (optional)
└── ButtonGroupButton

Set orientation="horizontal" for a row or orientation="vertical" for a stack. The root renders role="group" and forwards native div props.

ButtonGroupButton renders the argv Button directly and forwards its variants, sizes, render prop, refs, events, and accessibility attributes. Use it for the standard group API; an existing Button may still be used directly as a child.

Use ButtonGroupText for a short readout or label that belongs inside the connected surface. Use ButtonGroupSeparator only when a visible boundary helps distinguish subsets of controls.

Match the separator to the boundary: vertical separators belong in horizontal groups, while horizontal separators belong in vertical groups.

Interaction states

Grouped buttons remove the leading rails and triangular corner cuts that disrupt the connected silhouette. They keep the Button's small signature details: clipped scan passes, telemetry ticks, and fine corner marks.

Hover affects only the actionable segment under the pointer while the group keeps one shared outer shadow. The active segment stays stationary and uses a two-pixel foreground inset ring for contained press feedback.

The interaction stack is deterministic: children rise in DOM order, while hover, active, and focus occupy successively higher layer bands. This prevents a separator or neighboring segment from cutting through the current effect.

Keyboard focus uses a high-contrast neutral inset ring, so it remains visible on outline, filled, and destructive buttons without changing the group's footprint. Invalid focus uses the destructive color. Disabled segments remain fully opaque, switch to the muted gray palette, and do not trigger hover or active feedback.

API Reference

ButtonGroup

PropTypeDefault
orientation"horizontal" | "vertical""horizontal"
classNamestring-

ButtonGroupText

PropTypeDefault
renderReactElement | functiondiv
classNamestring-

ButtonGroupButton

ButtonGroupButton accepts the same props as Button, including variant, size, render, and disabled.

ButtonGroupSeparator

PropTypeDefault
orientation"horizontal" | "vertical""vertical"
classNamestring-

Accessibility

Give every group an accessible name with aria-label or aria-labelledby. The label should describe what the controls affect, such as “Release actions.”

Each button still needs a clear individual name. Grouping controls does not replace the accessible label of an icon-only button.