ButtonGroup

Fuses two actions into one control, a split button, with one hairline between them.

import { ButtonGroup } from "@usefragments/ui";Source

Preview

import { CaretDown } from '@phosphor-icons/react';
import { IconButton } from '@usefragments/ui';
import { Menu } from '@usefragments/ui';

<ButtonGroup aria-label="Save options">
  <Button variant="soft">Save</Button>

Usage

Use when

  • A split button: the main verb plus a menu of its variations
  • Two actions that read as one control

Avoid when

  • Spacing separate buttons: use Stack (direction="row", gap, justify="end")
  • A form footer or verb cluster: use Stack
  • Picking one option: use ToggleGroup

Implementation notes

  • At most two; a third verb goes in a Menu
  • The fused halves share one opaque hairline whatever their variant; outer corners keep the control radius
  • Give both halves the same size and variant family
  • Always name the group with aria-label or aria-labelledby

Installation

pnpm add @usefragments/ui

The npm package stays managed by your package manager. Import styles once from @usefragments/ui/styles. See the installation guide for framework and theme setup.

Examples

Verb Cluster

Separate buttons are a Stack, right-aligned, at most two.

import { Stack } from '@usefragments/ui';

<Stack direction="row" gap="sm" justify="end">
  <Button variant="soft">Cancel</Button>
  <Button>Save</Button>
</Stack>

API reference

Component props
Prop
Type
Default
Description
aria-labelstring | undefinedNot setNames the group; required unless aria-labelledby is set
aria-labelledbystring | undefinedNot setID of the element that names the group
childrenRequiredReact.ReactNodeNot setThe fused actions: a Button and an IconButton menu trigger; at most two

Accessibility

  • Renders role="group"; a dev warning fires when it has no name
  • Each half stays individually focusable
  • Name the menu trigger for what it opens ("More save options")
  • ButtonchildThe main verb of a split button
  • IconButtonchildThe menu trigger half of a split button
  • StackalternativeStack spaces separate buttons; ButtonGroup only fuses

Next steps