HySwitch
A form-associated switch component that toggles between on and off states. Provides comprehensive form integration via the ElementInternals API, accessibility features, and customizable styling.
Key Behavioral Model
This switch implements a clear separation between user interactions and programmatic control:
User Interactions (Mouse clicks, Space key)
- Binary states: Toggle between
off↔on - Standard behavior: Follows native switch/toggle conventions
- Predictable UX: Users get consistent toggle behavior
Programmatic Control (JavaScript methods)
- Method-controlled: Use
setState(),toggle(),turnOn(),turnOff() - Event tracking: All changes include
reasonfield ('user' | 'programmatic')
Form Integration
This component implements the Form-Associated Custom Elements API, allowing it to participate in form submission just like native checkboxes. The switch's value will be included in FormData when in the "on" state and the form is submitted.
Usage Guidelines
Switches are ideal for settings that take effect immediately and represent binary on/off states. Use switches for enabling/disabling features, toggling preferences, or controlling visibility. For selections that require a form submission, consider using checkboxes instead.
Sizes
- small: Compact switch for dense layouts or inline controls
- medium (default): Standard switch size for most use cases
- large: Prominent switch for emphasis or improved touch targets
Variants
- default: Standard switch appearance
- error: Red-themed switch indicating error state or required field validation
States
- off: Inactive state (default)
- on: Active/enabled state
- disabled: Non-interactive state (can be combined with off/on)
Keyboard Navigation
- Space key: Toggles between
off↔on - Tab: Moves focus to/from the switch
- Enter: No effect (standard switch behavior - doesn't change state)
Examples
Basic toggle
<hy-switch name="notifications" value="enabled" label="Enable notifications"> </hy-switch>Form submission
<form>
<hy-switch name="dark-mode" value="enabled" label="Dark mode"> </hy-switch>
<button type="submit">Save</button>
</form>With top label and help text
<hy-switch
name="newsletter"
value="subscribed"
top-label="Newsletter Preferences"
label="Subscribe to weekly newsletter"
help-text="Get the latest updates delivered to your inbox"
>
</hy-switch>Required field with error variant
<form>
<hy-switch
name="terms"
value="accepted"
label="Accept terms and conditions"
help-text="You must accept to continue"
required
variant="error"
>
</hy-switch>
<button type="submit">Submit</button>
</form>Different sizes
<hy-switch size="small" label="Small switch"></hy-switch>
<hy-switch size="medium" label="Medium switch"></hy-switch>
<hy-switch size="large" label="Large switch"></hy-switch>Disabled states
<hy-switch label="Disabled off" disabled></hy-switch>
<hy-switch label="Disabled on" state="on" disabled></hy-switch>Programmatic control
const switchElement = document.querySelector('hy-switch');
// Turn on
switchElement.turnOn();
// Turn off
switchElement.turnOff();
// Toggle
switchElement.toggle();
// Check state
console.log(switchElement.checked); // true/false
console.log(switchElement.state); // 'on'/'off'
// Form validation
if (switchElement.checkValidity()) {
console.log('Valid');
} else {
switchElement.reportValidity();
}Event handling
switchElement.addEventListener('change', (e) => {
console.log({
state: e.detail.state, // 'on' or 'off'
checked: e.detail.checked, // true or false
value: e.detail.value, // switch's value attribute
reason: e.detail.reason // 'user' or 'programmatic'
});
// Save setting immediately
if (e.detail.reason === 'user') {
savePreference(e.detail.checked);
}
});Using slots for dynamic content
<hy-switch name="privacy" value="enabled">
<span slot="top-label">
Privacy Settings
<hy-icon name="shield"></hy-icon>
</span>
<span slot="help-text"> Learn more about our <a href="/privacy">privacy policy</a> </span>
</hy-switch>Complete settings interface
<form>
<fieldset>
<legend>Notification Preferences</legend>
<hy-switch
name="email-notifications"
value="enabled"
label="Email notifications"
help-text="Receive updates via email"
state="on"
>
</hy-switch>
<hy-switch
name="push-notifications"
value="enabled"
label="Push notifications"
help-text="Receive push notifications in browser"
state="on"
>
</hy-switch>
<hy-switch
name="sms-notifications"
value="enabled"
label="SMS notifications"
help-text="Receive text message alerts"
disabled
>
</hy-switch>
</fieldset>
<button type="submit">Save Preferences</button>
</form>Programmatic Methods
const switchEl = document.querySelector('hy-switch');
// State control
switchEl.turnOn();
switchEl.turnOff();
switchEl.toggle();
// Form validation
switchEl.checkValidity();
switchEl.reportValidity();
// Focus management
switchEl.focus();
switchEl.blur();
// Access form
console.log(switchEl.form);
console.log(switchEl.validity);
console.log(switchEl.validationMessage);Events
- change - Fired when state changes, includes state, checked, value, and reason
- change - Standard form change event
- input - Standard form input event
Slots
- top-label - Content above the switch
- help-text - Content below the switch
- check-icon - Icon rendered inside the thumb when state is
on. Defaults to a check icon. - uncheck-icon - Icon rendered inside the thumb when state is
off. Empty by default; useful for binary-meaning switches (e.g. sun/moon for a theme toggle).
Methods
willUpdate()
Generates unique IDs before the first render to prevent update-after-update warnings. IDs are generated client-side only to prevent SSR/client hydration mismatches.
checkValidity()
Checks if the switch is valid according to form validation rules. Returns true if valid, false otherwise.
const switchEl = document.querySelector('hy-switch');
if (!switchEl.checkValidity()) {
console.log('Switch is invalid');
}reportValidity()
Checks validity and shows browser validation UI if invalid. Returns true if valid, false otherwise.
const switchEl = document.querySelector('hy-switch');
if (!switchEl.reportValidity()) {
console.log('Switch is invalid and message shown');
}toggle()
Toggles the switch between 'on' and 'off' states programmatically. Does nothing if the switch is disabled.
const switchEl = document.querySelector('hy-switch');
switchEl.toggle(); // off -> on or on -> offturnOn()
Turns the switch to 'on' state programmatically. Does nothing if the switch is disabled.
const switchEl = document.querySelector('hy-switch');
switchEl.turnOn();turnOff()
Turns the switch to 'off' state programmatically. Does nothing if the switch is disabled.
const switchEl = document.querySelector('hy-switch');
switchEl.turnOff();focus()
Sets focus on the switch input.
const switchEl = document.querySelector('hy-switch');
switchEl.focus();blur()
Removes focus from the switch input.
const switchEl = document.querySelector('hy-switch');
switchEl.blur();