-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
187 lines (170 loc) · 10.7 KB
/
index.html
File metadata and controls
187 lines (170 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Toggle Switch - Resonance Labs</title>
<link rel="stylesheet" href="/resonance-labs/assets/style/global.css" />
<link rel="stylesheet" href="toggle-switch.css" />
<link rel="icon" href="/resonance-labs/assets/images/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-numbers/prism-line-numbers.min.css" />
<script src="/resonance-labs/assets/js/component-layout.js" defer></script>
</head>
<body>
<header><a href="/resonance-labs/index.html" class="back-link"><img src="/resonance-labs/assets/images/logo.svg" alt="Resonance Logo" /></a></header>
<main>
<div class="section">
<h1>Toggle Switch</h1>
<p class="component-tagline">A toggle switch provides an immediate on/off control that takes effect right away, with its current state communicated visually and through ARIA attributes for assistive technology.</p>
</div>
<div class="section">
<h2>Demo</h2>
<p>Click or tap the toggle to switch it between on and off. Then tab to it with the keyboard and press <strong>Space</strong> to activate it. Listen with a screen reader to confirm that the new state — "on" or "off" — is announced immediately after each interaction without requiring a page reload or form submission.</p>
<div class="mount"></div>
</div>
<div class="section">
<h2>What to Observe</h2>
<ul>
<li>The toggle has a persistent visible label that identifies what setting it controls — the label does not disappear when the switch is activated.</li>
<li>A screen reader announces the label and the current state (on or off) when focus lands on the control.</li>
<li>Activating the toggle immediately announces the new state without requiring focus to leave and return.</li>
<li>The visual difference between on and off states is communicated through more than color alone — position or shape also changes.</li>
<li>The control is reachable and operable by keyboard using Space or Enter without any mouse interaction.</li>
</ul>
</div>
<div class="section">
<h2>Anatomy</h2>
<p class="anatomy-placeholder">[Anatomy image placeholder — will be added when assets are available]</p>
<ol>
<li><strong>Label:</strong> A visible text label identifying what the toggle controls, persistently displayed regardless of the current state.</li>
<li><strong>Track:</strong> The elongated pill-shaped background element that visually represents the switch housing; its fill color typically changes between states.</li>
<li><strong>Thumb:</strong> The circular element that slides left (off) or right (on) within the track to indicate the current state.</li>
<li><strong>State indicator:</strong> Optional text inside or beside the track ("On" / "Off") providing an additional non-color cue for the current state.</li>
<li><strong>Interactive control:</strong> The underlying button or checkbox element that receives focus, carries the ARIA switch role and checked state, and handles keyboard activation.</li>
</ol>
</div>
<div class="section">
<h2>Accessibility Behavior</h2>
<ul>
<li>The control must use <code>role="switch"</code> and <code>aria-checked</code> set to <code>true</code> or <code>false</code> to communicate state to assistive technology.</li>
<li>The label must be programmatically associated with the control so screen readers announce what the toggle controls, not just its state.</li>
<li>The current state must update immediately on activation, and the change must be announced to screen readers without a page reload.</li>
<li>The toggle must be operable by keyboard — pressing Space must toggle the state when the control has focus.</li>
<li>On and off states must be distinguishable through visual cues beyond color, such as the thumb position or supplementary text labels.</li>
<li>The control must have a visible focus indicator with sufficient contrast so keyboard users can identify where focus is.</li>
</ul>
</div>
<div class="section">
<h2>Common Mistakes</h2>
<ul>
<li>Building the toggle as a styled <code><div></code> with a click handler but no role, label, or keyboard support, making it completely inaccessible.</li>
<li>Using only background color to differentiate the on and off states, which fails users with color vision deficiencies.</li>
<li>Omitting the label or placing it in a way that is not programmatically associated, so screen readers only announce "switch, on" without context for what is being toggled.</li>
<li>Requiring a form submission to apply the toggled state, which contradicts the expected immediate-effect behavior of a switch.</li>
<li>Not updating <code>aria-checked</code> when the visual state changes, leaving screen readers stuck reporting the old state.</li>
</ul>
</div>
<div class="section">
<h2>Why This Matters</h2>
<p>Toggle switches appear in settings panels, feature flags, notification preferences, and privacy controls — all places where users need to make quick binary decisions. A toggle that communicates its state only through visual position or color gives blind users and keyboard-only users no way to know whether a setting is on or off. In critical contexts like privacy permissions or accessibility settings, this is not just an inconvenience — it means users cannot make informed choices about their own experience. Implementing the switch role and live state updates closes that gap entirely.</p>
</div>
<div class="section">
<h2>Accessibility Validation</h2>
<p>This component is validated against internal accessibility criteria aligned with WCAG standards, using our internally developed system, <strong>Resonance Specs</strong>.</p>
<p>To learn more, please contact us.</p>
</div>
<div class="section">
<h2>Code</h2>
<div class="code-tabs" role="tablist">
<button class="code-tabs__tab code-tabs__tab--active" role="tab" aria-selected="true" data-tab="html">HTML</button>
<button class="code-tabs__tab" role="tab" aria-selected="false" data-tab="css">CSS</button>
<button class="code-tabs__tab" role="tab" aria-selected="false" data-tab="js">JS</button>
</div>
<div class="code-preview" id="panel-html" role="tabpanel">
<pre class="line-numbers"><code id="code-html" class="language-markup"></code></pre>
<button class="code-preview__copy" data-target="code-html">Copy Code</button>
</div>
<div class="code-preview" id="panel-css" role="tabpanel" hidden>
<pre class="line-numbers"><code id="code-css" class="language-css"></code></pre>
<button class="code-preview__copy" data-target="code-css">Copy Code</button>
</div>
<div class="code-preview" id="panel-js" role="tabpanel" hidden>
<pre class="line-numbers"><code id="code-js" class="language-javascript"></code></pre>
<button class="code-preview__copy" data-target="code-js">Copy Code</button>
</div>
</div>
<div class="section">
<h2>Reference Implementation</h2>
<ul class="btn-group">
<li><a class="btn btn-primary" href="/resonance-labs/index.html">Back to Home</a></li>
<li><a class="btn btn-secondary" href="https://github.com/Accenture/resonance-labs">GitHub Code</a></li>
</ul>
</div>
</main>
<footer>
<p><strong>Created and maintained by Accenture Song</strong></p>
<p>© 2026 Accenture - Resonance</p>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
<script>
// Fetch HTML fragment
fetch("./toggle-switch.html")
.then(function (r) { return r.text(); })
.then(function (html) {
document.querySelector(".mount").innerHTML = html;
// Populate HTML code preview (strip leading comment block)
var rawHtml = html.replace(/<!--[\s\S]*?-->\n*/g, "").replace(/<script type="application\/json"[\s\S]*?<\/script>\n*/g, "").trim();
var codeHtml = document.getElementById("code-html");
codeHtml.textContent = rawHtml;
Prism.highlightElement(codeHtml);
// Load component JS
var s = document.createElement("script");
s.src = "./toggle-switch.js";
document.body.appendChild(s);
});
// Fetch CSS
fetch("./toggle-switch.css")
.then(function (r) { return r.text(); })
.then(function (css) {
var codeCss = document.getElementById("code-css");
codeCss.textContent = css;
Prism.highlightElement(codeCss);
});
// Fetch JS
fetch("./toggle-switch.js")
.then(function (r) { return r.text(); })
.then(function (js) {
var codeJs = document.getElementById("code-js");
codeJs.textContent = js;
Prism.highlightElement(codeJs);
});
// Tab switching
var tabs = document.querySelectorAll(".code-tabs__tab");
var codePanels = document.querySelectorAll("#panel-html, #panel-css, #panel-js");
tabs.forEach(function (tab) {
tab.addEventListener("click", function () {
tabs.forEach(function (t) {
t.classList.remove("code-tabs__tab--active");
t.setAttribute("aria-selected", "false");
});
codePanels.forEach(function (p) { p.hidden = true; });
tab.classList.add("code-tabs__tab--active");
tab.setAttribute("aria-selected", "true");
document.getElementById("panel-" + tab.dataset.tab).hidden = false;
});
});
// Copy buttons
document.querySelectorAll(".code-preview__copy").forEach(function (btn) {
btn.addEventListener("click", function () {
var codeEl = document.getElementById(btn.dataset.target);
navigator.clipboard.writeText(codeEl.textContent).then(function () {
btn.textContent = "Copied!";
setTimeout(function () { btn.textContent = "Copy Code"; }, 2000);
});
});
});
</script>
</body>
</html>