What is Segmented control?
Segmented control: A segmented control is a row of two to five connected buttons where exactly one is selected, used to switch a view, a mode or a value in place.
A segmented control shows every option side by side in one track and highlights the selected one, so the choice and its alternatives are visible at a glance. It comes from iOS, where it switches between views like List and Map, and it is now common on the web for billing periods (Monthly or Yearly), chart ranges (1D, 1W, 1M), density settings and view modes. It is a radio group with a different look, and it should behave like one.
When to use it
- Two to five short options that fit on one line. Beyond that, labels get truncated and the control stops reading as one unit; use tabs, a select or a radio group.
- Immediate effect. Changing the segment changes the view or the value right away, with no Apply button.
- One choice at a time. For several independent on and off states, use a toggle group with multiple selection.
- Not for navigation between pages or for switching large panels of content; those are tabs, and page navigation should be links.
Accessibility
Because exactly one option is selected, the right semantics are a radio group: the container has role="radiogroup" with an aria-label, and each segment is a button with role="radio" and aria-checked. Keyboard behavior follows the radio pattern with a roving tabindex: one Tab stop for the whole control, Left and Right Arrow move the selection, Home and End jump to the ends. Arrow keys select as they move, so there is no separate Enter step.
The selected state must not rely on color alone. A raised thumb, a bolder label or a filled background all work together. Every segment needs a target of at least 24 by 24 CSS pixels, and the control needs a visible focus ring on the focused segment, not just on the track.
How to build one in React
MiniDev's SegmentedControl renders the radio group with roving focus, arrow key handling and a raised thumb that glides to the selected segment on a spring, standing still under prefers-reduced-motion:
"use client"
import * as React from "react"
import { SegmentedControl } from "@/components/ui/segmented-control"
export function BillingPeriod() {
const [period, setPeriod] = React.useState("monthly")
return (
<SegmentedControl
aria-label="Billing period"
options={[
{ value: "monthly", label: "Monthly" },
{ value: "yearly", label: "Yearly", badge: "-20%" },
]}
value={period}
onChange={setPeriod}
/>
)
}
The items shorthand takes plain strings when values and labels are the same, size offers three heights and fullWidth stretches the segments evenly across a container. Pair it with a pricing toggle, or put it in a data table toolbar to switch views. Find related controls in the forms category.