Segmented Control
A single-select control for switching between a small set of options or views.
<SegmentedControl defaultValue="account" className="w-fit"> <SegmentedControlList> <SegmentedControlItem value="account">Account</SegmentedControlItem> <SegmentedControlItem value="password">Password</SegmentedControlItem> </SegmentedControlList></SegmentedControl>Usage
import {
SegmentedControl,
SegmentedControlContent,
SegmentedControlItem,
SegmentedControlList,
} from "@reva/ui";Use defaultValue (uncontrolled) or value + onValueChange (controlled). Each SegmentedControlItem carries a unique value string.
A segmented control is a single-select control — reach for it to switch a view, mode, or filter. For labelled content panels with an underline rail, use Tabs instead. Render an optional SegmentedControlContent to show the active option's content (it animates the swap by default), or omit it and drive your own content/router from onValueChange.
Composition
Use the following composition to build a segmented control:
SegmentedControl
├── SegmentedControlList
│ ├── SegmentedControlItem
│ └── SegmentedControlItem
└── SegmentedControlContent (optional — animated; omit for control-only)Examples
With icons
Compose a Phosphor icon before the label. Mark it with data-icon="inline-start" (or inline-end) so the segment tightens its padding.
<SegmentedControl defaultValue="grid" className="w-fit"> <SegmentedControlList> <SegmentedControlItem value="grid"> <SquaresFour data-icon="inline-start" /> Grid </SegmentedControlItem> <SegmentedControlItem value="list"> <ListBullets data-icon="inline-start" /> List </SegmentedControlItem> <SegmentedControlItem value="stats"> <Gauge data-icon="inline-start" /> Stats </SegmentedControlItem> </SegmentedControlList></SegmentedControl>Animated content
Render a single SegmentedControlContent to pair the control with content that cross-slides (with blur) when the active segment changes. Direction is derived from the authored item order, and the motion respects prefers-reduced-motion. Pass animated={false} for a static pane.
Overview
Track your project progress across all active workstreams and milestones.
12
Active
84
Complete
94%
Velocity
"use client";import {SegmentedControl,SegmentedControlContent,SegmentedControlItem,SegmentedControlList,} from "@reva/ui";import { useState } from "react";export function SegmentedControlSwapDemo() {const [tab, setTab] = useState("overview");return ( <SegmentedControl value={tab} onValueChange={setTab} className="w-full max-w-xl gap-4"> <SegmentedControlList className="w-full"> <SegmentedControlItem value="overview">Overview</SegmentedControlItem> <SegmentedControlItem value="activity">Activity</SegmentedControlItem> <SegmentedControlItem value="settings">Settings</SegmentedControlItem> </SegmentedControlList> <SegmentedControlContent>{/* render content for `tab` */}</SegmentedControlContent> </SegmentedControl>);}Props
SegmentedControl is built on Radix Tabs; the root forwards Radix props.
SegmentedControl (root)
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | string | — | Initial selected segment (uncontrolled). |
value | string | — | Controlled selected segment. |
onValueChange | (value: string) => void | — | Change handler. |
SegmentedControlList
The pill track. Forwards all Radix Tabs.List props. Height is 40px, on a bg-muted track with a 3px inset.
SegmentedControlItem
| Prop | Type | Description |
|---|---|---|
value | string | Required. Unique segment value. |
SegmentedControlContent
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | — | Content for the currently active segment. |
animated | boolean | true | Cross-slide the pane on change; false renders statically. |