j3w1 / theme

j3w1 / theme4.0.0

j3w1 / command

  • SPEC Overview
  • SPEC Foundations
  • SPEC Components
  • SPEC Patterns
  • SPEC Tokens
  • SPEC Tools
  • SPEC Workbench
  • SPEC Form builder
  • SPEC Task kit
  • SPEC Recipes
  • SPEC Figma bridge
  • SPEC Report an issue
  • SPEC Implement
  • SPEC For agents
  • SPEC Ports
  • SPEC Releases
  • SPEC Specification
  • DEMO Vue application demo

Switch

An on/off control that takes effect immediately; a button with role switch and aria-checked, drawn as a square-cornered track with a square thumb that fills with the primary colour when on.

stable · light DOM · 4.0.0. Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.

Live variants

default

Markup
<j3w1-switch id="example-switch-default"><button class="switch" type="button" role="switch" aria-checked="false" aria-label="Wrap long lines">
  <span class="switch-track"><span class="switch-thumb"></span></span>
</button></j3w1-switch>

with-labels

Follow system theme
Markup
<j3w1-switch id="example-switch-with-labels"><div class="switch-row">
  <span class="switch-name" id="example-switch-with-labels-sw-follow-name">Follow system theme</span>
  <button class="switch" type="button" role="switch" aria-checked="false" aria-labelledby="example-switch-with-labels-sw-follow-name">
    <span class="switch-track"><span class="switch-thumb"></span></span>
    <span class="switch-state" aria-hidden="true"><span class="switch-state-off">Off</span><span class="switch-state-on">On</span></span>
  </button>
</div></j3w1-switch>

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.0
import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/switch.css';
import '@j3w1/ui/register/switch';

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.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

npx --package=@j3w1/ui@4.0.0 j3w1-ui copy switch --out ./vendor/j3w1/switch

The 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

NameType / signatureMeaning
disabledCustomEventDisable the native controls owned by this instance.
loadingCustomEventMark the primary control busy and prevent duplicate activation.
checkedCustomEventDefault switch checked.
valueCustomEventDefault switch value.

properties

NameType / signatureMeaning
disabledbooleanDelegates disabled state to native children.
namestringNative control name; application form keys remain explicit.
checkedbooleanImmediate switch state; a named switch exposes a matching native hidden form value.

methods

NameType / signatureMeaning
refresh(): voidReconnect behavior after replacing native child structure.
focus(options?: FocusOptions): voidFocus the first usable native control.

events

NameType / signatureMeaning
j3w1-changeCustomEventThe user toggled the switch.

Dependencies and verification

Registered components: none. Style dependencies: none.

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

Switch switch

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Custom widget: <button type="button" role="switch" aria-checked> — APG pattern
  • specified
  • demonstrated

An on/off control that takes effect immediately; a button with role switch and aria-checked, drawn as a square-cornered track with a square thumb that fills with the primary colour when on.

Report an issue with this component

Tokens

Focus a role to inspect its values; follow its link for persistent usage and source details.

PartRoleValueUse
track.bgcolor.surface.inputapproveduse#000000Form-control fill.
track.bordercolor.border.controlapproveduse#c81a1aD-041 owner correction: red control and floating-frame borders, distinct from rose text.
track.bg-hovercolor.interaction.hover.bgapproveduse#1c1010D-041 interaction.hover.bg: color.primitive.modern.hover.
track.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
track.bg-checkedcolor.action.primary.bgapproveduse#7d1310Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12.
track.bg-checked-hovercolor.action.primary.hover-bgobserveduse#911410Primary button hover; pair with action.primary.text (D-033).
track.ring-checkedcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
track.bg-disabledcolor.interaction.disabled.bgapproveduse#0d0707D-041 interaction.disabled.bg: color.primitive.modern.panel.
track.border-disabledcolor.border.disabledapproveduse#482b2bD-041 border.disabled: color.primitive.modern.divider.
thumb.bgcolor.text.defaultapproveduse#e99499D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
thumb.bg-checkedcolor.action.primary.textapproveduse#ffa2a7Primary action labels: bright rose across rest, hover and pressed states (D-033).
thumb.bg-disabledcolor.text.disabledapproveduse#a3676bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
name.textcolor.text.defaultapproveduse#e99499D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
state.textcolor.text.mutedapproveduse#d4868bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
name.text-disabledcolor.text.disabledapproveduse#a3676bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefaultWith labels
default
Follow system theme
hover
focus-visible
checked
checked+focus-visible
disabled
checked+disabled

Purpose

A setting that applies the moment it is toggled: notifications, wrap lines, follow system theme. A choice applied on submit is a checkbox. The switch is a button because it acts; it is not a form field.

Anatomy

Parts as listed in the anatomy; the thumb sits at the start when off and at the end when on.

States

StateVisualNon-colour channel
defaulttrack 1px color.border.control on color.surface.input; thumb color.text.default at the startthumb position
hoveroff track → color.interaction.hover.bg; on track → color.action.primary.hover-bgcursor: pointer; hover-capable pointers only
focus-visible1px dashed color.interaction.focus.ring at −2px on the trackthe ring
checkedtrack fills color.action.primary.bg; thumb color.action.primary.text at the end; border stays color.border.control; the word reads “On”aria-checked="true"; thumb position; the word
checked+focus-visiblethe fill and a color.interaction.focus.ring-container ring on the trackposition and ring
disabledtrack color.interaction.disabled.bg, 1px color.border.disabled; thumb and name color.text.disableddisabled; cursor: not-allowed
checked+disabledas disabled, thumb at the enddisabled; aria-checked="true"; thumb position

The thumb moves without animation by default; a host may transition transform for at most 120ms under prefers-reduced-motion: no-preference. Precedence: disabled > checked > hover; focus-visible is always drawn.

Keyboard

As in the key table; no arrow keys between switches. Toggling never moves focus.

Accessibility

On a native button only aria-checked is scripted. The name states what is on (“Wrap long lines”), never the current value. Thumb position and, with labels, the word also carry the state. The thumb and track edge meet 3:1, the ring 3:1 off and on.

Portability

The thumb position is layout, not a transform, so it survives hosts with no animation. Hosts with a native switch use it, square it, and map the two fills.

Non-examples

A pill track or round thumb. A switch that applies on submit. A checkbox input styled as a switch. Colour as the only on/off difference. A green on colour. “On” as the name. Disabling by opacity. A slide longer than 120ms or one under reduced motion.

Contrast report

16 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.

PairStateKindForegroundBackgroundRatioMinResult
switch default borderdefaultuicolor.border.control #c81a1acolor.surface.input #0000003.623pass
switch hover borderhoveruicolor.border.control #c81a1acolor.interaction.hover.bg #1c10103.203pass
switch focus-visible borderfocus-visibleuicolor.border.control #c81a1acolor.surface.input #0000003.623pass
switch focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
switch checked textcheckedtextcolor.action.primary.text #ffa2a7color.action.primary.bg #7d13105.574.5pass
switch checked+focus-visible textchecked+focus-visibletextcolor.action.primary.text #ffa2a7color.action.primary.bg #7d13105.574.5pass
switch checked+focus-visible outlinechecked+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.action.primary.bg #7d13105.573pass
thumb on the off track—uicolor.text.default #e99499color.surface.input #0000009.163pass
thumb on the hovered off trackhoveruicolor.text.default #e99499color.interaction.hover.bg #1c10108.103pass
thumb on the hovered on trackhoveruicolor.action.primary.text #ffa2a7color.action.primary.hover-bg #9114104.753pass
on track edge against the panel (the border stays border.control)checkeduicolor.border.control #c81a1acolor.surface.default #0d07073.443pass
visible name on the panel surface—textcolor.text.default #e99499color.surface.default #0d07078.724.5pass
Off / On word on the panel surface—textcolor.text.muted #d4868bcolor.surface.default #0d07077.224.5pass
disabled thumb (exempt; house floor 3:1)disableduicolor.text.disabled #a3676bcolor.interaction.disabled.bg #0d07074.483pass
disabled name (exempt; house floor 3:1)disableduicolor.text.disabled #a3676bcolor.surface.default #0d07074.483pass
disabled border (exempt)disableduicolor.border.disabled #482b2bcolor.interaction.disabled.bg #0d07071.581pass

Keys

KeyAction
Tab / Shift+TabMoves focus to and from the switch.
Space / EnterToggles aria-checked and applies the change at once.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: checkbox radio-group icon-button field

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX