Skip to content

Commit fc4b5a2

Browse files
authored
Merge pull request #770 from BitcoinDesign/feature/accessibility-fixes
Added Skip to content button + other a11y fixes
2 parents 3e5e3c5 + 78b7fad commit fc4b5a2

File tree

8 files changed

+109
-39
lines changed

8 files changed

+109
-39
lines changed

_includes/header.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
{%- if my_page.title -%}
1919
{% assign current_page = page.url | replace:'/',' ' | truncatewords: 1,"" %}
2020
{% assign menu_page = my_page.url | replace:'/',' ' | truncatewords: 1,"" %}
21-
<a class="page-link{% if current_page == menu_page %} active{% endif %}" href="{{ my_page.url | relative_url }}">{{ my_page.title | escape }}</a>
21+
<a class="page-link{% if current_page == menu_page %} active{% endif %}" href="{{ my_page.url | relative_url }}"{% if page.url == my_page.url %} aria-current="page"{% endif %}>{{ my_page.title | escape }}</a>
2222

2323
{%- if my_page.title contains 'Guide' -%}
2424
{% include secondary-nav.html id="top" %}
@@ -32,7 +32,7 @@
3232
<svg viewBox="0 0 44 44" class="search-icon"><use xlink:href="#svg-search"></use></svg>
3333
</button>
3434

35-
<button aria-label="Toggle menu" id="nav-trigger" class="nav-trigger" aria-controls="site-nav" aria-expanded="false">
35+
<button aria-label="Toggle menu" id="nav-trigger" class="nav-trigger" aria-controls="site-nav" aria-expanded="false" aria-haspopup="true">
3636
<svg viewBox="0 0 44 44"><use xlink:href="#svg-menu"></use></svg>
3737
</button>
3838

_includes/secondary-nav.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
{%- if node.has_children -%}
3636
<button class="nav-list-expander" aria-expanded="false" aria-controls="nav-list-{{ forloop.index }}" title="Toggle list"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></button>
3737
{%- endif -%}
38-
<a href="{{ node.url | relative_url }}" class="nav-list-link{% if page.url == node.url %} -active{% endif %}">{%- if node.secondary_nav_title -%}{{ node.secondary_nav_title }}{%- else -%}{{ node.title }}{%- endif -%}</a>
38+
<a href="{{ node.url | relative_url }}" class="nav-list-link{% if page.url == node.url %} -active{% endif %}"{% if page.url == node.url %} aria-current="page"{% endif %}>{%- if node.secondary_nav_title -%}{{ node.secondary_nav_title }}{%- else -%}{{ node.title }}{%- endif -%}</a>
3939
{%- if node.has_children -%}
4040
{%- assign children_list = pages_list | where: "parent", node.title -%}
4141
<ul class="nav-list" id="nav-list-{{ include.id | default: "1" }}-{{ forloop.index }}">
@@ -45,13 +45,13 @@
4545
{%- if page.url == child.url or page.parent == child.title -%}
4646
{%- assign second_level_url = child.url | relative_url -%}
4747
{%- endif -%}
48-
<a href="{{ child.url | relative_url }}" class="nav-list-link{% if page.url == child.url %} -active{% endif %}">{{ child.title }}</a>
48+
<a href="{{ child.url | relative_url }}" class="nav-list-link{% if page.url == child.url %} -active{% endif %}"{% if page.url == child.url %} aria-current="page"{% endif %}>{{ child.title }}</a>
4949
{%- if child.has_children -%}
5050
{%- assign grand_children_list = pages_list | where: "parent", child.title | where: "grand_parent", node.title -%}
5151
<ul class="nav-list">
5252
{%- for grand_child in grand_children_list -%}
5353
<li class="nav-list-item {% if page.url == grand_child.url %} -active{% endif %}">
54-
<a href="{{ grand_child.url | relative_url }}" class="nav-list-link{% if page.url == grand_child.url %} -active{% endif %}">{{ grand_child.title }}</a>
54+
<a href="{{ grand_child.url | relative_url }}" class="nav-list-link{% if page.url == grand_child.url %} -active{% endif %}"{% if page.url == grand_child.url %} aria-current="page"{% endif %}>{{ grand_child.title }}</a>
5555
</li>
5656
{%- endfor -%}
5757
</ul>

_includes/svgs.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
<symbol id="svg-search" viewBox="0 0 44 44">
1010
<title>Search</title>
1111
<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor">
12-
<path d="M29.543 20.1474C29.543 24.9654 25.5061 28.9282 20.4548 28.9282C15.4036 28.9282 11.3667 24.9654 11.3667 20.1474C11.3667 15.3295 15.4036 11.3667 20.4548 11.3667C25.5061 11.3667 29.543 15.3295 29.543 20.1474Z" stroke="black" stroke-width="2.2"/>
13-
<line y1="-1.1" x2="9.18598" y2="-1.1" transform="matrix(0.739399 0.673268 -0.739399 0.673268 26.5678 27.1004)" stroke="black" stroke-width="2.2"/>
12+
<path d="M29.543 20.1474C29.543 24.9654 25.5061 28.9282 20.4548 28.9282C15.4036 28.9282 11.3667 24.9654 11.3667 20.1474C11.3667 15.3295 15.4036 11.3667 20.4548 11.3667C25.5061 11.3667 29.543 15.3295 29.543 20.1474Z" stroke="currentColor" stroke-width="2.2"/>
13+
<line y1="-1.1" x2="9.18598" y2="-1.1" transform="matrix(0.739399 0.673268 -0.739399 0.673268 26.5678 27.1004)" stroke="currentColor" stroke-width="2.2"/>
1414
</svg>
1515
</symbol>
1616
<symbol id="svg-menu" viewBox="0 0 44 44">

_layouts/default.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
<body class="{% if page.path contains 'guide' %}sidebar{% endif %}">
77

8+
<a class="skip-to-content-link" href="#main">
9+
Skip to content
10+
</a>
11+
812
{%- include svgs.html -%}
913
{%- include header.html -%}
1014

@@ -33,7 +37,7 @@ <h3>
3337
</div>
3438
{%- endif -%}
3539

36-
<div class="main{% if page.path contains 'guide' %} sidebar{% endif %}{% if page.main_classes %} {{ page.main_classes }}{% endif %}" id="top">
40+
<div class="main{% if page.path contains 'guide' %} sidebar{% endif %}{% if page.main_classes %} {{ page.main_classes }}{% endif %}" id="main">
3741

3842
{{ content }}
3943

_sass/minima/_base.scss

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ main {
6969
display: block; /* Default value of `display` of `main` element is 'inline' in IE 11. */
7070
}
7171

72-
72+
a:focus-visible,
73+
button:focus-visible {
74+
outline: 4px solid rgba($primary-color, 0.6);
75+
outline-offset: 1px;
76+
}
7377

7478
/**
7579
* Images
@@ -588,3 +592,22 @@ figcaption {
588592
position: absolute;
589593
left: -999rem;
590594
}
595+
596+
a.skip-to-content-link {
597+
position: absolute;
598+
left: 50%;
599+
padding: 7px 15px;
600+
transform: translate(-50%, -100%);
601+
z-index: 12;
602+
font-size: 15px;
603+
font-weight: 500;
604+
color: white;
605+
background: #e77e23;
606+
border-bottom-left-radius: 5px;
607+
border-bottom-right-radius: 5px;
608+
transition: transform 150ms $ease;
609+
610+
&:focus {
611+
transform: translate(-50%, 0%);
612+
}
613+
}

_sass/minima/_nav-list.scss

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
height: 30px;
7474
background-color: transparent;
7575
border-width: 0;
76-
appearance: none;
7776

7877
svg {
7978
width: 15px;
@@ -85,7 +84,6 @@
8584
&:active,
8685
&:focus {
8786
border-width: 0;
88-
outline: none;
8987
background-color: rgba($primary-color, 0.1);
9088
}
9189

_sass/minima/_site-header.scss

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@
2828
letter-spacing: -0.5px;
2929
color: var(--frontHex);
3030
transition: color 100ms $ease;
31-
outline: none;
31+
// outline: none;
3232
white-space: nowrap;
3333

34+
&:focus {
35+
outline: 2px solid $primary-color;
36+
}
37+
3438
svg {
3539
width: 40px;
3640
height: 40px;
@@ -75,6 +79,10 @@
7579
text-decoration: none;
7680
}
7781

82+
&:focus {
83+
background-color: rgba($primary-color, 0.1);
84+
}
85+
7886
&.active {
7987
color: $primary-color;
8088
}
@@ -93,8 +101,6 @@
93101
background-color: transparent;
94102
padding: 0;
95103
width: 60px;
96-
outline: none;
97-
margin-left: 10px;
98104

99105
svg {
100106
width: 44px;
@@ -132,7 +138,6 @@
132138
box-shadow: 0 10px 25px -5px rgba(var(--front), 0.1);
133139
border-bottom-left-radius: 3px;
134140
border-bottom-right-radius: 3px;
135-
// border-bottom: 1px solid rgba(var(--front), 0.1);
136141

137142
form {
138143
position: relative;
@@ -152,7 +157,6 @@
152157

153158
&:focus {
154159
outline: none;
155-
156160
}
157161
}
158162
}
@@ -163,16 +167,6 @@
163167

164168
form {
165169
border: 1px solid rgba(var(--front), 0.05);
166-
// &:before {
167-
// display: block;
168-
// content: '';
169-
// position: absolute;
170-
// top: 0;
171-
// left: 0;
172-
// width: 100%;
173-
// height: 100%;
174-
// border: 1px solid $primary-color;
175-
// }
176170
}
177171
}
178172

@@ -253,7 +247,7 @@
253247
background-color: transparent;
254248
padding: 0;
255249
border-width: 0;
256-
outline: none;
250+
// outline: none;
257251

258252
svg {
259253
width: 44px;
@@ -367,9 +361,11 @@
367361
.site-nav {
368362
display: flex;
369363
margin-left: auto;
364+
gap: 20px;
370365

371366
.page-link {
372-
margin-left: 40px;
367+
padding-left: 10px;
368+
padding-right: 10px;
373369

374370
&:after {
375371
display: block;

js/scripts.js

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var searchOverlayVisible = false;
66
var mobileMenuVisible = false;
77
var figmaEmbeds = [];
88
var ref = {};
9+
var isMobile = window.innerWidth <= 1024;
910

1011
function toggleMenu() {
1112
if(mobileMenuVisible) {
@@ -16,8 +17,6 @@ function toggleMenu() {
1617
};
1718

1819
function updateNavAccessibility() {
19-
var isMobile = window.innerWidth <= 375;
20-
2120
ref.navTrigger.setAttribute("aria-hidden", !isMobile);
2221
ref.siteNav.setAttribute("aria-hidden", isMobile);
2322

@@ -34,10 +33,17 @@ function showMenu() {
3433

3534
// Update nav menu accessibility properties
3635
ref.siteNav.removeAttribute("hidden");
36+
ref.siteNav.setAttribute("aria-hidden", false);
3737

3838
setTimeout(function() {
3939
ref.header.classList.add('-active');
40-
}, 5);
40+
41+
// Focus on the first nav item
42+
var links = ref.siteNav.getElementsByTagName('a');
43+
if(links.length > 0) {
44+
links[0].focus();
45+
}
46+
}, 50);
4147

4248
if(searchOverlayVisible) {
4349
hideSearchOverlay();
@@ -53,6 +59,7 @@ function hideMenu() {
5359

5460
setTimeout(function() {
5561
ref.siteNav.setAttribute("hidden", "hidden");
62+
ref.siteNav.setAttribute("aria-hidden", true);
5663
}, 400);
5764
};
5865

@@ -195,10 +202,10 @@ function toggleSecondaryNav(event) {
195202

196203
if(navListItem.classList.contains('-active')) {
197204
navListItem.classList.remove('-active');
198-
navListItem.setAttribute('aria-expanded', false);
205+
event.currentTarget.setAttribute('aria-expanded', false);
199206
} else {
200207
navListItem.classList.add('-active');
201-
navListItem.setAttribute('aria-expanded', true);
208+
event.currentTarget.setAttribute('aria-expanded', true);
202209
}
203210
}
204211

@@ -344,10 +351,8 @@ function handleModalImageLinkClick(e) {
344351
});
345352
}
346353

347-
var mobile = window.innerWidth < 640;
348-
349354
ref.modalImageContainer.classList.add('loading');
350-
if(mobile && imgTag.dataset.modalWidthMobile && imgTag.dataset.modalHeightMobile) ref.modalImageDimensions = [imgTag.dataset.modalWidthMobile, imgTag.dataset.modalHeightMobile];
355+
if(isMobile && imgTag.dataset.modalWidthMobile && imgTag.dataset.modalHeightMobile) ref.modalImageDimensions = [imgTag.dataset.modalWidthMobile, imgTag.dataset.modalHeightMobile];
351356
else if(imgTag.dataset.modalWidth && imgTag.dataset.modalHeight) ref.modalImageDimensions = [imgTag.dataset.modalWidth, imgTag.dataset.modalHeight];
352357
else ref.modalImageDimensions = [imgTag.getAttribute('width'), imgTag.getAttribute('height')];
353358
ref.modalImage.setAttribute('width', ref.modalImageDimensions[0]);
@@ -374,7 +379,7 @@ function handleModalImageLinkClick(e) {
374379

375380
var img,
376381
modalLink = imgTag.closest('.modal-image-link');
377-
if(mobile && modalLink.dataset.modalImageMobile) img = modalLink.dataset.modalImageMobile;
382+
if(isMobile && modalLink.dataset.modalImageMobile) img = modalLink.dataset.modalImageMobile;
378383
else img = modalLink.getAttribute('href');
379384

380385
var request = new Request(img);
@@ -577,11 +582,53 @@ function decideIfLottie(){
577582
}
578583

579584
window.addEventListener("resize", function(event) {
585+
isMobile = window.innerWidth <= 1024;
586+
580587
resizeFigmaEmbeds();
581588
resizeModal();
582589
})
583590

591+
// Adds keyup listeners to links in the mobile nav.
592+
setupMobileNavLinkKeyboardNavigation = function() {
593+
var navLinks = ref.siteNav.getElementsByTagName('a');
594+
if(navLinks.length > 0) {
595+
for(var i=0; i<navLinks.length; i++) {
596+
navLinks[i].setAttribute('data-index', i);
597+
navLinks[i].addEventListener('keyup', onMobileNavLinkKeyUp);
598+
}
599+
}
600+
};
601+
602+
// Handles arrow up/down and escape for mobile nav links.
603+
onMobileNavLinkKeyUp = function(event) {
604+
if(isMobile && mobileMenuVisible) {
605+
if(event.which == 38 || event.which == 40) {
606+
// Select previous or next menu option.
607+
event.preventDefault();
608+
var index = parseInt(event.target.getAttribute('data-index'));
609+
var navLinks = ref.siteNav.getElementsByTagName('a');
610+
var direction = event.which == 38 ? -1 : 1;
611+
var newIndex = index + direction;
612+
if(newIndex < 0) newIndex = navLinks.length - 1;
613+
if(newIndex >= navLinks.length) newIndex = 0;
614+
var newLink = navLinks[newIndex];
615+
while(newLink.offsetParent === null) {
616+
newIndex += direction;
617+
if(newIndex < 0) newIndex = navLinks.length - 1;
618+
if(newIndex >= navLinks.length) newIndex = 0;
619+
newLink = navLinks[newIndex];
620+
}
621+
newLink.focus();
622+
} else if(event.which == 27) {
623+
// Escape closes the menu
624+
hideMenu();
625+
}
626+
}
627+
};
628+
584629
document.addEventListener("DOMContentLoaded", function(event) {
630+
isMobile = window.innerWidth <= 1024;
631+
585632
ref.header = document.getElementById("site-header");
586633
ref.siteNav = document.getElementById('site-nav');
587634
ref.navTrigger = document.getElementById("nav-trigger");
@@ -609,6 +656,8 @@ document.addEventListener("DOMContentLoaded", function(event) {
609656

610657
if(ref.navTrigger) {
611658
ref.navTrigger.addEventListener('click', toggleMenu);
659+
660+
setupMobileNavLinkKeyboardNavigation();
612661
}
613662

614663
var secondaryNavListExpander = document.getElementsByClassName("nav-list-expander");
@@ -621,7 +670,7 @@ document.addEventListener("DOMContentLoaded", function(event) {
621670

622671
setupUnitsAndSymbolsFormatter();
623672

624-
for(var i = 0; i < ref.modalImageLinks.length; i++) {
625-
ref.modalImageLinks[i].addEventListener('click', handleModalImageLinkClick);
673+
for(var k=0; i<ref.modalImageLinks.length; k++) {
674+
ref.modalImageLinks[k].addEventListener('click', handleModalImageLinkClick);
626675
}
627676
});

0 commit comments

Comments
 (0)