Components · Form Controls
Toggle
A binary switch for enabling or disabling a single option. Communicates state instantly through colour and position.
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.
Specifications
Default (desktop) dimensions as defined in toggle.css.
A responsive breakpoint at 480 px scales the component proportionally.
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.
<!-- 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".
<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.
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
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.
<script src="/JS/toggle.js"></script>
File structure
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.
| Attribute | Value | Notes |
|---|---|---|
| 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
document.querySelectorAll('.toggle').forEach(el => {
el.addEventListener('keydown', e => {
if (e.key === ' ' || e.key === 'Enter') {
e.preventDefault(); el.click();
}
});
});