AppSegmented
Two to four mutually-exclusive options shown side by side, all visible at once.
<app-segmented label="Theme" value="dark"><app-segmented-option … /></app-segmented><app-segmented> shows a small set of exclusive choices with all of them visible — a theme switch, a date-range toggle above a chart, a list/grid view switch. Unlike a select, the reader sees every option without opening anything.
It is built on real <input type="radio"> elements inside labels. That is not an implementation detail: arrow-key navigation, the single tab stop for the whole group, and the “2 of 3 selected” screen-reader announcement all come from the browser — and because there is no JavaScript involved, the control posts inside a plain form.
Playground
Every attribute, live. Combine them freely — the generated call underneath is the exact call that produced the control above it. The selected value comes from clicking the preview itself, same as a real screen.
options control here picks between four preset children sets (plain, icons, notes, one option disabled) — in real code that's just the <app-segmented-option> children you author, not something a user ever changes at runtime.Basic
Options as children, value for the selected one, and name for the field it posts as. label is the group's accessible name — required, because a bare row of pills tells a screen reader nothing about what is being chosen.
Show code
<app-segmented label="Date range" name="range" value="30d">
<app-segmented-option value="7d" label="7 days" />
<app-segmented-option value="30d" label="30 days" />
<app-segmented-option value="90d" label="90 days" />
</app-segmented>
<form> post with nothing wired up. Give it a name and read the value on the server like any other field.With icons
An icon speeds recognition for a familiar concept — a sun for light, a moon for dark. It sits beside the label, never replacing it.
Show code
<app-segmented-option value="light" label="Light" icon="sun" /> <app-segmented-option value="dark" label="Dark" icon="moon" />
With a note
An option can carry a note — a smaller, muted sub-line under the label for a supporting detail. Segments without one keep the plain single-line layout.
Show code
<app-segmented-option value="7d" label="7 days" note="Last week" /> <app-segmented-option value="30d" label="30 days" note="Last month" />
Sizes
size takes sm, lg or xl (md is the default). sm tightens the padding for a card header or table toolbar; lg and xl give a more prominent toggle, xl for a hero or settings screen.
Show code
<app-segmented size="sm" label="Date range" name="range" value="30d">…</app-segmented> <app-segmented label="Date range" name="range" value="30d">…</app-segmented> <app-segmented size="lg" label="Date range" name="range" value="30d">…</app-segmented> <app-segmented size="xl" label="Date range" name="range" value="30d">…</app-segmented>
Full width
Set full-width to make the segments share the row equally and fill the container — for a toggle spanning a card or a form section.
Show code
<app-segmented full-width="true" label="View" name="view" value="list">…</app-segmented>
Without the ring
The selected option is an outlined pill by default. Set bordered="false" to drop the ring and keep only the faint tint and the primary label, for a quieter control in a dense toolbar.
Show code
<app-segmented bordered="false" label="Range" name="range" value="30d">…</app-segmented>
Disabled
Disable the whole control with disabled, or keep a single option visible but unpickable with the option's disabled.
Show code
<app-segmented disabled="true" label="View" name="view" value="7d">…</app-segmented> <app-segmented-option value="map" label="Map" disabled="true" />
When to use
Use it when
- Two to four exclusive options, and seeing all of them helps the reader choose.
- The choice changes a view — a range, a mode, a theme.
- The options are short words that fit on one row.
Reach for something else when
- There are five or more options. → app-select
- It is a single on/off setting. → app-switch
- Several can be on at once. → app-checkbox / app-choice-chip
- The options need descriptions. → app-radio / app-choice-card
Best practices
Every option
The whole surface of the component, one cell per value — sizes, icon and note variants, the disabled states, full width, and the edge cases a normal example never shows.
size — sm · md · lg · xl
size="sm"
size="md"
size="lg"
size="xl"
icon + label items
icon="sun" / "moon" / "gauge"
note — under every label
app-segmented-option note
disabled — whole control vs. a single option
disabled="true" — whole control
app-segmented-option disabled="true" — one option
block / full width
full-width="true" — segments share the row equally
edge cases
options — minimum (2)
value matches no option — nothing checked
no app-segmented-option children — empty group
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| label * | string | — | Accessible name for the group. Without it a screen reader announces unrelated radios. |
| value | string | — | The selected option's value. |
| name | string | generated | What groups the radios and what the value posts as. |
| size | sm | md | lg | xl | md | sm for a card header/toolbar; lg or xl for a more prominent toggle. |
| full-width | bool | false | Segments share the row equally and fill the container. |
| bordered | bool | true | Draws the primary ring on the selected option. false keeps only the tint and the primary label. |
| disabled | bool | false | Disables the whole control. A single option: <app-segmented-option disabled="true">. |
<app-segmented-option> takes value, label, and optional icon, note, and disabled attributes (React option icon / note / disabled) — note renders a smaller, muted sub-line under the label; disabled keeps that one option visible but unpickable.