Toggle
On/off switch with smooth animation, glow effect, and ARIA switch role.
<arc-toggle> Overview
The Toggle component provides a binary on/off control that mirrors the behavior of a physical switch. It is the preferred choice whenever you need a setting that takes immediate effect — toggling a feature on or off, enabling a preference, or activating a mode. Unlike a checkbox, which typically submits with a form, a toggle communicates instant state change to the user.
Internally, Toggle renders with role="switch" and manages aria-checked automatically, giving assistive technology a clear picture of the current state. The thumb slides between positions with a spring-timed CSS transition, and the active state lights up with a subtle glow drawn from the current theme's accent color. Both the track and the thumb inherit design tokens so the component stays consistent across light, dark, and high-contrast modes.
Toggle works equally well as an uncontrolled element (set checked once and let the component manage its own state) or as a fully controlled input driven by framework reactivity. It also participates in native form submission when given a name, emitting a boolean value alongside other form fields.
Guidelines
When to use
- Use a toggle for settings that take effect immediately (e.g. enable notifications)
- Provide a clear, concise label describing what the toggle controls
- Place toggles in a vertical list when presenting multiple related settings
- Use the `checked` attribute to set a sensible default for each option
- Pair with descriptive helper text when the label alone may be ambiguous
When not to use
- Do not use a toggle when the change requires an explicit "Save" action — use a checkbox instead
- Avoid wrapping a toggle inside a clickable card or button — the double-action confuses users
- Do not disable a toggle without explaining why the option is unavailable
- Avoid placing more than 8-10 toggles in a single group — consider grouping into sections
- Do not use a toggle for mutually exclusive options — use a radio group instead
Features
- Binary on/off state with animated thumb slide and glow transition
- Built-in `role="switch"` and automatic `aria-checked` management
- Keyboard accessible — Space and Enter keys toggle state
- Paired label rendered inline, with click-to-toggle support
- Disabled state with reduced opacity and blocked pointer events
- Participates in native `<form>` submission when `name` is set
- Theme-aware glow color derived from accent design tokens
- Works as controlled or uncontrolled input across all frameworks
Preview
Usage
Layout and styling work without JavaScript via the HTML/CSS versions. Interactive features like events and state management require the Web Component or a framework wrapper.
<arc-toggle label="Email notifications" checked></arc-toggle>
<arc-toggle label="Push notifications"></arc-toggle>
<arc-toggle label="Marketing emails"></arc-toggle> import { Toggle } from '@arclux/arc-ui-react';
export default function Example() {
return (
<>
<Toggle label="Email notifications" checked />
<Toggle label="Push notifications" />
<Toggle label="Marketing emails" />
</>
);
} <script setup>
import { Toggle } from '@arclux/arc-ui-vue';
</script>
<template>
<Toggle label="Email notifications" checked />
<Toggle label="Push notifications" />
<Toggle label="Marketing emails" />
</template> <script>
import { Toggle } from '@arclux/arc-ui-svelte';
</script>
<Toggle label="Email notifications" checked />
<Toggle label="Push notifications" />
<Toggle label="Marketing emails" /> import { Component } from '@angular/core';
import { Toggle } from '@arclux/arc-ui-angular';
@Component({
imports: [Toggle],
template: `
<arc-toggle label="Email notifications" checked></arc-toggle>
<arc-toggle label="Push notifications"></arc-toggle>
<arc-toggle label="Marketing emails"></arc-toggle>
`,
})
export class SettingsPanel {} import { Toggle } from '@arclux/arc-ui-solid';
export default function Example() {
return (
<>
<Toggle label="Email notifications" checked />
<Toggle label="Push notifications" />
<Toggle label="Marketing emails" />
</>
);
} import { Toggle } from '@arclux/arc-ui-preact';
export default function Example() {
return (
<>
<Toggle label="Email notifications" checked />
<Toggle label="Push notifications" />
<Toggle label="Marketing emails" />
</>
);
} <arc-toggle label="Email notifications" checked></arc-toggle>
<arc-toggle label="Push notifications"></arc-toggle>
<arc-toggle label="Marketing emails"></arc-toggle> <!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-toggle — self-contained, no external CSS needed -->
<div class="arc-toggle">
</div> API
-
disabledbooleanfalse - Prevents user interaction. The toggle appears at reduced opacity and ignores pointer and keyboard events.
-
labelstring'' - Visible text rendered beside the toggle. Clicking the label also toggles the switch, matching native
<label>behavior. -
namestring'' - Form field name submitted with the toggle value. When set, the component participates in native
<form>submission. -
checkedbooleanfalse - Whether the toggle is in the on position. When set, the thumb slides to the active side and the track displays the accent glow.
-
size'sm' | 'md' | 'lg''md' - Controls the toggle size.
-
formAssociatedbooleantrue -
propertiesobject{ // flag(), unlike `disabled`. The exclusion in props.js is specifically // about form-associated *platform* semantics: a `disabled` content // attribute that is merely present makes the element actually disabled // per the HTML spec, and formDisabledCallback assigns the property back, // so no converter can win. Neither of these is platform-mapped — // `required` is enforced by _computeValidity() below and `readonly` by // each component's own interaction handlers — so the stock converter buys // nothing here and costs the usual bug: `required="false"` read as true, // blocking submission of a form the author meant to leave optional. // Finding #48's shape, across all 26 form controls at once. required: flag(false), readonly: flag(false), } - Lit merges static properties up the prototype chain, so every consumer
gets these without declaring them.
requiredparticipates in constraint validation below;readonlyreflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state). -
autoValidatesbooleantrue - Components that run their own constraint-validation logic (pattern checks, range checks) opt out of the automatic required sync by overriding this to false, and own the whole validity flag set instead.
-
form -
validity -
validationMessage -
requiredbooleanfalse -
readonlybooleanfalse
Methods
-
checkValidity()boolean - Whether the control currently satisfies its constraints, per the native
constraint-validation API. Fires
invalidon the element when it does not, and reports nothing to the user. -
reportValidity()boolean - As checkValidity(), but also shows the browser's validation message against the control when it fails.
Events
-
arc-changedetail: { checked: boolean } - Fired when the toggle state changes
See Also
- Checkbox Multi-select form control supporting checked, indeterminate, and disabled states. Ideal for preferences, bulk-selection patterns, and consent forms where users need to toggle one or more independent options.
- Radio Group Single-select option group with arrow-key navigation and ARIA radiogroup semantics. Ideal for pricing tiers, settings panels, and any context where exactly one choice must be made from a visible set of options.