Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve accessibility #659

Merged
merged 7 commits into from
Jan 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
mkdocs-material-2.4.0 (2017-01-11)

* Added focus state for clipboard buttons
* Fixed #400: Search bar steals tab focus
* Fixed search not closing on ENTER when result is selected
* Fixed search not closing when losing focus due to TAB
* Fixed collapsed navigation links getting focus
* Fixed outline being cut off on TAB focus of navigation links
* Fixed bug with first search result navigation being ignored
* Removed search result navigation via TAB (use UP and DOWN)
* Removed outline resets for links
* Improved general tabbing behavior on desktop

mkdocs-material-2.3.0 (2017-01-09)

* Added example (synonym: snippet) style for Admonition
Expand Down
17 changes: 16 additions & 1 deletion docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ To determine the currently installed version, use the following command:

``` sh
pip show mkdocs-material | grep -E ^Version
# Version 2.3.0
# Version 2.4.0
```

### Material 1.x to 2.x
Expand All @@ -38,6 +38,21 @@ pip show mkdocs-material | grep -E ^Version

## Changelog

### 2.4.0 <small>_ January 11, 2018</small>

* Added focus state for clipboard buttons
* Fixed [#400][400]: Search bar steals tab focus
* Fixed search not closing on ++enter++ when result is selected
* Fixed search not closing when losing focus due to ++tab++
* Fixed collapsed navigation links getting focus
* Fixed `outline` being cut off on ++tab++ focus of navigation links
* Fixed bug with first search result navigation being ignored
* Removed search result navigation via ++tab++ (use ++up++ and ++down++)
* Removed `outline` resets for links
* Improved general tabbing behavior on desktop

[400]: https://github.com/squidfunk/mkdocs-material/issues/400

### 2.3.0 <small>_ January 9, 2018</small>

* Added `example` (synonym: `snippet`) style for Admonition
Expand Down
1 change: 0 additions & 1 deletion material/assets/javascripts/application.206c856d.js

This file was deleted.

1 change: 1 addition & 0 deletions material/assets/javascripts/application.d5140e78.js

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions material/assets/stylesheets/application.0e9c8aca.css

This file was deleted.

2 changes: 2 additions & 0 deletions material/assets/stylesheets/application.7fb6a6f0.css

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions material/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<meta name="lang:{{ key }}" content="{{ lang.t(key) }}">
{% endfor %}
<link rel="shortcut icon" href="{{ base_url }}/{{ config.theme.favicon }}">
<meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-2.3.0">
<meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-2.4.0">
{% endblock %}
{% block htmltitle %}
{% if page and page.meta and page.meta.title %}
Expand All @@ -46,7 +46,7 @@
{% endif %}
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application.0e9c8aca.css">
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application.7fb6a6f0.css">
{% if palette.primary or palette.accent %}
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-palette.792431c1.css">
{% endif %}
Expand Down Expand Up @@ -167,7 +167,7 @@ <h2 id="__comments">{{ lang.t("meta.comments") }}</h2>
{% endblock %}
</div>
{% block scripts %}
<script src="{{ base_url }}/assets/javascripts/application.206c856d.js"></script>
<script src="{{ base_url }}/assets/javascripts/application.d5140e78.js"></script>
{% if lang.t("search.language") != "en" %}
{% set languages = lang.t("search.language").split(",") %}
{% if languages | length and languages[0] != "" %}
Expand Down
8 changes: 5 additions & 3 deletions material/partials/search.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
{% import "partials/language.html" as lang with context %}
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="search"></label>
<div class="md-search__inner">
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" required placeholder="{{ lang.t('search.placeholder') }}" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query">
<input type="text" class="md-search__input" name="query" placeholder="{{ lang.t('search.placeholder') }}" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset">&#xE5CD;</button>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ markdown_extensions:
- pymdownx.emoji:
emoji_generator: !!python/name:pymdownx.emoji.to_svg
- pymdownx.inlinehilite
- pymdownx.keys
- pymdownx.magiclink
- pymdownx.mark
- pymdownx.smartsymbols
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mkdocs-material",
"version": "2.3.0",
"version": "2.4.0",
"description": "A Material Design theme for MkDocs",
"keywords": [
"mkdocs",
Expand Down
37 changes: 31 additions & 6 deletions src/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,32 @@ function initialize(config) { // eslint-disable-line func-style
})
})).listen()

/* Listener: handle tabbing context for better accessibility */
new Material.Event.Listener(document.body, "keydown", ev => {
if (ev.keyCode === 9) {
const labels = document.querySelectorAll(
"[data-md-component=navigation] .md-nav__link[for]:not([tabindex])")
Array.prototype.forEach.call(labels, label => {
if (label.offsetHeight)
label.tabIndex = 0
})
}
}).listen()

/* Listener: reset tabbing behavior */
new Material.Event.Listener(document.body, "mousedown", () => {
const labels = document.querySelectorAll(
"[data-md-component=navigation] .md-nav__link[tabindex]")
Array.prototype.forEach.call(labels, label => {
label.removeAttribute("tabIndex")
})
}).listen()

document.body.addEventListener("click", () => {
if (document.body.dataset.mdState === "tabbing")
document.body.dataset.mdState = ""
})

/* Listener: close drawer when anchor links are clicked */
new Material.Event.MatchMedia("(max-width: 959px)",
new Material.Event.Listener("[data-md-component=navigation] [href^='#']",
Expand Down Expand Up @@ -381,8 +407,8 @@ function initialize(config) { // eslint-disable-line func-style
}
}

/* Escape: close search */
} else if (ev.keyCode === 27) {
/* Escape or Tab: close search */
} else if (ev.keyCode === 9 || ev.keyCode === 27) {
toggle.checked = false
toggle.dispatchEvent(new CustomEvent("change"))
query.blur()
Expand All @@ -392,10 +418,9 @@ function initialize(config) { // eslint-disable-line func-style
if (query !== document.activeElement)
query.focus()

/* Vertical arrows and tab: select previous or next search result */
} else if ([9, 38, 40].indexOf(ev.keyCode) !== -1) {
const map = ev.shiftKey ? 38 : 40
const key = ev.keyCode === 9 ? map : ev.keyCode
/* Vertical arrows: select previous or next search result */
} else if ([38, 40].indexOf(ev.keyCode) !== -1) {
const key = ev.keyCode

/* Retrieve all results */
const links = Array.prototype.slice.call(
Expand Down
23 changes: 23 additions & 0 deletions src/assets/javascripts/components/Material/Nav/Collapse.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ export default class Collapse {
this.el_ = ref
}

/**
* Initialize overflow and display for accessibility
*/
setup() {
const current = this.el_.getBoundingClientRect().height

/* Hidden links should not be focusable, so hide them when the navigation
is collapsed and set overflow so the outline is not cut off */
this.el_.style.display = current ? "block" : "none"
this.el_.style.overflow = current ? "visible" : "hidden"
}

/**
* Animate expand and collapse smoothly
*
Expand All @@ -54,6 +66,10 @@ export default class Collapse {
update() {
const current = this.el_.getBoundingClientRect().height

/* Reset overflow to CSS defaults */
this.el_.style.display = "block"
this.el_.style.overflow = ""

/* Expanded, so collapse */
if (current) {
this.el_.style.maxHeight = `${current}px`
Expand Down Expand Up @@ -89,6 +105,11 @@ export default class Collapse {
target.removeAttribute("data-md-state")
target.style.maxHeight = ""

/* Hidden links should not be focusable, so hide them when the navigation
is collapsed and set overflow so the outline is not cut off */
target.style.display = current ? "none" : "block"
target.style.overflow = current ? "hidden" : "visible"

/* Only fire once, so directly remove event listener */
target.removeEventListener("transitionend", end)
}
Expand All @@ -101,5 +122,7 @@ export default class Collapse {
reset() {
this.el_.dataset.mdState = ""
this.el_.style.maxHeight = ""
this.el_.style.display = ""
this.el_.style.overflow = ""
}
}
39 changes: 23 additions & 16 deletions src/assets/javascripts/components/Material/Search/Result.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export default class Result {
const article = (
<li class="md-search-result__item">
<a href={doc.location} title={doc.title}
class="md-search-result__link">
class="md-search-result__link" tabindex="-1">
<article class="md-search-result__article
md-search-result__article--document">
<h1 class="md-search-result__title">
Expand All @@ -297,7 +297,8 @@ export default class Result {
const section = this.docs_.get(item.ref)
article.appendChild(
<a href={section.location} title={section.title}
class="md-search-result__link" data-md-rel="anchor">
class="md-search-result__link" data-md-rel="anchor"
tabindex="-1">
<article class="md-search-result__article">
<h1 class="md-search-result__title">
{{ __html: section.title.replace(match, highlight) }}
Expand Down Expand Up @@ -329,21 +330,27 @@ export default class Result {
/* Bind click handlers for anchors */
const anchors = this.list_.querySelectorAll("[data-md-rel=anchor]")
Array.prototype.forEach.call(anchors, anchor => {
anchor.addEventListener("click", ev2 => {
const toggle = document.querySelector("[data-md-toggle=search]")
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (toggle.checked) {
toggle.checked = false
toggle.dispatchEvent(new CustomEvent("change"))
}
["click", "keydown"].forEach(action => {
anchor.addEventListener(action, ev2 => {
if (action === "keydown" && ev2.keyCode !== 13)
return

/* Close search */
const toggle = document.querySelector("[data-md-toggle=search]")
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (toggle.checked) {
toggle.checked = false
toggle.dispatchEvent(new CustomEvent("change"))
}

/* Hack: prevent default, as the navigation needs to be delayed due
to the search body lock on mobile */
ev2.preventDefault()
setTimeout(() => {
document.location.href = anchor.href
}, 100)
/* Hack: prevent default, as the navigation needs to be delayed due
to the search body lock on mobile */
ev2.preventDefault()
setTimeout(() => {
document.location.href = anchor.href
}, 100)
})
})
})

Expand Down
8 changes: 1 addition & 7 deletions src/assets/stylesheets/base/_reset.scss
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,6 @@ input {
a {
color: inherit;
text-decoration: none;

// Remove outline on focused or active links
&:active,
&:hover {
outline-width: 0;
}
}

// Normalize font-size in all browsers
Expand Down Expand Up @@ -125,7 +119,7 @@ th {
button {
padding: 0;
border: 0;
outline: 0;
outline-style: none;
background: transparent;
font-size: inherit;
}
Expand Down
2 changes: 1 addition & 1 deletion src/assets/stylesheets/base/_typeset.scss
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ kbd {

padding: 0 0.25em * $correct;
border: 0.1rem solid darken($md-keyboard-background, 20%);
border-radius: 0.2rem;
border-radius: 0.3rem;
border-bottom-color: darken($md-keyboard-background, 25%);
background-color: $md-keyboard-background;
color: $md-keyboard-color;
Expand Down
11 changes: 5 additions & 6 deletions src/assets/stylesheets/layout/_clipboard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,19 @@
transition:
color 0.25s,
opacity 0.25s;
color: $md-color-black--light;
color: $md-color-black--lightest;
content: "\E14D"; // content_copy
opacity: 0.25;

// Show on container hover
pre:hover &,
.codehilite:hover & {
opacity: 1;
color: $md-color-black--light;
}
}

// Hovered and active icon
&:hover::before,
&:active::before {
// Focused or hovered icon
&:focus::before,
&:hover::before {
color: $md-color-accent;
}

Expand Down
10 changes: 10 additions & 0 deletions src/assets/stylesheets/layout/_nav.scss
Original file line number Diff line number Diff line change
Expand Up @@ -395,12 +395,22 @@
.md-nav__toggle ~ & {
max-height: 0;
overflow: hidden;

// Just hide links for accessibility if JavaScript is not available
.no-js & {
display: none;
}
}

// Expand nested navigation, if toggle is checked
.md-nav__toggle:checked ~ &,
&[data-md-state="expand"] {
max-height: 100%;

// Just show for accessibility links if JavaScript is not available
.no-js & {
display: block;
}
}

// Hide titles for nested navigation
Expand Down