-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
192 lines (175 loc) · 10.6 KB
/
index.html
File metadata and controls
192 lines (175 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
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Carousel - Resonance Labs</title>
<link rel="stylesheet" href="/resonance-labs/assets/style/global.css" />
<link rel="stylesheet" href="carousel.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>Carousel</h1>
<p class="component-tagline">A carousel cycles through a set of slides using previous and next controls, pauses on hover or focus, and announces each slide to assistive technology so all users can access the content.</p>
</div>
<div class="section">
<h2>Demo</h2>
<p>Use the previous and next buttons to advance through slides. Tab into the carousel and observe that autoplay pauses when focus enters. Use the keyboard to activate controls and listen for how slide changes are announced by a screen reader.</p>
<div class="mount"></div>
</div>
<div class="section">
<h2>What to Observe</h2>
<ul>
<li>The previous and next controls are keyboard operable and have descriptive accessible names</li>
<li>Autoplay pauses when the mouse hovers over the carousel or when keyboard focus enters it</li>
<li>Each slide transition is announced to screen reader users, including the current slide position within the total</li>
<li>Hidden slides are not reachable by keyboard or assistive technology</li>
<li>The carousel region is identified with a label so screen reader users know where they are when they encounter it</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>Carousel Region</strong> — the landmark or labelled container that identifies the carousel to screen reader users and holds all slides and controls</li>
<li><strong>Slide Track</strong> — the scrollable or animated container that holds all individual slides in sequence</li>
<li><strong>Slide</strong> — an individual content panel within the carousel; only the active slide is visible and reachable to all users</li>
<li><strong>Previous and Next Controls</strong> — native button elements that advance or reverse the slide position; each carries a descriptive accessible name</li>
<li><strong>Slide Indicators</strong> — optional dot or tab controls that show total slide count and allow direct navigation to a specific slide; each must have an accessible name identifying its target slide</li>
<li><strong>Live Region</strong> — an announcement area that communicates slide changes to screen reader users without requiring focus to move</li>
</ol>
</div>
<div class="section">
<h2>Accessibility Behavior</h2>
<ul>
<li>Wrap the carousel in a labelled region so users navigating by landmarks can identify and locate it</li>
<li>Pause autoplay whenever the mouse hovers over the carousel or keyboard focus is within it, so users are not timed out of content</li>
<li>Announce slide changes to screen reader users, including position information such as "slide 2 of 5," so users understand what has changed and how much content remains</li>
<li>Ensure hidden slides are completely inaccessible to keyboard and assistive technology — not merely visually hidden</li>
<li>Give previous and next buttons descriptive accessible names that clarify their action; avoid naming them only with directional symbols</li>
<li>Provide a way to stop autoplay entirely, giving users full control over moving content</li>
</ul>
</div>
<div class="section">
<h2>Common Mistakes</h2>
<ul>
<li>Continuing autoplay while the user is focused on or hovering over the carousel, which can disorient users before they finish reading a slide</li>
<li>Failing to announce slide changes, leaving screen reader users unaware that the content has updated</li>
<li>Allowing hidden slides to remain keyboard focusable, causing users to interact with content they cannot see</li>
<li>Labelling navigation buttons only with icons such as arrows without providing an accessible name, making them ambiguous to screen reader users</li>
<li>Omitting slide position context from announcements, so users have no sense of how many slides exist or where they are in the sequence</li>
</ul>
</div>
<div class="section">
<h2>Why This Matters</h2>
<p>Carousels are among the most accessibility-challenged components in common use. Autoplay that does not pause creates a time pressure that disproportionately affects users with cognitive and motor disabilities. Hidden slides that remain keyboard-reachable create a confusing and disorienting experience. Without slide announcements, screen reader users have no way to know the content has changed. When controls lack accessible names, users cannot tell what the buttons do. The carousel requires more careful accessibility engineering than almost any other component — done well, it gives all users access to the full content; done poorly, it effectively hides content from a significant portion of the audience.</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("./carousel.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 = "./carousel.js";
document.body.appendChild(s);
});
// Fetch CSS
fetch("./carousel.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("./carousel.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>