Segmented Control
Choose one option from a short visible set on a shared track. A raised selected segment uses the current theme surfaces. Native radio inputs supply keyboard navigation, validation, submission and reset. Supply name for behavior before upgrade. The select and change events follow Radio Group; value updates replace the selection without reporting a user edit.
One visible choice
Choose one status from a shared track. Native radio buttons supply arrow-key navigation and form submission.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-segmented-control/ui-segmented-control.html"
>
<ui-segmented-control
label="Status"
name="status"
value="active"
items="[{value: "active", label: "Active"}, {value: "archived", label: "Archived"}]"
></ui-segmented-control><script setup>
import { UiSegmentedControl } from "@threadlabs/looma";
</script>
<template>
<UiSegmentedControl
label="Status"
name="status"
value="active"
:items="[{ value: 'active', label: 'Active' }, { value: 'archived', label: 'Archived' }]"
/>
</template>import { UiSegmentedControl } from "@threadlabs/looma";
export default function Example() {
return <UiSegmentedControl
label="Status"
name="status"
value="active"
items={[{"value":"active","label":"Active"},{"value":"archived","label":"Archived"}]}
/>;
}/** @jsxImportSource preact */
import { UiSegmentedControl } from "@threadlabs/looma";
export default function Example() {
return <UiSegmentedControl
label="Status"
name="status"
value="active"
items={[{"value":"active","label":"Active"},{"value":"archived","label":"Archived"}]}
/>;
}<script>
import { UiSegmentedControl } from "@threadlabs/looma";
</script>
<UiSegmentedControl
label="Status"
name="status"
value="active"
items={[{"value":"active","label":"Active"},{"value":"archived","label":"Archived"}]}
/>import { Component } from "@angular/core";
import { UiSegmentedControl } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiSegmentedControl],
template: `
<fieldset
ui-segmented-control
[label]="'Status'"
[name]="'status'"
[value]="'active'"
[items]="[{ value: 'active', label: 'Active' }, { value: 'archived', label: 'Archived' }]"
></fieldset>
`,
})
export default class Example {}Sizes and unavailable choices
Small and large controls share field sizes. An unavailable option stays visible, while disabling the group prevents every choice.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-segmented-control/ui-segmented-control.html"
>
<ui-stack>
<ui-segmented-control
size="sm"
label="View"
name="small-view"
value="list"
items="[{value: "list", label: "List"}, {value: "grid", label: "Grid"}, {value: "board", label: "Board", disabled: true}]"
></ui-segmented-control>
<ui-segmented-control
size="lg"
label="View"
name="large-view"
value="grid"
disabled
items="[{value: "list", label: "List"}, {value: "grid", label: "Grid"}]"
></ui-segmented-control>
</ui-stack><script setup>
import { UiSegmentedControl, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack>
<UiSegmentedControl
size="sm"
label="View"
name="small-view"
value="list"
:items="[{ value: 'list', label: 'List' }, { value: 'grid', label: 'Grid' }, { value: 'board', label: 'Board', disabled: true }]"
/>
<UiSegmentedControl
size="lg"
label="View"
name="large-view"
value="grid"
:disabled="true"
:items="[{ value: 'list', label: 'List' }, { value: 'grid', label: 'Grid' }]"
/>
</UiStack>
</template>import { UiSegmentedControl, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack>
<UiSegmentedControl
size="sm"
label="View"
name="small-view"
value="list"
items={[{"value":"list","label":"List"},{"value":"grid","label":"Grid"},{"value":"board","label":"Board","disabled":true}]}
/>
<UiSegmentedControl
size="lg"
label="View"
name="large-view"
value="grid"
disabled
items={[{"value":"list","label":"List"},{"value":"grid","label":"Grid"}]}
/>
</UiStack>;
}/** @jsxImportSource preact */
import { UiSegmentedControl, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack>
<UiSegmentedControl
size="sm"
label="View"
name="small-view"
value="list"
items={[{"value":"list","label":"List"},{"value":"grid","label":"Grid"},{"value":"board","label":"Board","disabled":true}]}
/>
<UiSegmentedControl
size="lg"
label="View"
name="large-view"
value="grid"
disabled
items={[{"value":"list","label":"List"},{"value":"grid","label":"Grid"}]}
/>
</UiStack>;
}<script>
import { UiSegmentedControl, UiStack } from "@threadlabs/looma";
</script>
<UiStack>
<UiSegmentedControl
size="sm"
label="View"
name="small-view"
value="list"
items={[{"value":"list","label":"List"},{"value":"grid","label":"Grid"},{"value":"board","label":"Board","disabled":true}]}
/>
<UiSegmentedControl
size="lg"
label="View"
name="large-view"
value="grid"
disabled
items={[{"value":"list","label":"List"},{"value":"grid","label":"Grid"}]}
/>
</UiStack>import { Component } from "@angular/core";
import { UiSegmentedControl, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiSegmentedControl],
template: `
<div
ui-stack
>
<fieldset
ui-segmented-control
[size]="'sm'"
[label]="'View'"
[name]="'small-view'"
[value]="'list'"
[items]="[{ value: 'list', label: 'List' }, { value: 'grid', label: 'Grid' }, { value: 'board', label: 'Board', disabled: true }]"
></fieldset>
<fieldset
ui-segmented-control
[size]="'lg'"
[label]="'View'"
[name]="'large-view'"
[value]="'grid'"
[disabled]="true"
[items]="[{ value: 'list', label: 'List' }, { value: 'grid', label: 'Grid' }]"
></fieldset>
</div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: fieldset
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
disabled | Disable the group and exclude its value from form submission. Individually disabled choices retain their own state. | disabled | boolean | false | — |
form | Associate the native radios with this form ID. Omit it to use their containing form. | form | string | — | — |
invalid | Expose validation failure on the group and its visible boundary. | invalid | boolean | false | — |
items | A short set of mutually exclusive choices. Values must be unique; labels remain visible. | items | list(object)
| — | — |
label | The question answered by the choices, used as the group's legend and accessible name. | label | string | Options | — |
label-visibility | Hide the legend visually only when the surrounding content already names the choice. | labelVisibility | keyword | visible | visible, sr-only |
name | The native radio name used for form submission. Supply a unique name for each group so it also works before JavaScript connects. | name | string | | — |
required | Require one native radio selection for form validation. | required | boolean | false | — |
size | Match the height and type size of nearby form controls. | size | keyword | md | sm, md, lg |
value | The selected value, initially or when changed externally. A native form reset returns to this value. Empty selects none. | value | string | | — |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
disabled | boolean | false | — |
form | string | — | — |
invalid | boolean | false | — |
items | readonly ({ readonly value: string; readonly label: string; readonly disabled?: boolean | null })[]
| — | — |
label | string | Options | — |
labelVisibility | "visible" | "sr-only" | visible | visible, sr-only |
name | string | | — |
required | boolean | false | — |
size | "sm" | "md" | "lg" | md | sm, md, lg |
value | string | | — |
Events
| Name | Detail | Description |
|---|---|---|
change | object
| Emitted when a toggleable control changes checked state. |
select | object
| Emitted when a selectable option becomes active. |
Slots
No slots.
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
| Token | Declared values | Fallback |
|---|---|---|
--ui-segmented-control-border | — | var(--ui-control-border) |
--ui-segmented-control-radius | var(--ui-field-radius, var(--ui-radius-md)) | — |
--ui-segmented-control-selected-border | — | var(--ui-border) |
--ui-segmented-control-selected-surface | — | var(--ui-surface-raised) |
--ui-segmented-control-track | — | var(--ui-surface-sunken) |
Shared tokens
| Token | Fallback |
|---|---|
--ui-border | — |
--ui-border-width | — |
--ui-control-border | — |
--ui-control-size-lg | — |
--ui-control-size-md | — |
--ui-control-size-sm | — |
--ui-danger-solid | — |
--ui-disabled-border | — |
--ui-disabled-surface | — |
--ui-disabled-text | — |
--ui-field-danger | var(--ui-danger-solid) |
--ui-field-radius | var(--ui-radius-md) |
--ui-focus-ring | — |
--ui-focus-width | — |
--ui-font-medium | — |
--ui-font-size-lg | — |
--ui-font-size-md | — |
--ui-font-size-sm | — |
--ui-line-height-tight | — |
--ui-radius-md | — |
--ui-shadow-sm | — |
--ui-space-1 | — |
--ui-space-2 | — |
--ui-space-3 | — |
--ui-space-4 | — |
--ui-surface-raised | — |
--ui-surface-sunken | — |
--ui-text-primary | — |