Segmented
Segmented is a single-select group of buttons — the canonical "view switcher" control. The group is the Segmented element; each option is a SegmentedButton with an active flag on the selected one. cladd handles the active-vs-inactive styling difference via context, so individual buttons stay terse.
This page covers Segmented together with its child, SegmentedButton.
<ExampleToolbar>
<Segmented>
{VIEWS.map((v) => (
<SegmentedButton
key={v}
active={v === view}
onClick={() => setView(v)}
>
{v}
</SegmentedButton>
))}
</Segmented>
</ExampleToolbar>Usage
import { Segmented, SegmentedButton, Toolbar } from '@cladd-ui/react';
<Toolbar>
<Segmented>
<SegmentedButton active>List</SegmentedButton>
<SegmentedButton>Grid</SegmentedButton>
<SegmentedButton>Calendar</SegmentedButton>
</Segmented>
</Toolbar>;Segmented is layout only — it renders a flex row of buttons with no fill, outline, or padding of its own. Pair it with a container that supplies the visual housing; Toolbar is the canonical match (it sets size, rounded, and accent context that Segmented reads automatically).
SegmentedButton extends Button — every Button prop works on it. The only addition is active. When set, it switches the button to the surrounding Segmented's activeColor / activeVariant / activeOutline, lifts it one surface level for visual elevation, and sets readOnly so the already-selected option isn't pressable again.
Examples
Inside a container
Segmented doesn't draw a wrapper — bare, it's just three buttons floating in the parent. Wrap it in Toolbar for the standard pill-toolbar look, or inside any Surface when you want a custom shell.
<div className="flex flex-col items-center gap-2">
<span className="font-mono text-cladd-fg-softer">bare</span>
<Segmented>
<SegmentedButton active>List</SegmentedButton>
<SegmentedButton>Grid</SegmentedButton>
<SegmentedButton>Calendar</SegmentedButton>
</Segmented>
</div>
<div className="flex flex-col items-center gap-2">
<span className="font-mono text-cladd-fg-softer">
inside <Toolbar>
</span>
<ExampleToolbar>
<Segmented>
<SegmentedButton active>List</SegmentedButton>
<SegmentedButton>Grid</SegmentedButton>
<SegmentedButton>Calendar</SegmentedButton>
</Segmented>
</ExampleToolbar>
</div>
<div className="flex flex-col items-center gap-2">
<span className="font-mono text-cladd-fg-softer">
inside <Surface>
</span>
<Surface outline className="rounded-full" contentClassName="p-1">
<Segmented>
<SegmentedButton active>List</SegmentedButton>
<SegmentedButton>Grid</SegmentedButton>
<SegmentedButton>Calendar</SegmentedButton>
</Segmented>
</Surface>
</div>Inside Toolbar, Segmented reads the toolbar's size from context — so you only need to set size on the toolbar (or omit it for the md default), and the segments follow. Same goes for accent color set on the toolbar.
Sizes
size accepts the standard 2xs → 2xl scale. The value is forwarded to every child SegmentedButton through context, so individual buttons stay clean. Inside a Toolbar, you can omit size on Segmented and it'll pick up the toolbar's size instead.
<ExampleToolbar>
<Segmented size="md">
{VIEWS.map((v) => (
<SegmentedButton
key={v}
active={v === view}
onClick={() => setView(v)}
>
{v}
</SegmentedButton>
))}
</Segmented>
</ExampleToolbar>Active segment style
activeVariant, activeColor, and activeOutline control the look of the selected segment. The defaults — gradient variant with the theme accent and an outline ring — make the active option pop against the muted inactive ones. Try a solid-fill for a louder selection state, or pick a color that matches the page's accent.
<ExampleToolbar>
<Segmented activeVariant="gradient" activeColor="brand">
{VIEWS.map((v) => (
<SegmentedButton
key={v}
active={v === view}
onClick={() => setView(v)}
>
{v}
</SegmentedButton>
))}
</Segmented>
</ExampleToolbar>Inactive segment style
variant, color, and outline control the unselected segments. The default transparent variant with no outline lets inactive options fade into the parent surface — when paired with a Toolbar, only the selected segment reads as a real button. Switch to solid if you want every option to look pressable, or add outline to make inactive segments look like buttons sitting in their own slots.
<ExampleToolbar>
<Segmented variant="transparent" color="neutral" outline={false}>
{DENSITIES.map((d) => (
<SegmentedButton
key={d}
active={d === density}
onClick={() => setDensity(d)}
>
{d}
</SegmentedButton>
))}
</Segmented>
</ExampleToolbar>Rounded
rounded controls the corner shape of the segments — pill (true, default) or matching the size-specific radius. The flag is forwarded via context just like size, so each segment picks it up automatically.
<ExampleToolbar rounded>
<Segmented rounded>
{VIEWS.map((v) => (
<SegmentedButton
key={v}
active={v === view}
onClick={() => setView(v)}
>
{v}
</SegmentedButton>
))}
</Segmented>
</ExampleToolbar>Disabled
disabled dims the entire group to 40% opacity and disables pointer events. For per-segment disabling, use the Button disabled or readOnly props directly on a SegmentedButton.
<ExampleToolbar>
<Segmented disabled>
{VIEWS.map((v) => (
<SegmentedButton
key={v}
active={v === view}
onClick={() => setView(v)}
>
{v}
</SegmentedButton>
))}
</Segmented>
</ExampleToolbar>Playground
Segmented exposes two parallel sets of style props — one for active, one for inactive — plus the shared layout knobs. They compose freely; the playground below combines them all.
<ExampleToolbar rounded>
<Segmented
size="md"
activeVariant="gradient"
activeColor="brand"
variant="transparent"
color="neutral"
rounded
>
{VIEWS.map((v) => (
<SegmentedButton
key={v}
active={v === view}
onClick={() => setView(v)}
>
{v}
</SegmentedButton>
))}
</Segmented>
</ExampleToolbar>API Reference
Segmented
| Name: Type | Default | Description |
|---|---|---|
| activeColor: Color | — | Color applied to the active segment button. Default: theme accent color. |
| activeOutline: boolean | true | Outline ring on the active segment button. Default true. |
| activeVariant: SurfaceVariant | 'gradient' | Surface variant applied to the active segment button. Default 'gradient'. |
| as: ElementType | 'div' | Polymorphic root element. Defaults to 'div'. Use 'fieldset'/'ul'/etc. for semantic groupings. |
| children: ReactNode | — | Should be one or more SegmentedButton elements. |
| className: string | — | Extra classes for the segmented container. |
| color: Color | — | Accent color applied to inactive segment buttons. |
| disabled: boolean | — | Visually dim the entire group and disable pointer events. |
| outline: boolean | false | Outline ring on inactive segment buttons. Default false. |
| rounded: boolean | true | Pill-style segment buttons. Default true. Forwarded via context. |
| size: ButtonSize | 'md' | Segment button size. Default 'md'. Forwarded via context. |
| variant: SurfaceVariant | 'transparent' | Surface variant applied to inactive segment buttons through context.Default 'transparent' - inactive segments fade into the parent surface. |
SegmentedButton
| Name: Type | Default | Description |
|---|---|---|
| active: boolean | — | Marks this button as the selected segment. When true, switches to the activeColor / activeVariant / activeOutline from the surrounding Segmented, raises surfaceLevel by +2 for visual elevation, and sets readOnly so the already-selected segment is not pressable again. |