Primitive / Moleculebeta
Button Group
Merges adjacent buttons into one segmented control with shared borders.
pnpm dlx @glinui/cli@latest add button-groupInstallation
Install from
pnpm dlx @glinui/cli@latest add button-groupPrefer the package?
Usage
Variants
import { Button, ButtonGroup } from "@glinui/ui"
export function Demo() { return ( <div className="grid gap-3"> <ButtonGroup variant="glinr" aria-label="Glinr"><Button>One</Button><Button>Two</Button></ButtonGroup> <ButtonGroup variant="solid" aria-label="Solid"><Button>One</Button><Button>Two</Button></ButtonGroup> <ButtonGroup variant="plain" aria-label="Plain"><Button>One</Button><Button>Two</Button></ButtonGroup> <ButtonGroup variant="outline" aria-label="Outline"><Button>One</Button><Button>Two</Button></ButtonGroup> </div> )}Glass (opt-in)
import { Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText } from "@glinui/ui"
// Glass needs a colorful or photographic backdrop to read.export function Demo() { return ( <ButtonGroup variant="glass" aria-label="Zoom"> <Button>-</Button> <ButtonGroupText>100%</ButtonGroupText> <ButtonGroupSeparator /> <Button>+</Button> </ButtonGroup> )}Quantity stepper
Icon buttons around a live value make a compact stepper.
"use client"
import { useState } from "react"import { Minus, Plus } from "@phosphor-icons/react"import { Button, ButtonGroup } from "@glinui/ui"
export function ToggleStepper() { const [qty, setQty] = useState(2) return ( <ButtonGroup aria-label="Quantity" variant="outline"> <Button size="icon" aria-label="Decrease quantity" onClick={() => setQty((value) => Math.max(1, value - 1))}> <Minus weight="bold" /> </Button> <Button aria-live="polite" tabIndex={-1} className="min-w-12 tabular-nums">{qty}</Button> <Button size="icon" aria-label="Increase quantity" onClick={() => setQty((value) => value + 1)}> <Plus weight="bold" /> </Button> </ButtonGroup> )}Accessibility
- Renders `role="group"`; give it an `aria-label` describing the set.
- Each child keeps its own button semantics and focus ring (raised above neighbours).
Keyboard Interactions
| Key | Action |
|---|---|
| Tab | Move through each button in order. |
ARIA Attributes
- `role="group"` with `aria-label`
- `role="separator"` on ButtonGroupSeparator
Reduced Motion
Hover lift and press scale are disabled inside the group so merged edges stay aligned.
Affected properties
transformAPI Reference
ButtonGroup
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
orientation | "horizontal" | "vertical" | No | horizontal | Layout direction. Adjacent buttons share borders; only outer ends are rounded. |
variant | "default" | "glass" | "glinr" | "solid" | "plain" | "soft" | "outline" | "ghost" | "gradient" | No | default | Look shared with every child Button that does not set its own. Glass also adds a blurred container and needs a backdrop. |
tone | SurfaceTone | No | - | Tone shared with child Buttons. |
size | ButtonGroupContextValue["size"] | No | - | Size shared with child Buttons. |
ButtonGroupText
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
asChild | boolean | - | false | Render as the child element, for example a label. |
orientation | "horizontal" | "vertical" | No | "vertical" | Variant option from buttonGroupVariants. |
size | ButtonGroupContextValue["size"] | No | - | Size applied to child Buttons that do not set their own. |
tone | SurfaceTone | No | - | Tone applied to child Buttons that do not set their own. |
variant | "default" | "glass" | "glinr" | "solid" | "plain" | "soft" | "outline" | "ghost" | "gradient" | No | "default" | Variant option from buttonGroupVariants. |
ButtonGroupSeparator
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
orientation | "horizontal" | "vertical" | No | vertical | Divider direction. |
size | ButtonGroupContextValue["size"] | No | - | Size applied to child Buttons that do not set their own. |
tone | SurfaceTone | No | - | Tone applied to child Buttons that do not set their own. |
variant | "default" | "glass" | "glinr" | "solid" | "plain" | "soft" | "outline" | "ghost" | "gradient" | No | "default" | Variant option from buttonGroupVariants. |
Source
Import directly from the package or browse the source on GitHub. Click any file to view it.
Import
import { ButtonGroup } from "@glinui/ui"Source Files
Dependencies
@glinui/ui@radix-ui/react-slotclass-variance-authorityGenerated API Snapshot
Beta
Generated API Snapshot
BetaAuto-extracted from TypeScript source in packages/ui/src/components/button-group.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.
Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata
Primary Props Type
ButtonGroupProps
ButtonGroupProps
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
orientation | "horizontal" | "vertical" | No | "vertical" | Variant option from buttonGroupVariants. |
size | ButtonGroupContextValue["size"] | No | - | Size applied to child Buttons that do not set their own. |
tone | SurfaceTone | No | - | Tone applied to child Buttons that do not set their own. |
variant | "default" | "glass" | "glinr" | "solid" | "plain" | "soft" | "outline" | "ghost" | "gradient" | No | "default" | Variant option from buttonGroupVariants. |
ButtonGroupTextProps
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
asChild | boolean | No | false | - |