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
| Prop | Type | Default | Description |
|---|---|---|---|
value | T | — | Currently selected option value. |
options | Array<SegmentedControlOption> | — | Required. Option definitions. |
onChange | (value: T) => void | — | Required. Called when selection changes. |
label | string | — | Optional field label above the control. |
disabled | boolean | — | Disables all options. |
size | 'sm' | 'md' | 'md' | Button size within the group. |
fullWidth | boolean | — | Makes the button group stretch to full width. |
className | string | — | Additional classes on the outer container. |
trackClassName | string | — | Additional classes on the ButtonGroup. |
Option Shape
| Prop | Type | Description |
|---|---|---|
value | T | Required. Option identifier. |
label | ReactNode | Required. Visible label. |
leftAdornment | IconName | — |
hideLabel | boolean | — |
count | ReactNode | — |
tooltip | string | — |
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-hidewrapper while the label stays pinned. - Icon-only options should set
hideLabeland providearia-labelvia the label string. - This is not a native tab or radio group — it is a styled button rail.
Brand Dashboard And Shared Usage
| Pattern | Path | Notes |
|---|---|---|
| DataTable view toggle | fsai/packages/shared-ui/src/components/DataTable/toolbar/ViewToggle.tsx | Grid/list/table view switching. |
| Funnel builder mode | fsai/apps/brand-dashboard/src/pages/FranDevPortalBuilder/components/BuilderHeader.tsx | Edit/preview mode toggle. |
| Portal page tabs | fsai/apps/applicant-portal/src/components/FranchiseePortalPageHeader/FranchiseePortalPageHeader.tsx | Consumer-facing segmented navigation. |
| Chart metric switcher | fsai/packages/shared-ui/src/modules/socials/components/SocialAnalytics/SocialAnalyticsView.tsx | Metric selection in an analytics section header (see the Analytics Display pattern). |
Guidelines
- Do use
SegmentedControlas the default for segmented single-choice UI - Do use
leftAdornmenticons when they help distinguish options quickly - Do use count badges when the counts carry meaningful signal
- Don't use
SegmentedControlfor card-based visual comparison — useRadioCards - Don't drop to raw
ButtonGroupunless you need custom button behavior