Components · Form Controls

Toggle

A binary switch for enabling or disabling a single option. Communicates state instantly through colour and position.


Interactive demo — click to toggle
state: on

Anatomy

The component has two elements. The track (.toggle) is the pill-shaped container whose background colour reflects state. The thumb (.toggle-circle) is the white circle that slides inside the track.

.toggle
.toggle-circle

Specifications

Default (desktop) dimensions as defined in toggle.css. A responsive breakpoint at 480 px scales the component proportionally.

Width 280px
Height 160px
Border radius 80px
Thumb diameter 140px
Thumb inset 10px (all sides)
Thumb travel left: 10px → left: 130px
Easing cubic-bezier(0.4, 0, 0.2, 1) — 0.4s
Off colour #DDDDDD
Active colour #FF385C
Thumb colour #ffffff

HTML Usage

Link toggle.css in <head> and place the two-element markup anywhere in your template. toggle.js auto-initialises every .toggle on DOMContentLoaded — no manual wiring needed.

HTML
<!-- In <head> -->
<link rel="stylesheet" href="/Components/toggle.css">

<!-- Component markup -->
<div class="toggle"
     role="switch"
     aria-checked="false"
     tabindex="0"
     aria-label="Enable notifications">
  <div class="toggle-circle"></div>
</div>

<!-- Before </body> -->
<script src="/JS/toggle.js"></script>

Pre-active state

Add the active class in markup to render the toggle in the on state on first paint. Pair it with aria-checked="true".

HTML
<div class="toggle active"
     role="switch"
     aria-checked="true"
     tabindex="0"
     aria-label="Notifications enabled">
  <div class="toggle-circle"></div>
</div>

Always include role="switch", aria-checked, tabindex="0", and a descriptive aria-label. toggle.js keeps aria-checked in sync automatically on every state change.


JavaScript API

ToggleSwitch is defined in toggle.js and auto-instantiated on page load via the '.toggle' selector. Construct a new instance for programmatic control.

Method Arguments Returns Description
getState(el) HTMLElement "on" | "off" Reads the current state from the element's data-state attribute.
setState(el, state) HTMLElement, "on" | "off" Sets state silently — does not fire toggle-change.
toggle(el) HTMLElement Flips the current state silently.

Listening for state changes

Every user click dispatches a toggle-change CustomEvent on the element. The detail object exposes a string state and a boolean.

JavaScript
const el = document.querySelector('.toggle');

el.addEventListener('toggle-change', (e) => {
  console.log(e.detail.state);    // "on" | "off"
  console.log(e.detail.isActive); // true | false
});

Programmatic control

JavaScript
const sw = new ToggleSwitch('.toggle');
const el = document.querySelector('#myToggle');

sw.setState(el, 'on');   // force on  — no event
sw.setState(el, 'off');  // force off — no event
sw.toggle(el);            // flip      — no event
sw.getState(el);          // → "on" | "off"

setState() and toggle() do not fire toggle-change. Only user-initiated clicks dispatch the custom event.


Integration

Include toggle.js once before </body>. It auto-initialises all .toggle elements present at load time. Elements added dynamically after load require a fresh new ToggleSwitch(selector) call.

HTML
<script src="/JS/toggle.js"></script>

File structure

Directory
design_guidelines/
├── header.php
├── left_sidebar.php
├── right_sidebar.php
├── toggle.php
├── design-system.css
├── Components/
│   └── toggle.css
└── JS/
    └── toggle.js

Accessibility

The toggle is a custom control — ARIA attributes must be set explicitly in markup. toggle.js keeps aria-checked synchronised on every state transition. The element is keyboard-operable via Space or Enter when focused.

AttributeValueNotes
role "switch" Identifies the element as a binary switch to screen readers.
aria-checked "true" / "false" Kept in sync by toggle.js. Set the initial value in markup.
tabindex "0" Places the element in the natural tab order.
aria-label Descriptive string Describes what is toggled, e.g. "Enable dark mode".

Keyboard activation

JavaScript
document.querySelectorAll('.toggle').forEach(el => {
  el.addEventListener('keydown', e => {
    if (e.key === ' ' || e.key === 'Enter') {
      e.preventDefault(); el.click();
    }
  });
});