-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkeyboard-navigation.html
More file actions
167 lines (150 loc) · 9.58 KB
/
Copy pathkeyboard-navigation.html
File metadata and controls
167 lines (150 loc) · 9.58 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
---
layout: experience
title: Keyboard Navigation
page_js: keyboard-nav.js
---
<!-- Page intro -->
<div class="dx-content">
<span class="eyebrow">Access Lab · Experience 02</span>
<h1 class="page-title">Keyboard Navigation</h1>
<p class="lead">Navigate a library services widget using only your keyboard, and discover why some options are reachable and others are not.</p>
<p>This activity contains one intentionally inaccessible element. That element is the lesson.</p>
</div>
<!-- ── Challenge preview frame ─────────────────────────────
The mock "Library Services" widget has three items.
Two are real <button> elements — keyboard accessible.
One is a <div onclick> — intentionally NOT accessible.
Do NOT add tabindex to the div. The unreachability is the point.
──────────────────────────────────────────────────────────── -->
<div class="preview-container al-challenge-frame">
<div class="preview-toolbar">
<div class="preview-toolbar__dots" aria-hidden="true">
<span class="preview-toolbar__dot"></span>
<span class="preview-toolbar__dot"></span>
<span class="preview-toolbar__dot"></span>
</div>
<span class="preview-toolbar__label">Library website — Services widget</span>
</div>
<div class="al-preview-display">
<div class="al-services-box">
<h3 class="al-hours-heading">Library Services</h3>
<div class="al-services-list">
<!-- Real <button> — keyboard accessible -->
<button class="al-service-item" data-item="1">Reserve a study room</button>
<!--
INTENTIONALLY a <div>, not a <button> — demonstrates keyboard inaccessibility.
This element is genuinely unreachable via the Tab key by design.
Do NOT add tabindex, role="button", or aria-label here.
(WCAG 2.1 SC 2.1.1 Keyboard, Level A; SC 4.1.2 Name, Role, Value, Level A)
-->
<div class="al-service-item" onclick="window.selectItem(2)" data-item="2">
Interlibrary loan
<span class="al-mouse-only-label" hidden>mouse only</span>
</div>
<!-- Real <button> — keyboard accessible -->
<button class="al-service-item" data-item="3">Ask a librarian</button>
</div>
</div>
</div>
<div class="al-preview-controls">
<ol class="al-steps">
<li class="al-step">
<span class="al-step__num" aria-hidden="true">1</span>
<div class="al-step__body">
<p class="al-step__prompt">Use only your keyboard. Press <kbd>Tab</kbd> to move between options, <kbd>Enter</kbd> to select. Try to reach all three services.</p>
<p class="al-step__hint">Click somewhere neutral first to clear focus, then Tab in from the top.</p>
<div id="s3-feedback" hidden></div>
</div>
</li>
<li class="al-step">
<span class="al-step__num" aria-hidden="true">2</span>
<div class="al-step__body">
<p class="al-step__prompt">Found a dead end? See what’s happening in the code.</p>
<div class="al-step__actions">
<button id="s3-reveal-btn" class="btn btn--ghost btn--sm" hidden>
Show what’s happening →
</button>
</div>
</div>
</li>
</ol>
</div>
</div><!-- /preview-container -->
<!-- Code explanation (shown when s3Revealed = true) -->
<div id="s3-explanation" class="al-explanation" hidden>
“Reserve a study room” and “Ask a librarian” are real
<code class="al-code-tag al-code-tag--green"><button></code>
elements — naturally focusable and keyboard-activatable.
“Interlibrary loan” is a
<code class="al-code-tag al-code-tag--orange"><div></code>
with an
<code class="al-code-tag al-code-tag--orange">onclick</code>.
It looks identical on screen but is invisible to keyboard navigation.
</div>
<!-- What this reveals -->
<div class="panel panel--featured al-insight-panel" role="note">
<div class="panel__header">
<div class="panel__icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/></svg>
</div>
<h2 class="panel__title">What this reveals</h2>
</div>
<div class="panel__body">
<p>You can see all three options. Tab reaches “Reserve a study room” and “Ask a librarian.” “Interlibrary loan” is skipped entirely. Without a mouse, there is no way to reach it.</p>
<p>This happens because “Interlibrary loan” is a <code><div></code> element with an <code>onclick</code> handler. Unlike <code><button></code>, a <code><div></code> is not in the keyboard focus sequence by default. Screen readers also cannot announce it as an interactive control.</p>
<p>Changing <code><div></code> to <code><button></code> is one word in the code. For a keyboard user, that word determines whether a library service is reachable.</p>
</div>
</div>
<!-- Key ideas -->
<div class="panel panel--featured al-key-ideas-panel" role="note">
<div class="panel__header">
<div class="panel__icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="8" x2="21" y1="6" y2="6"/><line x1="8" x2="21" y1="12" y2="12"/><line x1="8" x2="21" y1="18" y2="18"/><line x1="3" x2="3.01" y1="6" y2="6"/><line x1="3" x2="3.01" y1="12" y2="12"/><line x1="3" x2="3.01" y1="18" y2="18"/></svg>
</div>
<h3 class="panel__title">Key ideas</h3>
</div>
<div class="panel__body">
<ul>
<li>Keyboard-only navigation is the baseline test for most assistive technologies. If Tab cannot reach it, the option is effectively invisible.</li>
<li>A <code><div onclick></code> looks and behaves like a button for mouse users. For keyboard and screen reader users, it does not exist as an interactive element.</li>
<li>One word in the code (<code>div</code> → <code>button</code>) opens or closes access to a library service for every patron who navigates without a mouse.</li>
<li>26% of people with disabilities rely on some form of keyboard-based navigation. Keyboard accessibility is not an edge case.</li>
</ul>
</div>
</div>
<!-- ── Key standards (take-aways) ─────────────────────── -->
<div class="panel panel--featured al-insight-panel" role="note" style="margin-top: var(--space-6);">
<div class="panel__header">
<div class="panel__icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
</div>
<h2 class="panel__title">Key standards</h2>
</div>
<div class="panel__body">
<p>WCAG (Web Content Accessibility Guidelines) is the international standard for digital accessibility. Each success criterion is assigned a conformance level: A is the baseline, AA is what most organizations target, and AAA covers enhanced requirements. This activity covered two WCAG criteria:</p>
<div class="table-wrap">
<table class="table table--bordered">
<thead>
<tr>
<th>Criterion</th>
<th class="al-cell-center">Level</th>
<th>What it requires</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>2.1.1</strong> Keyboard</td>
<td class="al-cell-center"><span class="badge badge--neutral">A</span></td>
<td>All functionality is available from a keyboard</td>
</tr>
<tr>
<td><strong>4.1.2</strong> Name, Role, Value</td>
<td class="al-cell-center"><span class="badge badge--neutral">A</span></td>
<td>UI components must expose name, role, and state to assistive technologies</td>
</tr>
</tbody>
</table>
</div>
<p>The full WCAG 2.1 specification includes 78 success criteria across all three levels.</p>
</div>
</div>