Segmented control
A short exclusive choice implemented with labelled native radios.
stable · light DOM · 4.0.0. Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.
Live variants
default
<j3w1-segmented-control id="example-segmented-control-default"><fieldset class="segmented-control radio-group radio-group-horizontal"><legend class="radio-group-legend">View density</legend><div class="segmented-control-options radio-group-options"><label class="radio-group-option"><span class="radio-group-control"><input class="radio-group-input" type="radio" name="example-segmented-control-default-density" value="compact" checked="" data-demo-focus-target=""><span class="radio-group-dot" aria-hidden="true"></span></span><span class="radio-group-text">Compact</span></label><label class="radio-group-option"><span class="radio-group-control"><input class="radio-group-input" type="radio" name="example-segmented-control-default-density" value="comfortable"><span class="radio-group-dot" aria-hidden="true"></span></span><span class="radio-group-text">Comfortable</span></label></div></fieldset></j3w1-segmented-control>Install and register
Use the exact version. If npm publication is pending, install the release tarball from the installation guide.
npm install --save-exact @j3w1/ui@4.0.0import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/segmented-control.css';
import '@j3w1/ui/register/segmented-control';Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.
Copy the complete implementation
npx --package=@j3w1/ui@4.0.0 j3w1-ui copy segmented-control --out ./vendor/j3w1/segmented-controlThe CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.
Public API
attributes
| Name | Type / signature | Meaning |
|---|---|---|
disabled | CustomEvent | Disable the native controls owned by this instance. |
loading | CustomEvent | Mark the primary control busy and prevent duplicate activation. |
properties
| Name | Type / signature | Meaning |
|---|---|---|
disabled | boolean | Delegates disabled state to native children. |
name | string | Native control name; application form keys remain explicit. |
methods
| Name | Type / signature | Meaning |
|---|---|---|
refresh | (): void | Reconnect behavior after replacing native child structure. |
focus | (options?: FocusOptions): void | Focus the first usable native control. |
events
| Name | Type / signature | Meaning |
|---|
Dependencies and verification
Registered components: none. Style dependencies: radio-group.
Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.
Full implementation manifest, API and token dependency closure
Canonical specification
Segmented control segmented-control
A short exclusive choice implemented with labelled native radios.
Report an issue with this component
Tokens
Focus a role to inspect its values; follow its link for persistent usage and source details.
| Part | Role | Value | Use |
|---|---|---|---|
root.bg | color.surface.defaultapproveduse | #0d0707 | D-041 surface.default: color.primitive.modern.panel. |
root.text | color.text.defaultapproveduse | #e99499 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
root.border | color.border.controlapproveduse | #c81a1a | D-041 owner correction: red control and floating-frame borders, distinct from rose text. |
heading.text | color.text.brightapproveduse | #ffa2a7 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
secondary.text | color.text.mutedapproveduse | #d4868b | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
control.bg | color.surface.inputapproveduse | #000000 | Form-control fill. |
control.focus | color.interaction.focus.ringobserveduse | #e53935 | 1px dashed focus ring on controls and rows. |
dependency.role-border-width-default | border.width.defaultobserveduse | 1px | Every border is 1px. |
dependency.role-border-width-emphasis | border.width.emphasisobserveduse | 2px | Selected indicator, sticky header rule, invalid border. |
dependency.role-color-action-primary-bg | color.action.primary.bgapproveduse | #7d1310 | Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12. |
dependency.role-color-action-primary-hover-bg | color.action.primary.hover-bgobserveduse | #911410 | Primary button hover; pair with action.primary.text (D-033). |
dependency.role-color-action-primary-text | color.action.primary.textapproveduse | #ffa2a7 | Primary action labels: bright rose across rest, hover and pressed states (D-033). |
dependency.role-color-border-disabled | color.border.disabledapproveduse | #482b2b | D-041 border.disabled: color.primitive.modern.divider. |
dependency.role-color-interaction-disabled-bg | color.interaction.disabled.bgapproveduse | #0d0707 | D-041 interaction.disabled.bg: color.primitive.modern.panel. |
dependency.role-color-interaction-focus-ring-container | color.interaction.focus.ring-containerobserveduse | #ffa2a7 | Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry. |
dependency.role-color-interaction-hover-bg | color.interaction.hover.bgapproveduse | #1c1010 | D-041 interaction.hover.bg: color.primitive.modern.hover. |
dependency.role-color-interaction-selection-bg | color.interaction.selection.bgapproveduse | #531310 | Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection. |
dependency.role-color-interaction-selection-text | color.interaction.selection.textobserveduse | #f4eeee | Text on the selection. |
dependency.role-color-status-danger-border | color.status.danger.borderobserveduse | #e53935 | Danger border, 2px on invalid inputs. |
dependency.role-color-status-danger-text | color.status.danger.textobserveduse | #f07178 | D-041 readable error text on neutral surfaces and native warning tints. |
dependency.role-color-text-disabled | color.text.disabledapproveduse | #a3676b | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
dependency.role-density-comfortable-control-height | density.comfortable.control-heightobserveduse | 32px | |
dependency.role-density-compact-control-height | density.compact.control-heightobserveduse | 24px | |
dependency.role-focus-offset | focus.offsetobserveduse | -2px | outline-offset for controls. |
dependency.role-focus-ring | focus.ringobserveduse | 1px dashed #e53935 | outline on controls and rows. |
dependency.role-font-line-height-ui-md | font.line-height.ui-mdobserveduse | 18px | |
dependency.role-font-line-height-ui-sm | font.line-height.ui-smobserveduse | 16px | |
dependency.role-font-size-ui-md | font.size.ui-mdobserveduse | 13px | |
dependency.role-font-size-ui-sm | font.size.ui-smobserveduse | 12px | |
dependency.role-icon-size-md | icon.size.mdobserveduse | 16px | |
dependency.role-radius-none | radius.noneobserveduse | 0px | The only radius. Nothing is rounded. |
dependency.role-space-12 | space.12observeduse | 12px | |
dependency.role-space-16 | space.16observeduse | 16px | |
dependency.role-space-24 | space.24observeduse | 24px | |
dependency.role-space-4 | space.4observeduse | 4px | |
dependency.role-space-8 | space.8observeduse | 8px |
State matrix
Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).
| State | Default |
|---|---|
default | |
checked | |
focus-visible | |
disabled |
Purpose
Changes one value from a short labelled set; for associated content panels use tabs.
Anatomy
Parts as listed in the anatomy.
States
| State | Visual | Non-colour channel |
|---|---|---|
| default | Named content on the default surface. | Native text and structure. |
| checked | Selected fill and a check indicator. | Native checked state. |
| focus-visible | Dashed focus ring. | Native keyboard focus position. |
| disabled | Disabled semantic foreground, background and border at full opacity. | Native disabled state blocks activation. |
Keyboard
As in the key table.
Accessibility
Keep native radios and labels. A checked value has both a visible native
indicator and its programmatic checked state. Never hide all radios from
assistive technology or put role=tab on the labels.
Portability
Follows the shared component defaults in spec/portability.md (section “Shared component defaults”).
Non-examples
Unlabelled controls, color-only status, drag-only operations, hidden required instructions, stolen focus or an invented service success.
Contrast report
5 declared pairs measured on resolved sRGB values with the WCAG 2.x formula; 0 waived (decorative only), 0 failing. A pass is a design target for the named role, not an application-wide conformance claim.
| Pair | State | Kind | Foreground | Background | Ratio | Min | Result |
|---|---|---|---|---|---|---|---|
| segmented-control default text | default | text | color.text.default #e99499 | color.surface.default #0d0707 | 8.72 | 4.5 | pass |
| segmented-control default border | default | ui | color.border.control #c81a1a | color.surface.default #0d0707 | 3.44 | 3 | pass |
| Primary content | — | text | color.text.default #e99499 | color.surface.default #0d0707 | 8.72 | 4.5 | pass |
| Supporting content | — | text | color.text.muted #d4868b | color.surface.default #0d0707 | 7.22 | 4.5 | pass |
| Control boundary | — | ui | color.border.control #c81a1a | color.surface.default #0d0707 | 3.44 | 3 | pass |
Keys
| Key | Action |
|---|---|
| Tab / Shift+Tab | Enter the native radio group once and leave it. |
| Arrow keys / Space | Use native radio selection and wrapping. |
For agents
Component JSON ·Implementation brief ·Build a task kit ·
Stress fixtures: FX-320 FX-360 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX