-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
188 lines (171 loc) · 11.3 KB
/
index.html
File metadata and controls
188 lines (171 loc) · 11.3 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
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Video - Resonance Labs</title>
<link rel="stylesheet" href="/resonance-labs/assets/style/global.css" />
<link rel="stylesheet" href="video.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>Video</h1>
<p class="component-tagline">A video component embeds a media player with accessible controls for play, pause, volume, and captions, ensuring keyboard operability and text alternatives for users who cannot see or hear the content.</p>
</div>
<div class="section">
<h2>Demo</h2>
<p>Use the playback controls below the video to play, pause, and adjust volume using only the keyboard. Tab through the controls and press <strong>Space</strong> or <strong>Enter</strong> to activate each one. Enable captions if available and observe how the caption track is announced and displayed. Check whether a transcript is also provided alongside the player.</p>
<div class="mount"></div>
</div>
<div class="section">
<h2>What to Observe</h2>
<ul>
<li>All player controls — play, pause, volume, seek, and captions toggle — are reachable and operable by keyboard alone.</li>
<li>Each control has an accessible label so screen readers can announce its purpose rather than just "button."</li>
<li>Captions can be enabled and are synchronized with the spoken audio content in the video.</li>
<li>A text transcript of the video's audio content is provided so users who cannot play the video at all can still access the information.</li>
<li>The video does not autoplay with sound, avoiding a disorienting experience for screen reader users whose audio output would be interrupted.</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>Video element:</strong> The native <code><video></code> element that contains the media source and hosts child track elements for captions and descriptions.</li>
<li><strong>Caption track:</strong> A <code><track></code> element with <code>kind="captions"</code> pointing to a WebVTT file that provides synchronized text for spoken dialogue and important audio cues.</li>
<li><strong>Playback controls:</strong> Buttons for play/pause, volume, mute, and full-screen, each with an accessible name through visible text or <code>aria-label</code>.</li>
<li><strong>Progress/seek bar:</strong> A slider or range input allowing users to move to any point in the video, labeled so screen readers can announce the current playback position.</li>
<li><strong>Captions toggle:</strong> A button that enables or disables the caption track, with its current state (on or off) communicated to assistive technology.</li>
<li><strong>Transcript:</strong> A separate section of the page containing the full text of the video's audio content, available to users regardless of their ability to play the media.</li>
</ol>
</div>
<div class="section">
<h2>Accessibility Behavior</h2>
<ul>
<li>The video must not autoplay with audio — doing so disrupts screen reader users who rely on audio output to navigate the page.</li>
<li>All custom player controls must be operable by keyboard and must have accessible labels describing their function and, where applicable, their current state.</li>
<li>Captions must be provided for all spoken dialogue and meaningful audio content, synchronized with the playback timeline.</li>
<li>An audio description track or a descriptive transcript must be available for visual content in the video that is not conveyed through the audio alone.</li>
<li>A full text transcript must be provided so users who cannot play the video can still access its content.</li>
<li>If the video contains flashing or strobing content, a warning must precede it so users with photosensitive conditions can make an informed choice before playing.</li>
</ul>
</div>
<div class="section">
<h2>Common Mistakes</h2>
<ul>
<li>Autoplaying video with sound, which interrupts screen readers and can disorient users who are not expecting audio to begin.</li>
<li>Providing no captions or providing auto-generated captions without reviewing them for accuracy, leaving deaf and hard-of-hearing users with inaccurate or missing dialogue.</li>
<li>Building custom player controls as non-interactive <code><div></code> elements that cannot receive keyboard focus or be activated without a mouse.</li>
<li>Omitting a transcript, which is the only way some users — including those on metered connections, in quiet environments, or with certain cognitive disabilities — can access the content.</li>
<li>Labeling the play button only with an icon and no text alternative, leaving screen reader users with no way to identify or activate it.</li>
</ul>
</div>
<div class="section">
<h2>Why This Matters</h2>
<p>Video is one of the richest formats for delivering information, but it is also one of the most exclusive when implemented without accessibility in mind. Deaf users miss all spoken content without captions. Blind users miss all visual-only information without audio descriptions. Users on slow connections or in noise-sensitive environments need transcripts. Users with motor disabilities need keyboard-operable controls. Each of these groups is shut out entirely by a single missing accommodation. Video is also increasingly used for onboarding, training, and compliance content — areas where being locked out has direct consequences for participation and employment. Getting video accessibility right means the content reaches every person it was intended for.</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("./video.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 = "./video.js";
document.body.appendChild(s);
});
// Fetch CSS
fetch("./video.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("./video.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>