Components
Segmented Filter
The filter the shelf screens share: a row of segments on one plate, exactly one of them in force. A segmented control rather than a strip of words, because the plate is what says which alternative you are in — a bare strip leaves that to a colour change alone.
Usage
Radix's single-select toggle group underneath, which gives roving focus and
radio semantics for free. label is the accessible name — what it is these
segments filter.
import { SegmentedFilter } from "@/components/base/segmented-filter";
<SegmentedFilter
label="Lists"
value={value}
onChange={setValue}
segments={[
{ value: "all", label: "All", count: 12 },
{ value: "published", label: "Published", count: 9 },
{ value: "drafts", label: "Drafts", count: 3 },
{ value: "archived", label: "Archived", count: null },
]}
/>Counts
The count is what makes the control worth reading before you click it — “3
drafts” answers the question that brought you here. Pass null while a number
is not known yet: the segment keeps its place and simply carries no count
until it is.
Behaviour
Radix's one unwanted behaviour is deselection — clicking the active segment clears the value — so an empty change is ignored, and callers pass an explicit “All” segment rather than modelling it as the absence of one. The row scrolls rather than wraps: twelve categories on a phone would otherwise stack three rows deep and push the shelf itself off the screen.