FSAI Design System
Components

Button Group

Segmented button rail for mutually exclusive or grouped compact actions.

Overview

ButtonGroup is the low-level segmented button rail used to present a compact group of related button choices.

It exposes:

  • ButtonGroup
  • ButtonGroup.Button

In practice, most feature code should first consider SegmentedControl, which already wraps ButtonGroup for the common “pick one option” case.

Use raw ButtonGroup when you need the segmented visual treatment but want direct control over button markup and behavior.

Basic Usage

<ButtonGroup>
  <ButtonGroup.Button isActive={view === 'grid'} onClick={() => setView('grid')}>
    Grid
  </ButtonGroup.Button>
  <ButtonGroup.Button isActive={view === 'list'} onClick={() => setView('list')}>
    List
  </ButtonGroup.Button>
</ButtonGroup>

With Icons

<ButtonGroup>
  <ButtonGroup.Button
    leftAdornment="Rows02"
    isActive={density === 'comfortable'}
    onClick={() => setDensity('comfortable')}
  >
    Comfortable
  </ButtonGroup.Button>
  <ButtonGroup.Button
    leftAdornment="Rows03"
    isActive={density === 'compact'}
    onClick={() => setDensity('compact')}
  >
    Compact
  </ButtonGroup.Button>
</ButtonGroup>

Props

ButtonGroup

PropTypeDescription
childrenReactNodeRequired. Grouped buttons.

ButtonGroup.Button

PropTypeDefaultDescription
childrenReactNodeButton label/content.
leftAdornmentIconNameOptional left icon.
rightAdornmentIconNameOptional right icon.
isActivebooleanMarks the button as active.
size'md' | 'sm' | 'xs''md'Button size.
...buttonPropsButtonHTMLAttributes<HTMLButtonElement>Standard button props such as onClick, disabled, and aria-label.

Relationship To SegmentedControl

SegmentedControl is the higher-level, more common API for segmented choice UI.

Use SegmentedControl when:

  • the control is just choosing one option from a list
  • you want built-in label support and option mapping

Use raw ButtonGroup when:

  • you need custom button contents
  • the grouped buttons are not just a simple value-picker
  • you want direct control over button behavior

Important Cautions

  • ButtonGroup is a visual grouping primitive, not a DOM radio group.
  • Selection semantics are driven by isActive and your own click handlers.
  • Accessibility responsibilities such as aria-label or pressed/selection semantics still belong to the caller.

Shared Usage

PatternPathNotes
Segmented control foundationfsai/packages/shared-ui/src/components/SegmentedControl/SegmentedControl.tsxCanonical wrapper around ButtonGroup for ordinary segmented selection.

Guidelines

  • Do use SegmentedControl first for ordinary segmented choice UI
  • Do use ButtonGroup directly when you need custom segmented button behavior
  • Do drive the active state explicitly with isActive
  • Don't assume ButtonGroup gives you radio-group semantics for free

On this page