Switch
Switches toggle a single setting on or off with immediate effect, such as notifications, dark mode, or feature flags.
Try it
Usage
Bind checked for controlled state. Place inside RuiField with a RuiLabel that describes what the switch controls when composing forms.
import { RuiSwitch } from '@ecopages/radiant-ui/switch';
<RuiSwitch checked={enabled}>Email notifications</RuiSwitch>Custom markup
<rui-switch> coordinates any light-DOM tree that matches its query contract. The RuiSwitch helper stamps these targets; it is not required.
import '@ecopages/radiant-ui/switch';
<rui-switch checked>
<label class="rui-switch">
<input
type="checkbox"
role="switch"
data-ref="input"
data-rui-control
data-rui-control-type="boolean"
class="rui-switch__input"
/>
<span class="rui-switch__track" aria-hidden="true">
<span class="rui-switch__thumb"></span>
</span>
<span class="rui-switch__label">Email notifications</span>
</label>
</rui-switch>BEM classes are presentation-only. The host syncs checked, disabled, and name on [data-ref="input"].
Switch vs checkbox
Use switches for settings that take effect immediately. Use checkboxes for options collected on form submit.
Theming
Switch chrome maps to semantic surface roles, never Tailwind palette steps. Override --rui-switch-* on rui-switch.
| Part / state | Default | Override |
|---|---|---|
| Track size | 2.5rem × 1.5rem | --rui-switch-width, --rui-switch-height |
| Thumb | 1rem | --rui-switch-thumb-size |
| Track off / hover | --on-background at 20% / 30% | --rui-switch-track, --rui-switch-track-hover |
| Track on / hover | --primary | --rui-switch-track-on, --rui-switch-track-on-hover |
| Thumb off / on | --on-background / --on-primary | --rui-switch-thumb, --rui-switch-thumb-on |
| Focus | focus-ring | theme --focus-ring |
| Disabled | opacity-disabled | theme --opacity-disabled |
rui-switch {
--rui-switch-width: 3rem;
--rui-switch-track-on: var(--success);
}Label text uses on-background; track uses the rounded-pill radius token. Remap theme roles for global mood.
Accessibility
- Switches expose
role="switch"witharia-checked. - Labels must describe the setting, not the control (for example, "Email notifications", not "Toggle").
- Space toggles the switch when focused.
API
RuiSwitch renders a <label> and native <input type="checkbox" role="switch"> inside the coordinating <rui-switch> custom element. Use the JSX view or compose equivalent marked-up light DOM; the browser owns activation and Space-to-toggle.
Attributes (<rui-switch>)
| Attribute | Type | Default | Description |
|---|---|---|---|
checked | boolean | false | On state; reflects to markup. |
disabled | boolean | false | Disabled state. |
name | string | '' | Form field name on the inner input. |
Light-DOM contract
| Target | Required | Host writes | Author owns |
|---|---|---|---|
[data-ref="input"] | yes | checked, disabled, name | the input element; stamp data-rui-control for field wiring |
Do not fight host-owned input state. Nested hosts: none.
Events
| Event | Detail | Description |
|---|---|---|
rui-change | { checked: boolean } | Emitted after the checked state changes. |
View helpers
| Component | Target stamped | Notes |
|---|---|---|
RuiSwitch | [data-ref="input"] on native role="switch" checkbox | Children render in rui-switch__label. Always stamps data-rui-control. |
CSS classes
Public BEM classes (documented via @cssclass):
| Class | Description |
|---|---|
.rui-switch | Label row: track + thumb + visible label. |
.rui-switch__input | Native input (visually hidden, receives focus). |
.rui-switch__track | Pill track; primary fill when checked. |
.rui-switch__thumb | Sliding thumb. |
.rui-switch__label | Light-DOM label text. |
Theme roles
| Part | CSS variables consumed |
|---|---|
| Track | --on-background (off, alpha), --primary (on) |
| Thumb | --on-background (off), --on-primary (on) |
| Focus ring | --focus-ring |