# ButtonGroup

> Joins adjacent Buttons into a single control, collapsing the inner corners and overlapping borders.

URL: https://apogee.avaui.dev/docs/button-group
Last updated: 2026-10-15

Joins adjacent Buttons into a single control, collapsing the inner corners and overlapping borders.

Last updated October 15, 2026

```astro
<ButtonGroup label="View">
<Button variant="outline" color="neutral">Day</Button>
<Button variant="outline" color="neutral">Week</Button>
<Button variant="outline" color="neutral">Month</Button>
</ButtonGroup>
```

## Add

```sh
npx @ava-ui/apogee add button-group
```

No Apogee dependencies of its own — it’s a layout wrapper. Designed to compose with `Button` (add that separately: `npx @ava-ui/apogee add button`).

## Usage

```astro
---
import ButtonGroup from '@/components/apogee/ButtonGroup/ButtonGroup.astro'
import Button from '@/components/apogee/Button/Button.astro'
---
<ButtonGroup label="Alignment">
  <Button variant="outline" color="neutral">Left</Button>
  <Button variant="outline" color="neutral">Center</Button>
  <Button variant="outline" color="neutral">Right</Button>
</ButtonGroup>
```

## API

`@composable` — exposed to Content Editors in AVA. Any other native `<div>` attribute passes through.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | — | Accessible label for the group (sets `aria-label` on the `role="group"` root). |
| `disabled` | `boolean` | `false` | Disables every button inside. The root is a `<fieldset>`, so this is native and needs no JS. |
| `class` | `string` | — | Extra classes, merged last. |

ButtonGroup applies no visual style to itself beyond the join — it targets its direct children (`[&>*:not(:first-child)]` / `[&>*:not(:last-child)]`) to overlap borders and drop the inner corner radius. It reads no color tokens of its own; those come from whatever’s composed inside (see Button’s Tokens).

## States

Hover, focus and active belong to the composed Buttons. A focused item lifts above its overlapping neighbour so its whole outline shows. `disabled` on the group disables every button at once.

```astro
<ButtonGroup label="Alignment">
<Button variant="outline" color="neutral">Left</Button>
<Button variant="outline" color="neutral">Center</Button>
<Button variant="outline" color="neutral">Right</Button>
</ButtonGroup>
<ButtonGroup label="Alignment" disabled>
<Button variant="outline" color="neutral">Left</Button>
<Button variant="outline" color="neutral">Center</Button>
<Button variant="outline" color="neutral">Right</Button>
</ButtonGroup>
```

## Examples

Mixed content — a group works with any adjacent controls, not only `Button`:

```astro
<ButtonGroup label="Zoom">
<Button variant="outline" color="neutral" iconOnly aria-label="Zoom out">−</Button>
<Button variant="outline" color="neutral" iconOnly aria-label="Zoom in">+</Button>
</ButtonGroup>
```

## Accessibility

-   Renders `role="group"` with `aria-label` (from the `label` prop) so screen readers announce it as a set, not stray buttons.
-   Always pass `label` — without it the group has no accessible name.
-   **Keyboard** — unchanged from the composed children: `Tab` moves through each button in order (no roving tabindex; this isn’t a `radiogroup` or `tablist`).

## Tokens

None of its own. Borders, backgrounds, and focus rings come from the composed components (typically Button — see its Tokens table).

## Do / Don’t

-   **Do** use it for a small set of related, mutually exclusive or peer actions (view toggles, pagination arrows).
-   **Do** always pass `label`.
-   **Don’t** mix more than one `variant` inside a group — it reads as one control, so its buttons should look uniform.
-   **Don’t** use it for unrelated actions that happen to sit next to each other — use plain spacing instead.

## Content

-   Labels follow Button’s content rules (short, verb-led where the action is a command; nouns for a view/filter toggle).

## Related

[

ButtonTriggers an action. Renders a <button>, or an <a> when href is set. Hue, fill and height are three separate props.

](https://apogee.avaui.dev/docs/button)[

ToggleButtonGroupConnects ToggleButtons into a segmented bar — single-select or multi-select.

](https://apogee.avaui.dev/docs/toggle-button-group)[

SegmentedControlA row of connected, mutually exclusive options backed by native radios — pick one from a small, always-visible set.

](https://apogee.avaui.dev/docs/segmented-control)
