{#snippet boldIcon()} {/snippet}
Controls · Toggle

Toggle

Two-state button (pressed / unpressed) — single APG button pattern, form-integrable via name + value, three variants (solid / outline / ghost), doctrinal intent (neutral | affirm | risk | threat), single commit-toggle sema event with sequence: 'post'.

parts{compiled.parts.order.length} events{events.length} variants3 intents4 apg button ↗
{labelText}
trace {#if trace.length === 0} click toggle to see commit-toggle event {:else} {#each trace.slice(0, 3) as entry} {entry.event} · {entry.family}{entry.intent ? ' · ' + entry.intent : ''} {fmtTime(entry.at)} {/each} {/if} state {pressed ? 'on' : 'off'}
{#if lastFormSubmit !== null}
FormData {JSON.stringify(lastFormSubmit)}
{/if}
{#if tab === 'live'}

Controls

Props grouped by layer: soma headless behavior, eidos visual treatment. Sema events live in the { e.preventDefault(); tab = 'sema'; }}>Sema tab.

soma props · headless behavior
eidos props · visual treatment
Demo content · literal label text
soma headless · ARIA + behavior only svelte
{somaSnippet}
eidos visual · adds variant, size, block, iconOnly, icon, checkMark svelte
{eidosSnippet}
{/if} {#if tab === 'api'}

API reference

Single-part component — <Toggle> IS the button. All props live on one component.

PropTypeDefaultDescription
pressed bindablebooleanfalseWhether the toggle is pressed.
onPressedChange(pressed: boolean) => void—Press change callback.
disabled / readonly / required / invalidbooleanfalseField-integration flags.
intent'neutral' | 'affirm' | 'risk' | 'threat''neutral'Doctrinal intent of the consequence. Drives sema sound + color.
color'primary' | 'secondary'—Hierarchical accent. Only applies when intent='neutral'.
name / valuestring— / 'on'Form field. Hidden input renders only while pressed.
aria-labelstring—Override accessible name when children isn't sufficient.
variant eidos'solid' | 'outline' | 'ghost''solid'Visual treatment.
size eidos'sm' | 'md' | 'lg''md'Padding + font preset.
block eidosbooleanfalseStretch to fill inline-size.
iconOnly eidosbooleanfalseSquare aspect, padding-inline reduced.
icon eidosSnippet<{`{pressed}`}>—Icon snippet rendered before children.
checkMark eidosboolean | SnippetfalseShow check mark when pressed.
{/if} {#if tab === 'morfo'}

morfo · declarative contract

Source: src/uix/morfo/components/toggle.ts. Single-part — Provider IS the button.

FieldValue
name"{toggleMorfo.name}"
kebab"{toggleMorfo.kebab}"
scope[{toggleMorfo.scope.map((s) => `"${s}"`).join(', ')}]
apg{toggleMorfo.apg}
parts.length{toggleMorfo.parts.length}
events.length{toggleMorfo.events?.length ?? 0}
Parts
{#each partsList as part} {/each}
PartMarkerElementRoleArchetypeStates
{part.kebab} [{part.marker}] <{part.defaultElement}> {part.role ?? '—'} {part.archetype ?? '—'} {part.states.length ? part.states.join(' | ') : '—'}
{#each toggleMorfo.parts as rawPart} {@const partAny = rawPart as unknown as { kebab: string; aria?: ReadonlyArray<{ attr: string; value: { kind: string }; condition?: { when: string; prop?: string }; severity?: string }>; keyboard?: ReadonlyArray<{ key: string; action: string }> }} {@const dataAttrs = compiled.contracts.dataAttrsByPart.get(partAny.kebab) ?? []} {@const ariaAttrs = partAny.aria ?? []} {@const keyboard = partAny.keyboard ?? []} {#if dataAttrs.length || ariaAttrs.length || keyboard.length}
{partAny.kebab}
{#if dataAttrs.length}
{#each dataAttrs as attr} {/each}
data-attrValuesSource
{attr.attr} {attr.values ? attr.values.join(' | ') : '—'} {'value' in attr && attr.value ? (attr as { value: { kind: string } }).value.kind : '—'}
{/if} {#if ariaAttrs.length}
{#each ariaAttrs as a} {/each}
aria-attrSourceConditionSeverity
{a.attr} {a.value.kind} {a.condition ? `when ${a.condition.when}${a.condition.prop ? ` (${a.condition.prop})` : ''}` : 'always'} {a.severity ?? 'required'}
{/if} {#if keyboard.length}
{#each keyboard as kb} {/each}
keyaction
{kb.key === ' ' ? 'Space' : kb.key}{kb.action}
{/if} {/if} {/each}
Events declaration
{#each events as action} {@const sem = action.semantic} {@const intentDecl = 'intent' in sem ? sem.intent : undefined} {@const intentStr = typeof intentDecl === 'string' ? intentDecl : intentDecl ? `fromProp:${(intentDecl as { fromProp?: string }).fromProp ?? '?'}` : '—'} {/each}
namefamilyverbsequenceintenttarget
{action.name} {sem.family} {sem.verb ?? '—'} {sem.sequence ?? 'pre'} {intentStr} {action.target}
{/if} {#if tab === 'sema'}

sema · events + perceptual signature

One event — commit-toggle — fires AFTER the state flip (canon sequence: 'post'). The pulse celebrates the resolved state. Intent comes from the intent prop and modulates the perceptual signature via SEMA_MAP.intents.

{#each events as action} {/each}
NameFamilyVerbSequenceIntent (live)Play
{action.name} {action.semantic.family} {action.semantic.verb ?? '—'} {action.semantic.sequence ?? 'pre'} {intent}
{/if} {#if tab === 'recipe'}

Eidos recipe

Selectors at src/uix/eidos/components/toggle/toggle.css. Maps data-state + data-color + data-variant + data-size to design tokens.

SelectorSource
[data-toggle]morfo
[data-toggle][data-state='on'/'off']morfo
[data-toggle][data-color]morfo · resolved from intent + color
[data-toggle][data-disabled / readonly / invalid / required]morfo
[data-toggle][data-variant / data-size / data-block / data-icon-only]eidos
{/if} {#if tab === 'a11y'}

Accessibility

Follows the APG button pattern. Native button keyboard. aria-pressed exposes the toggle state.

Keyboard
KeyAction
Enter / SpaceToggle pressed state.
TabMove focus to / from the toggle.
ARIA contract
AttributeValue
type"button"
aria-pressed"true" / "false"
aria-label{`{aria-label}`} (when set)
aria-disabled / readonly / required / invalid"true" (when set)
{/if}