-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
191 lines (174 loc) · 10.3 KB
/
index.html
File metadata and controls
191 lines (174 loc) · 10.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
189
190
191
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Card List - Resonance Labs</title>
<link rel="stylesheet" href="/resonance-labs/assets/style/global.css" />
<link rel="stylesheet" href="card-list.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>Card List</h1>
<p class="component-tagline">A structured group of cards presented in a vertical or grid layout, where each card links to a detail view with a single keyboard-accessible link and a large clickable surface.</p>
</div>
<div class="section">
<h2>Demo</h2>
<p>Tab through the card list and observe that each card contributes exactly one stop to the tab order. Notice how the list structure communicates the number of items to screen reader users, and how each card's link is labeled distinctly from the others.</p>
<div class="mount"></div>
</div>
<div class="section">
<h2>What to Observe</h2>
<ul>
<li>The list container communicates the total number of cards to screen reader users</li>
<li>Each card contributes a single focusable element, keeping the tab sequence efficient</li>
<li>Every card's link is uniquely and descriptively labeled — no two cards share the same accessible name</li>
<li>The visual grouping of cards into a list is reflected semantically in the markup</li>
<li>Keyboard focus order follows the visual reading order of the cards</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>List Container</strong> — a semantic list element that groups all cards and communicates their count and relationship to screen readers</li>
<li><strong>List Item</strong> — the wrapper for each individual card within the list, establishing it as a discrete member of the group</li>
<li><strong>Card</strong> — the individual content unit containing an image, title, description, and a primary link that covers the full card surface</li>
<li><strong>Primary Link</strong> — the single interactive element per card, with a descriptive accessible name that identifies the card's destination uniquely within the list</li>
<li><strong>Section Heading</strong> — an optional heading above the card list that names the collection and helps users navigate to it by landmark or heading</li>
</ol>
</div>
<div class="section">
<h2>Accessibility Behavior</h2>
<ul>
<li>Use a semantic list element to wrap the collection of cards so assistive technology communicates the total item count and list structure</li>
<li>Ensure each card has exactly one keyboard-reachable link so users can move through the list efficiently without encountering redundant tab stops</li>
<li>Give each card's link a unique and descriptive accessible name that identifies its specific destination within the list</li>
<li>Maintain a focus order that matches the visual layout so keyboard users and sighted users encounter cards in the same sequence</li>
<li>Ensure the list is preceded by a heading or label that gives context for what the card collection represents</li>
<li>Handle card images as decorative when the card title already conveys the card's subject, to avoid redundant announcements</li>
</ul>
</div>
<div class="section">
<h2>Common Mistakes</h2>
<ul>
<li>Using a div container instead of a semantic list, causing screen readers to miss the item count and grouping information</li>
<li>Giving all cards the same link text such as "Read more," making it impossible for screen reader users to distinguish between items when navigating by links</li>
<li>Including multiple links per card that all point to the same destination, requiring extra tab stops for no informational benefit</li>
<li>Placing interactive elements inside the card in a DOM order that does not match the visual layout, creating a confusing focus sequence</li>
<li>Omitting a heading or label for the card list, leaving users without context for what the collection represents</li>
</ul>
</div>
<div class="section">
<h2>Why This Matters</h2>
<p>A card list is a collection, and collections carry meaning for screen reader users — the item count tells them how much content to expect, the list structure tells them they can navigate item by item, and unique link names tell them what each item leads to. When these structural and naming conventions are absent, screen reader users must listen to or read through every card's full content to understand what is available, rather than scanning efficiently by links. For keyboard users, redundant links and mismatched DOM order can make navigating a card list exhausting. Getting the structure right respects all users' time and effort.</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("./card-list.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 = "./card-list.js";
document.body.appendChild(s);
});
// Fetch CSS
fetch("./card-list.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("./card-list.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>