ComponentsActions

Button Group

Joins related buttons into one control. Use it for pagers, steppers, split actions, and toolbars.

Orientation

A pager with a separator and a quantity with a text cell. Page and quantity changes stay in this example.

orientation="horizontal"Default. Joins controls left to right.

Page 1 of 3

Quantity: 0

0 items selected locally.

orientation="vertical"Stacks controls and joins them top to bottom.

Page 1 of 3

Quantity: 0

0 items selected locally.

Button sizes

The group keeps each button's height. Small sizes use the full control radius on the outer corners.

size="xs" · "icon-xs"Split share action in a dense row.
size="sm" · "icon-sm"Week stepper in a calendar header.
size="default"Text cell, value, and an icon-only default button.
Rows per page
size="icon"Square month pager in a date picker.
size="lg" · "icon-lg"Export with a format menu trigger.

No action yet.

Button variants

Outline buttons join on their borders. Filled buttons have no border, so add ButtonGroupSeparator between them.

variant="outline"Borders meet; no separator needed.
variant="secondary"A separator splits the fill.
variant="default"Primary split action.

Draft not saved.

Text cells and nested groups

ButtonGroupText can render another element, such as an output. A group of groups spaces them 8px apart.

render={<output />}Live seat count between steppers.
3 seats
ButtonGroupText + svgIcons in a text cell are 16px.
12 files
ButtonGroup > ButtonGroupCalendar toolbar.
Week 15

Usage

Button Group usageTSX
import { Button } from "@tulipfarm/sprout/button";
import {
  ButtonGroup,
  ButtonGroupSeparator,
  ButtonGroupText,
} from "@tulipfarm/sprout/button-group";

<ButtonGroup aria-label="Pages">
  <Button variant="outline" disabled={page === 1}>Previous</Button>
  <ButtonGroupSeparator />
  <Button variant="outline" disabled={page === 3}>Next</Button>
</ButtonGroup>

<ButtonGroup orientation="vertical" aria-label="Quantity">
  <ButtonGroupText>Quantity: {quantity}</ButtonGroupText>
  <Button variant="outline" aria-label="Add one"><Plus /></Button>
</ButtonGroup>

ButtonGroup renders a div with role="group". orientation is "horizontal", the default, or"vertical". Direct children with a data-slot, such as Sprõut buttons, lose their inner corners and the border where they meet. The outer corners use --sprout-radius-control for every button size.

ButtonGroupText is a muted cell for a label or value. It acceptsrender, so it can be an output or alabel. Icons inside it are 16px unless they have a size class.

ButtonGroupSeparator is a Separator with the"input" tone. It runs across the group, so it is "vertical" by default and must be "horizontal" in a vertical group. Use it between filled buttons, which have no border of their own.

A group that holds other groups spaces them 8px apart. A directinput child grows to fill the free space. buttonGroupVariants({ orientation }) returns the same class names for other elements.

Accessibility

Give each group an aria-label that names what it controls. Every button stays in the tab order, and a focused button draws its ring above its neighbors. Icon-only buttons need their own aria-label. Render a changing value with render={<output />} so screen readers hear it.

Color changes follow the theme in 120ms and stop when reduced motion is requested. In forced colors mode text cells keep a visible border.

Theme tokens

Text cells use --sprout-secondary, --sprout-text, and --sprout-input. Separators use --sprout-input. Radius follows --sprout-radius-control.