General · astro-ui · ButtonGroup

ButtonGroup

Zero-JS container that visually groups buttons by merging borders and rounding outer corners only.

ButtonGroup is a zero-JS layout container that visually groups buttons or other inline interactive elements by merging their borders and rounding only the outer corners. Children remain fully independent — the group is purely presentational. Horizontal and vertical orientations, plus proper focus/hover z-index handling, make it the foundation for toolbars, pagination controls, and segmented button sets.

Features

  • Horizontal and vertical orientations
  • Automatic border merging between adjacent children
  • Only outer corners remain rounded
  • Focus states elevated via z-index for full border visibility
  • role="group" or role="toolbar" for semantic grouping
  • Works with buttons, links, inputs, and other inline interactive elements
  • ButtonGroupText for non-button content (counts, labels, badges)
  • ButtonGroupSeparator for visual dividers between sections
  • Zero JavaScript — pure CSS visual grouping

Usage

---
import { Button, ButtonGroup } from "astro-ui";
---

<ButtonGroup>
  <Button variant="outline">Previous</Button>
  <Button variant="outline">Next</Button>
</ButtonGroup>

<ButtonGroup orientation="vertical">
  <Button variant="outline">Copy</Button>
  <Button variant="outline">Paste</Button>
  <Button variant="outline">Delete</Button>
</ButtonGroup>

Demos

Basic

<ButtonGroup>
  <Button variant="outline">Previous</Button>
  <Button variant="outline">Next</Button>
</ButtonGroup>

Vertical

<ButtonGroup orientation="vertical">
  <Button variant="outline">Copy</Button>
  <Button variant="outline">Paste</Button>
  <Button variant="outline">Delete</Button>
</ButtonGroup>

Variants

<ButtonGroup>
  <Button>Primary</Button>
  <Button variant="secondary">Secondary</Button>
</ButtonGroup>
<ButtonGroup>
  <Button variant="outline">Edit</Button>
  <Button variant="outline">Delete</Button>
</ButtonGroup>

Icons

<ButtonGroup ariaLabel="Text alignment">
  <Button variant="outline" size="icon" ariaLabel="Left">⇤</Button>
  <Button variant="outline" size="icon" ariaLabel="Center">↔</Button>
  <Button variant="outline" size="icon" ariaLabel="Right">⇥</Button>
</ButtonGroup>

With separator

<ButtonGroup>
  <Button variant="outline">Filter</Button>
  <Button variant="outline">Sort</Button>
  <ButtonGroupSeparator />
  <Button variant="outline">More</Button>
</ButtonGroup>

With text

2.4k
<ButtonGroup>
  <Button variant="outline">Star</Button>
  <ButtonGroupText>2.4k</ButtonGroupText>
</ButtonGroup>

API

Props

PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"Layout direction.
role"group" | "toolbar""group"Semantic ARIA role for the container.
classstring—Merged via cn(); Tailwind classes welcome.
idstring—Element id.
ariaLabelstring—Accessible name.

Slots

SlotDescription
defaultButton components or other inline interactive elements.

Accessibility

Implemented accessibility features — semantics, ARIA wiring, and keyboard behavior that ship with the component.

  • Grouped buttons share one aria-label-named group
  • Roving :focus-visible ring keeps focus clear across joined controls

FAQ

What elements can I put inside?

Any inline interactive elements work — Button, links with Button styles, even native <button> elements. The styles target direct children and merge their borders.

Do buttons need special props?

No — ButtonGroup is purely presentational. It adjusts borders and radii via CSS; buttons remain fully functional with zero changes.

Can I nest ButtonGroups?

Yes — vertical groups can contain horizontal groups (or vice versa) for complex toolbars. Each group independently manages its children's borders.

How does focus styling work?

Focused and hovered children get position: relative with elevated z-index, so their full border appears above siblings. This prevents border clipping.

Changelog

Version history mentioning ButtonGroup.

v0.1.0 — 2026-11-11
added
  • General (7): Button, ButtonGroup, Command, Carousel, Clipboard, Kbd, Link.