Switches

Switches with supporting text

Disabled

Documentation

Switch Component

The Switch component provides a Material Design 3 toggle switch control that allows users to toggle between two states (on/off). It's designed to be lightweight, accessible, and customizable.

Overview

Switches are commonly used for:

  • Toggling settings on/off
  • Enabling/disabling features
  • Binary choices that have an immediate effect

The component follows Material Design 3 guidelines with a track and thumb design, supporting labels, error states, and disabled states.

Import

import { createSwitch } from 'mtrl';

Basic Usage

// Create a basic switch
const mySwitch = createSwitch({
  label: 'Enable notifications',
  checked: true
});

// Add to your page
document.querySelector('.settings-container').appendChild(mySwitch.element);

// Listen for changes
mySwitch.on('change', (event) => {
  console.log('Switch toggled:', event.target.checked);
});

Configuration

The Switch component accepts the following configuration options:

OptionTypeDefaultDescription
namestringundefinedInput name attribute used for form submission
checkedbooleanfalseInitial checked state
requiredbooleanfalseWhether input is required for form validation
disabledbooleanfalseWhether the switch is disabled (non-interactive)
valuestring"on"Input value attribute used for form submission
labelstringundefinedLabel text displayed next to the switch
supportingTextstringundefinedHelper text displayed below the switch
errorbooleanfalseWhether supporting text indicates an error
classstringundefinedAdditional CSS classes to add to the switch
ariaLabelstringundefinedARIA label for accessibility
prefixstring"mtrl"Prefix for CSS class names
componentNamestring"switch"Component name used in CSS class generation
iconstringundefinedIcon HTML content for the switch

Component API

The Switch component provides the following methods:

Value Methods

MethodParametersReturnsDescription
getValue()nonestringGets the switch's current value attribute
setValue(value)value: stringSwitchComponentSets the switch's value attribute

State Methods

MethodParametersReturnsDescription
check()noneSwitchComponentChecks/activates the switch
uncheck()noneSwitchComponentUnchecks/deactivates the switch
toggle()noneSwitchComponentToggles the switch's checked state
isChecked()nonebooleanReturns whether the switch is checked
enable()noneSwitchComponentEnables the switch, making it interactive
disable()noneSwitchComponentDisables the switch, making it non-interactive

Label Methods

MethodParametersReturnsDescription
setLabel(text)text: stringSwitchComponentSets the switch's label text
getLabel()nonestringGets the switch's current label text

Supporting Text Methods

MethodParametersReturnsDescription
setSupportingText(text, isError?)text: string, isError?: booleanSwitchComponentSets supporting text content and optional error state
removeSupportingText()noneSwitchComponentRemoves supporting text

Event Methods

MethodParametersReturnsDescription
on(event, handler)event: string, handler: FunctionSwitchComponentAdds an event listener
off(event, handler)event: string, handler: FunctionSwitchComponentRemoves an event listener

Lifecycle Methods

MethodParametersReturnsDescription
destroy()nonevoidDestroys the switch component and cleans up resources

Events

The Switch component emits the following events:

EventDescriptionData
changeFires when the switch state changes{ checked: boolean, value: string, nativeEvent: Event }
focusFires when the switch receives focus{ event: FocusEvent }
blurFires when the switch loses focus{ event: FocusEvent }

Examples

Basic Switch

const basicSwitch = createSwitch({
  label: 'Dark mode'
});
document.body.appendChild(basicSwitch.element);

Pre-checked Switch

const checkedSwitch = createSwitch({
  label: 'Notifications',
  checked: true
});
document.body.appendChild(checkedSwitch.element);

Switch with Supporting Text

const switchWithHelper = createSwitch({
  label: 'Enable analytics',
  supportingText: 'Data will be collected anonymously'
});
document.body.appendChild(switchWithHelper.element);

Switch with Error State

const errorSwitch = createSwitch({
  label: 'Accept terms',
  supportingText: 'You must accept the terms to continue',
  error: true
});
document.body.appendChild(errorSwitch.element);

Disabled Switch

const disabledSwitch = createSwitch({
  label: 'Premium feature',
  disabled: true,
  supportingText: 'Available in the pro version'
});
document.body.appendChild(disabledSwitch.element);

Toggling Programmatically

const toggleSwitch = createSwitch({
  label: 'Automatic updates'
});

document.body.appendChild(toggleSwitch.element);

// Later, toggle the switch programmatically
toggleSwitch.toggle();

// Or set to a specific state
toggleSwitch.check();   // Turn on
toggleSwitch.uncheck(); // Turn off

Form Integration

const form = document.getElementById('settings-form');

const notificationsSwitch = createSwitch({
  name: 'notifications',
  label: 'Enable notifications',
  value: 'enabled'
});

form.appendChild(notificationsSwitch.element);

form.addEventListener('submit', (event) => {
  event.preventDefault();
  const formData = new FormData(form);
  console.log('Notifications enabled:', formData.has('notifications'));
});

Advanced Usage

Dynamic Supporting Text

const passwordSwitch = createSwitch({
  label: 'Show password',
  supportingText: 'Password will remain hidden'
});

passwordSwitch.on('change', (event) => {
  if (event.target.checked) {
    passwordSwitch.setSupportingText('Password is now visible');
  } else {
    passwordSwitch.setSupportingText('Password is hidden');
  }
});

Validation Integration

const termsSwitch = createSwitch({
  label: 'I agree to the terms and conditions',
  name: 'terms'
});

function validateForm() {
  if (!termsSwitch.isChecked()) {
    termsSwitch.setSupportingText('You must accept the terms to continue', true);
    return false;
  } else {
    termsSwitch.removeSupportingText();
    return true;
  }
}

Accessibility

The Switch component follows accessibility best practices:

  • Proper labeling with label elements and ARIA attributes
  • Keyboard navigation support
  • Focus indicators
  • Clear visual indications of state
  • Disabled states properly communicated to screen readers

Keyboard Navigation

KeyAction
TabMoves focus to the switch
SpaceToggles the switch state
EnterToggles the switch state

CSS Customization

The Switch component uses BEM-style CSS classes for easy customization:

/* Base switch styles */
.mtrl-switch { /* ... */ }

/* Switch container */
.mtrl-switch-container { /* ... */ }

/* Switch track */
.mtrl-switch-track { /* ... */ }

/* Switch thumb */
.mtrl-switch-thumb { /* ... */ }

/* Switch label */
.mtrl-switch-label { /* ... */ }

/* Supporting text */
.mtrl-switch-helper { /* ... */ }

/* Error state */
.mtrl-switch-helper--error { /* ... */ }
.mtrl-switch--error { /* ... */ }

/* Checked state */
.mtrl-switch--checked { /* ... */ }

/* Disabled state */
.mtrl-switch--disabled { /* ... */ }

Composition

The Switch component is built using functional composition, combining multiple features:

  • Event handling
  • DOM element creation
  • Text label
  • Input management
  • Track/thumb visualization
  • Supporting text
  • Checkable state
  • Disabled state
  • Lifecycle management

You can create custom variants by using similar composition patterns with the core utilities.

Best Practices

  • Use switches for binary options that take immediate effect
  • Provide clear, concise labels that describe the action
  • Use supporting text for additional context when needed
  • Group related switches together
  • Avoid using too many switches on a single page
  • Use the error state sparingly and only for required options
  • Prefer switches over checkboxes for toggles that immediately change system state

Browser Compatibility

The Switch component is compatible with all modern browsers:

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Performance Considerations

The Switch component is designed to be lightweight and performant:

  • Minimal DOM operations
  • Efficient event handling
  • No unnecessary reflows or repaints
  • Cleanup on destroy to prevent memory leaks