-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
206 lines (187 loc) · 10.6 KB
/
index.html
File metadata and controls
206 lines (187 loc) · 10.6 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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Select - Resonance Labs</title>
<link rel="stylesheet" href="/resonance-labs/assets/style/global.css" />
<link rel="stylesheet" href="select.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>
<section class="section">
<h1>Select</h1>
<p class="component-tagline">A select control presents a dropdown list from which users choose a single value, leveraging the native element for reliable keyboard interaction and screen reader support.</p>
</section>
<section class="section">
<h2>Demo</h2>
<p>Tab to the select control and press Space or Enter to open the option list. Use the arrow keys to move through options and press Enter or Space to confirm a selection. Verify that both the field label and the chosen option are announced by a screen reader.</p>
<div class="mount"></div>
</section>
<section class="section">
<h2>What to Observe</h2>
<ul>
<li>The select has a persistent visible label that is programmatically associated with the control.</li>
<li>The control is reachable by Tab and fully operable by keyboard — no mouse is needed to open, navigate, or select an option.</li>
<li>The currently selected option is communicated to screen readers both when the control receives focus and after a selection is made.</li>
<li>If a default placeholder option is present, it is not selectable as a real value after the user has made a choice.</li>
<li>The select respects browser and OS conventions for the option list, ensuring consistent behavior across platforms.</li>
</ul>
</section>
<section class="section">
<h2>Anatomy</h2>
<p class="anatomy-placeholder">[Anatomy image placeholder — will be added when assets are available]</p>
<ol>
<li><strong>Field label:</strong> The visible text label linked to the select control that describes what the user is choosing.</li>
<li><strong>Select element:</strong> The native HTML select control that renders the collapsed trigger and manages the option list.</li>
<li><strong>Trigger / collapsed state:</strong> The visible button-like surface showing the current selection that opens the option list when activated.</li>
<li><strong>Option list:</strong> The expanded dropdown containing all available choices, rendered by the browser or operating system.</li>
<li><strong>Option items:</strong> The individual selectable values within the list, each with a visible text label.</li>
<li><strong>Option groups:</strong> Optional groupings of related options under a shared non-selectable heading, created with the optgroup element.</li>
</ol>
</section>
<section class="section">
<h2>Accessibility Behavior</h2>
<ul>
<li>The select control must have a visible label that is programmatically associated using a for/id pairing.</li>
<li>The control must be operable by keyboard: Tab to focus, Space or Enter to open, arrow keys to navigate options, and Enter or Space to confirm.</li>
<li>The selected option must be communicated to screen readers when focus enters the control and when the selection changes.</li>
<li>Placeholder options that represent no real value should carry an empty value and be disabled to prevent them from being re-selected.</li>
<li>Groupings of options must use the optgroup element with a label attribute so the category name is announced for screen reader users.</li>
<li>An error state, if present, must be communicated through text and linked to the select — not conveyed by a border color change alone.</li>
</ul>
</section>
<section class="section">
<h2>Common Mistakes</h2>
<ul>
<li>Using a custom div-based dropdown instead of a native select element, losing all built-in keyboard and screen reader support.</li>
<li>Omitting a visible label and relying on a placeholder option as the only identifier, which disappears after the user makes a selection.</li>
<li>Failing to associate the label with the select programmatically, so screen readers do not announce the field's purpose.</li>
<li>Including a placeholder option that can be re-selected as a valid value, causing ambiguous or empty submissions.</li>
<li>Indicating an error state only through a red border color, with no text message linked to the control.</li>
</ul>
</section>
<section class="section">
<h2>Why This Matters</h2>
<p>The native select element is one of the most universally supported form controls across browsers, operating systems, and assistive technologies. When teams replace it with custom-built dropdowns, they take on the full responsibility of replicating every keyboard interaction and screen reader behavior — a burden that is often underestimated and leads to broken experiences. Retaining the native element with thoughtful labeling and option structure delivers the best accessibility outcome for the least implementation effort.</p>
</section>
<section 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>
</section>
<section 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>
</section>
<section 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>
</section>
</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("./select.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*/, "").trim();
var codeHtml = document.getElementById("code-html");
codeHtml.textContent = rawHtml;
Prism.highlightElement(codeHtml);
// Load component JS
var s = document.createElement("script");
s.src = "./select.js";
document.body.appendChild(s);
});
// Fetch CSS
fetch("./select.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("./select.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>