-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
236 lines (215 loc) · 12.4 KB
/
index.html
File metadata and controls
236 lines (215 loc) · 12.4 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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Breadcrumbs - Resonance Labs</title>
<link rel="stylesheet" href="/resonance-labs/assets/style/global.css" />
<link rel="stylesheet" href="breadcrumbs.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>Breadcrumbs</h1>
<p class="component-tagline">A navigation landmark that displays a trail of links reflecting the user's current position within a site hierarchy, helping them understand context and navigate to higher-level pages.</p>
</div>
<div class="section">
<h2>Demo</h2>
<p>Review both breadcrumb scenarios below. Tab through the links and observe how each is identified and announced. Notice how the current page item is distinguished from the preceding navigation links, and how the separator characters are handled by assistive technology.</p>
<div class="mount"></div>
</div>
<div class="section">
<h2>What to Observe</h2>
<ul>
<li>The breadcrumb trail is contained within a navigation landmark with a distinct accessible name</li>
<li>Separator characters between items are hidden from assistive technology and not announced</li>
<li>The current page item is marked programmatically so screen readers identify it as the active location</li>
<li>When the current page is a link, it is distinguishable from ancestor links both visually and semantically</li>
<li>When the current page is plain text, it is not focusable and does not behave like a link</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>Navigation Landmark</strong> — the wrapping nav element with a label that distinguishes this breadcrumb from other navigation regions on the page</li>
<li><strong>Ordered List</strong> — the semantic list container that groups breadcrumb items and communicates their count and sequential relationship to screen readers</li>
<li><strong>Ancestor Link</strong> — a standard anchor element linking to a higher-level page in the site hierarchy</li>
<li><strong>Current Page Item</strong> — the final item representing the user's current location, marked to indicate it is the active page; may be a link or plain text depending on the implementation</li>
<li><strong>Separator</strong> — a visual-only character or icon between items that is hidden from assistive technology</li>
</ol>
</div>
<div class="section">
<h2>Accessibility Behavior</h2>
<ul>
<li>Wrap the breadcrumb in a navigation landmark and give it an accessible name that distinguishes it from other navigation regions on the page</li>
<li>Use an ordered list to convey the hierarchical and sequential nature of the breadcrumb trail</li>
<li>Mark the current page item programmatically so assistive technology can identify the user's active location within the trail</li>
<li>Hide separator characters from assistive technology so they are not read aloud as part of the breadcrumb content</li>
<li>Ensure ancestor links have meaningful and descriptive link text that reflects the destination page</li>
<li>If the current page item is rendered as a link, it should still be identifiable as the current location rather than just another navigation link</li>
</ul>
</div>
<div class="section">
<h2>Common Mistakes</h2>
<ul>
<li>Placing the breadcrumb outside a navigation landmark, making it invisible to users who navigate by landmarks</li>
<li>Using an unordered list or a flat sequence of links without a list element, losing the semantic structure that communicates hierarchy</li>
<li>Failing to mark the current page item, leaving screen reader users without a clear indication of their location</li>
<li>Not hiding separator characters, causing them to be read aloud and cluttering the screen reader's output</li>
<li>Using generic link text such as "click here" or truncated labels that do not describe the destination page</li>
</ul>
</div>
<div class="section">
<h2>Why This Matters</h2>
<p>Breadcrumbs are a wayfinding tool. For sighted users, the visual trail makes location obvious at a glance. For screen reader users navigating by landmarks or links, the breadcrumb's structure — its landmark label, list semantics, and current-page marker — is what makes location comprehensible. When these elements are absent, screen reader users may have no way to understand where they are in a site's structure or how to return to a parent page without using the browser's back button. A correctly implemented breadcrumb gives all users an equivalent sense of orientation.</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>
<!-- Scenario 1: Current page as a link -->
<div class="section">
<h2>Code</h2>
<h3>Scenario: Current page as a link</h3>
<div class="code-tabs" role="tablist">
<button class="code-tabs__tab code-tabs__tab--active" role="tab" aria-selected="true" data-tab="html-1">HTML</button>
<button class="code-tabs__tab" role="tab" aria-selected="false" data-tab="css-1">CSS</button>
<button class="code-tabs__tab" role="tab" aria-selected="false" data-tab="js-1">JS</button>
</div>
<div class="code-preview" id="panel-html-1" role="tabpanel">
<pre class="line-numbers"><code id="code-html-1" class="language-markup"></code></pre>
<button class="code-preview__copy" data-target="code-html-1">Copy Code</button>
</div>
<div class="code-preview" id="panel-css-1" role="tabpanel" hidden>
<pre class="line-numbers"><code id="code-css-1" class="language-css"></code></pre>
<button class="code-preview__copy" data-target="code-css-1">Copy Code</button>
</div>
<div class="code-preview" id="panel-js-1" role="tabpanel" hidden>
<pre class="line-numbers"><code id="code-js-1" class="language-javascript"></code></pre>
<button class="code-preview__copy" data-target="code-js-1">Copy Code</button>
</div>
</div>
<!-- Scenario 2: Current page is NOT a link -->
<div class="section">
<h3>Scenario: Current page is NOT a link</h3>
<div class="code-tabs" role="tablist">
<button class="code-tabs__tab code-tabs__tab--active" role="tab" aria-selected="true" data-tab="html-2">HTML</button>
<button class="code-tabs__tab" role="tab" aria-selected="false" data-tab="css-2">CSS</button>
<button class="code-tabs__tab" role="tab" aria-selected="false" data-tab="js-2">JS</button>
</div>
<div class="code-preview" id="panel-html-2" role="tabpanel">
<pre class="line-numbers"><code id="code-html-2" class="language-markup"></code></pre>
<button class="code-preview__copy" data-target="code-html-2">Copy Code</button>
</div>
<div class="code-preview" id="panel-css-2" role="tabpanel" hidden>
<pre class="line-numbers"><code id="code-css-2" class="language-css"></code></pre>
<button class="code-preview__copy" data-target="code-css-2">Copy Code</button>
</div>
<div class="code-preview" id="panel-js-2" role="tabpanel" hidden>
<pre class="line-numbers"><code id="code-js-2" class="language-javascript"></code></pre>
<button class="code-preview__copy" data-target="code-js-2">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>
var mounts = document.querySelectorAll(".mount");
// Scenario 1: Current page as a link
fetch("./breadcrumbs-link.html")
.then(function (r) { return r.text(); })
.then(function (html) {
mounts[0].innerHTML = html;
var rawHtml = html.replace(/<!--[\s\S]*?-->\n*/g, "").trim();
var codeHtml = document.getElementById("code-html-1");
codeHtml.textContent = rawHtml;
Prism.highlightElement(codeHtml);
// Load component JS once
var s = document.createElement("script");
s.src = "./breadcrumbs.js";
document.body.appendChild(s);
});
// Scenario 2: Current page is NOT a link
fetch("./breadcrumbs-nolink.html")
.then(function (r) { return r.text(); })
.then(function (html) {
mounts[1].innerHTML = html;
var rawHtml = html.replace(/<!--[\s\S]*?-->\n*/g, "").trim();
var codeHtml = document.getElementById("code-html-2");
codeHtml.textContent = rawHtml;
Prism.highlightElement(codeHtml);
});
// Fetch CSS — populate both panels
fetch("./breadcrumbs.css")
.then(function (r) { return r.text(); })
.then(function (css) {
["code-css-1", "code-css-2"].forEach(function (id) {
var el = document.getElementById(id);
el.textContent = css;
Prism.highlightElement(el);
});
});
// Fetch JS — populate both panels
fetch("./breadcrumbs.js")
.then(function (r) { return r.text(); })
.then(function (js) {
["code-js-1", "code-js-2"].forEach(function (id) {
var el = document.getElementById(id);
el.textContent = js;
Prism.highlightElement(el);
});
});
// Tab switching — scoped per tab group
document.querySelectorAll(".code-tabs").forEach(function (tabBar) {
var tabs = tabBar.querySelectorAll(".code-tabs__tab");
tabs.forEach(function (tab) {
tab.addEventListener("click", function () {
tabs.forEach(function (t) {
t.classList.remove("code-tabs__tab--active");
t.setAttribute("aria-selected", "false");
});
tabs.forEach(function (t) {
var panel = document.getElementById("panel-" + t.dataset.tab);
if (panel) panel.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>