FSAI Design System
Components

Segmented Control

High-level segmented picker for choosing one option from a compact button rail.

Overview

SegmentedControl is the standard segmented choice component used across the platform for view toggles, filter modes, tab-like switches, and other mutually exclusive selections.

It wraps ButtonGroup with:

  • option mapping from a value/label array
  • optional field label
  • icon adornments, count badges, and tooltips per option
  • horizontal scroll on narrow viewports

For most segmented choice UI, prefer SegmentedControl over raw ButtonGroup. See the Button Group component page for when to drop down to the lower-level primitive.

Basic Usage

import { SegmentedControl } from '@fsai/shared-ui';

<SegmentedControl
  value={view}
  onChange={setView}
  options={[
    { label: 'Grid', value: 'grid', leftAdornment: 'Grid01' },
    { label: 'List', value: 'list', leftAdornment: 'Rows02' },
  ]}
/>

With Label And Counts

<SegmentedControl
  label="Status"
  value={status}
  onChange={setStatus}
  options={[
    { label: 'All', value: 'all', count: 24 },
    { label: 'Active', value: 'active', count: 12 },
    { label: 'Archived', value: 'archived', count: 3 },
  ]}
/>

With Tooltips

<SegmentedControl
  value={mode}
  onChange={setMode}
  options={[
    { label: 'Edit', value: 'edit', tooltip: 'Edit the live draft' },
    { label: 'Preview', value: 'preview', tooltip: 'See the published view' },
  ]}
/>

Props

PropTypeDefaultDescription
valueTCurrently selected option value.
optionsArray<SegmentedControlOption>Required. Option definitions.
onChange(value: T) => voidRequired. Called when selection changes.
labelstringOptional field label above the control.
disabledbooleanDisables all options.
size'sm' | 'md''md'Button size within the group.
fullWidthbooleanMakes the button group stretch to full width.
classNamestringAdditional classes on the outer container.
trackClassNamestringAdditional classes on the ButtonGroup.

Option Shape

PropTypeDescription
valueTRequired. Option identifier.
labelReactNodeRequired. Visible label.
leftAdornmentIconName
hideLabelboolean
countReactNode
tooltipstring

Important Conventions

  • Selection is driven by comparing option.value === value — the parent owns state.
  • On narrow viewports, the button group scrolls horizontally inside a scrollbar-hide wrapper while the label stays pinned.
  • Icon-only options should set hideLabel and provide aria-label via the label string.
  • This is not a native tab or radio group — it is a styled button rail.

Brand Dashboard And Shared Usage

PatternPathNotes
DataTable view togglefsai/packages/shared-ui/src/components/DataTable/toolbar/ViewToggle.tsxGrid/list/table view switching.
Funnel builder modefsai/apps/brand-dashboard/src/pages/FranDevPortalBuilder/components/BuilderHeader.tsxEdit/preview mode toggle.
Portal page tabsfsai/apps/applicant-portal/src/components/FranchiseePortalPageHeader/FranchiseePortalPageHeader.tsxConsumer-facing segmented navigation.
Chart metric switcherfsai/packages/shared-ui/src/modules/socials/components/SocialAnalytics/SocialAnalyticsView.tsxMetric selection in an analytics section header (see the Analytics Display pattern).

Guidelines

  • Do use SegmentedControl as the default for segmented single-choice UI
  • Do use leftAdornment icons when they help distinguish options quickly
  • Do use count badges when the counts carry meaningful signal
  • Don't use SegmentedControl for card-based visual comparison — use RadioCards
  • Don't drop to raw ButtonGroup unless you need custom button behavior

On this page