Fixed lost tab focus on collapsible navigation

This commit is contained in:
squidfunk 2018-01-11 20:42:30 +01:00 committed by Martin Donath
parent 809f943240
commit 7a0c464ed6
11 changed files with 47 additions and 13 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -46,7 +46,7 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block styles %} {% block styles %}
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application.cab7c440.css"> <link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application.4b085d0e.css">
{% if palette.primary or palette.accent %} {% if palette.primary or palette.accent %}
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-palette.792431c1.css"> <link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-palette.792431c1.css">
{% endif %} {% endif %}
@ -167,7 +167,7 @@
{% endblock %} {% endblock %}
</div> </div>
{% block scripts %} {% block scripts %}
<script src="{{ base_url }}/assets/javascripts/application.a2b571e1.js"></script> <script src="{{ base_url }}/assets/javascripts/application.24b6416b.js"></script>
{% if lang.t("search.language") != "en" %} {% if lang.t("search.language") != "en" %}
{% set languages = lang.t("search.language").split(",") %} {% set languages = lang.t("search.language").split(",") %}
{% if languages | length and languages[0] != "" %} {% if languages | length and languages[0] != "" %}

View File

@ -9,11 +9,11 @@
{% else %} {% else %}
<input class="md-toggle md-nav__toggle" data-md-toggle="{{ path }}" type="checkbox" id="{{ path }}"> <input class="md-toggle md-nav__toggle" data-md-toggle="{{ path }}" type="checkbox" id="{{ path }}">
{% endif %} {% endif %}
<label class="md-nav__link" for="{{ path }}"> <label class="md-nav__link" for="{{ path }}" tabindex="0">
{{ nav_item.title }} {{ nav_item.title }}
</label> </label>
<nav class="md-nav" data-md-component="collapsible" data-md-level="{{ level }}"> <nav class="md-nav" data-md-component="collapsible" data-md-level="{{ level }}">
<label class="md-nav__title" for="{{ path }}"> <label class="md-nav__title" for="{{ path }}" tabindex="0">
{{ nav_item.title }} {{ nav_item.title }}
</label> </label>
<ul class="md-nav__list" data-md-scrollfix> <ul class="md-nav__list" data-md-scrollfix>
@ -34,7 +34,7 @@
{% set toc_ = (toc_ | first).children %} {% set toc_ = (toc_ | first).children %}
{% endif %} {% endif %}
{% if toc_ | first is defined %} {% if toc_ | first is defined %}
<label class="md-nav__link md-nav__link--active" for="toc"> <label class="md-nav__link md-nav__link--active" for="toc" tabindex="0">
{{ nav_item.title }} {{ nav_item.title }}
</label> </label>
{% endif %} {% endif %}

View File

@ -3,7 +3,7 @@
<label class="md-search__overlay" for="search"></label> <label class="md-search__overlay" for="search"></label>
<div class="md-search__inner" role="search"> <div class="md-search__inner" role="search">
<form class="md-search__form" name="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" data-md-state="active"> <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> <label class="md-icon md-search__icon" for="search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1"> <button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD; &#xE5CD;

View File

@ -44,6 +44,18 @@ export default class Collapse {
this.el_ = ref 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 * Animate expand and collapse smoothly
* *
@ -54,6 +66,10 @@ export default class Collapse {
update() { update() {
const current = this.el_.getBoundingClientRect().height const current = this.el_.getBoundingClientRect().height
/* Reset overflow to CSS defaults */
this.el_.style.display = "block"
this.el_.style.overflow = ""
/* Expanded, so collapse */ /* Expanded, so collapse */
if (current) { if (current) {
this.el_.style.maxHeight = `${current}px` this.el_.style.maxHeight = `${current}px`
@ -89,6 +105,11 @@ export default class Collapse {
target.removeAttribute("data-md-state") target.removeAttribute("data-md-state")
target.style.maxHeight = "" 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 */ /* Only fire once, so directly remove event listener */
target.removeEventListener("transitionend", end) target.removeEventListener("transitionend", end)
} }
@ -101,5 +122,7 @@ export default class Collapse {
reset() { reset() {
this.el_.dataset.mdState = "" this.el_.dataset.mdState = ""
this.el_.style.maxHeight = "" this.el_.style.maxHeight = ""
this.el_.style.display = ""
this.el_.style.overflow = ""
} }
} }

View File

@ -395,12 +395,22 @@
.md-nav__toggle ~ & { .md-nav__toggle ~ & {
max-height: 0; max-height: 0;
overflow: hidden; overflow: hidden;
// Just hide links for accessibility if JavaScript is not available
.no-js & {
display: none;
}
} }
// Expand nested navigation, if toggle is checked // Expand nested navigation, if toggle is checked
.md-nav__toggle:checked ~ &, .md-nav__toggle:checked ~ &,
&[data-md-state="expand"] { &[data-md-state="expand"] {
max-height: 100%; max-height: 100%;
// Just show for accessibility links if JavaScript is not available
.no-js & {
display: block;
}
} }
// Hide titles for nested navigation // Hide titles for nested navigation

View File

@ -154,6 +154,7 @@
// Always expand nested navigation on 2nd level // Always expand nested navigation on 2nd level
.md-nav[data-md-level="1"] { .md-nav[data-md-level="1"] {
max-height: initial; max-height: initial;
overflow: visible;
// Remove left spacing on 2nd level items // Remove left spacing on 2nd level items
> .md-nav__list > .md-nav__item { > .md-nav__list > .md-nav__item {

View File

@ -40,12 +40,12 @@
{% endif %} {% endif %}
<!-- Expand active pages --> <!-- Expand active pages -->
<label class="md-nav__link" for="{{ path }}"> <label class="md-nav__link" for="{{ path }}" tabindex="0">
{{ nav_item.title }} {{ nav_item.title }}
</label> </label>
<nav class="md-nav" data-md-component="collapsible" <nav class="md-nav" data-md-component="collapsible"
data-md-level="{{ level }}"> data-md-level="{{ level }}">
<label class="md-nav__title" for="{{ path }}"> <label class="md-nav__title" for="{{ path }}" tabindex="0">
{{ nav_item.title }} {{ nav_item.title }}
</label> </label>
<ul class="md-nav__list" data-md-scrollfix> <ul class="md-nav__list" data-md-scrollfix>
@ -77,7 +77,7 @@
<!-- Render table of contents, if not empty --> <!-- Render table of contents, if not empty -->
{% if toc_ | first is defined %} {% if toc_ | first is defined %}
<label class="md-nav__link md-nav__link--active" for="toc"> <label class="md-nav__link md-nav__link--active" for="toc" tabindex="0">
{{ nav_item.title }} {{ nav_item.title }}
</label> </label>
{% endif %} {% endif %}

View File

@ -28,7 +28,7 @@
<div class="md-search__inner" role="search"> <div class="md-search__inner" role="search">
<form class="md-search__form" name="search"> <form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" <input type="text" class="md-search__input" name="query"
required placeholder="{{ lang.t('search.placeholder') }}" placeholder="{{ lang.t('search.placeholder') }}"
autocapitalize="off" autocorrect="off" autocomplete="off" autocapitalize="off" autocorrect="off" autocomplete="off"
spellcheck="false" data-md-component="query" spellcheck="false" data-md-component="query"
data-md-state="active" /> data-md-state="active" />