Skip to content

Commit

Permalink
Toc keyboard navigation (#4497)
Browse files Browse the repository at this point in the history
* Adds keyboard navigation to table of content links

Signed-off-by: Aaron Stephanus <[email protected]>

* Adds table of contents scroll and item focus management to the current page or the first toc item

Signed-off-by: Aaron Stephanus <[email protected]>

* Add space key capture to the toc expand/collapse arrows

Signed-off-by: Aaron Stephanus <[email protected]>

* Adds escape key support for expand/collapse of toc categories on the category label

Signed-off-by: Aaron Stephanus <[email protected]>

* Adds missing aria-role and aria-current attributes to toc affordances

Signed-off-by: Aaron Stephanus <[email protected]>

* Changes the function of the space bar to navigate to a toc parent category item instead of only expand its children

Signed-off-by: Aaron Stephanus <[email protected]>

* Adds arrow up/down key support to toc navigation

Signed-off-by: Aaron Stephanus <[email protected]>

* Adds missing accessibility attribute handling to the toc

Signed-off-by: Aaron Stephanus <[email protected]>

* Corrects arrow key handling of keyboard navigation of the toc

Signed-off-by: Aaron Stephanus <[email protected]>

* Adds padding to allow for the keyboard focus rectangle

Signed-off-by: Aaron Stephanus <[email protected]>

* Removes explicit tabindex values for the toc navigation

Signed-off-by: Aaron Stephanus <[email protected]>

* Removes auto focus of toc navigation items on page load; refactors navigation panel scroll into view logic to account for the sticky version selector

Signed-off-by: Aaron Stephanus <[email protected]>

* Removes keyboard focus trap on search field for the tab key

Signed-off-by: Aaron Stephanus <[email protected]>

* Unifies navigation item focus state for top level items and sub navigation items

Signed-off-by: Aaron Stephanus <[email protected]>

* Removes the expand/collapse navigation buttons from being tab focusable

Signed-off-by: Aaron Stephanus <[email protected]>

* Corrects navigation item spacing to permit visible focus rectangles

Signed-off-by: Aaron Stephanus <[email protected]>

* Implements full arrow navigation for the toc items according to the w3c tree view navigation pattern

Signed-off-by: Aaron Stephanus <[email protected]>

* Adds reference link to the w3c documentation about the tree view navigation to the arrow key toc navigation javascript

Signed-off-by: Aaron Stephanus <[email protected]>

* Account for the difference between the navigation panel height, and the viewport height when auto scrolling the toc item of the current page

Signed-off-by: Aaron Stephanus <[email protected]>

* Corrects keyboard navigation focus rectangles from being slightly obscured on the bottom

Signed-off-by: Aaron Stephanus <[email protected]>

* Corrects aria and role attributes according to the navigation tree pattern as opposed to the disclosure pattern

Signed-off-by: Aaron Stephanus <[email protected]>

* Corrects Jekyll include parameter assignment syntax error

Signed-off-by: Aaron Stephanus <[email protected]>

* Removes aria-expanded setting from the templates since it is unrealiable to determine without iterating through the entire tree to determine if one of its children of children is the current page

Signed-off-by: Aaron Stephanus <[email protected]>

* Moves setting of aria-expanded attributes to a runtime behavior, and corrects arrow left/right behavior on navigation tree items

Signed-off-by: Aaron Stephanus <[email protected]>

* Ensures unique navigation menu element ids; conditionally sets aira-owns and aria-current attributes

Signed-off-by: Aaron Stephanus <[email protected]>

* Removes JavaScript that is unused following refactoring tree view navigation; adds comments explaining choices

Signed-off-by: Aaron Stephanus <[email protected]>

---------

Signed-off-by: Aaron Stephanus <[email protected]>
  • Loading branch information
astephanus authored and vagimeli committed Dec 20, 2023
1 parent 3e20271 commit 230a5da
Show file tree
Hide file tree
Showing 5 changed files with 303 additions and 51 deletions.
61 changes: 49 additions & 12 deletions _includes/nav.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
<ul class="nav-list">
<ul
role="tree"
aria-expanded="{{ include.expanded | default: 'false' }}"
class="nav-list"
{%- if include.owned_tree_id -%}id="{{ include.owned_tree_id }}"{%- endif -%}
>
{%- assign titled_pages = include.pages
| where_exp:"item", "item.title != nil" -%}

Expand Down Expand Up @@ -56,32 +61,64 @@
{%- endfor -%}

{%- assign pages_list = sorted_number_ordered_pages | concat: sorted_string_ordered_pages -%}

{%- for node in pages_list -%}
{%- if node.parent == nil -%}
{%- unless node.nav_exclude -%}
<li class="nav-list-item{% if page.collection == include.key and page.url == node.url or page.parent == node.title or page.grand_parent == node.title %} active{% endif %}">
{% assign nested_owned_tree_id = include.owned_tree_id | append: "_" | append: forloop.index | append: "_" | append: node.title | append: "_navitems" | replace: " ", "_" %}
<li role="none" class="nav-list-item{% if page.collection == include.key and page.url == node.url or page.parent == node.title or page.grand_parent == node.title %} active{% endif %}">
{%- if node.has_children -%}
<a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
<a
role="treeitem"
aria-owns="{{ nested_owned_tree_id }}"
{%- if page.url == node.url -%}aria-current="page"{%- endif -%}
href="#"
class="nav-list-expander"
><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
{%- endif -%}
<a href="{{ node.url | absolute_url }}" class="nav-list-link{% if page.url == node.url %} active{% endif %}">{{ node.title }}</a>

<a
role="treeitem"
{%- if node.has_children -%}aria-owns="{{ nested_owned_tree_id }}"{%- endif -%}
{%- if page.url == node.url -%}aria-current="page"{%- endif -%}
href="{{ node.url | absolute_url }}"
class="nav-list-link{% if page.url == node.url %} active{% endif %}"
>{{ node.title }}</a>
{%- if node.has_children -%}
{%- assign children_list = pages_list | where: "parent", node.title -%}
<ul class="nav-list ">
<ul role="tree" class="nav-list" id="{{ nested_owned_tree_id }}">
{%- for child in children_list -%}
{%- unless child.nav_exclude -%}
<li class="nav-list-item {% if page.url == child.url or page.parent == child.title %} active{% endif %}">
<li role="none" class="nav-list-item {% if page.url == child.url or page.parent == child.title %} active{% endif %}">
{%- if child.has_children -%}
<a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
{% assign nested_nested_owned_tree_id = nested_owned_tree_id | append: "_" | append: forloop.index | append: "_" | append: child.title | append: "_navitems" | replace: " ", "_" %}
<a
role="treeitem"
aria-owns="{{ nested_nested_owned_tree_id }}"
{%- if page.url == node.url -%}aria-current="page"{%- endif -%}
href="#"
class="nav-list-expander"
><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
{%- endif -%}
<a href="{{ child.url | absolute_url }}" class="nav-list-link{% if page.url == child.url %} active{% endif %}">{{ child.title }}</a>
<a
role="treeitem"
{%- if child.has_children -%}aria-owns="{{ nested_nested_owned_tree_id }}"{%- endif -%}
{%- if page.url == node.url -%}aria-current="page"{%- endif -%}
href="{{ child.url | absolute_url }}"
class="nav-list-link{% if page.url == child.url %} active{% endif %}"
>{{ child.title }}</a>
{%- if child.has_children -%}
{%- assign grand_children_list = pages_list | where: "parent", child.title | where: "grand_parent", node.title -%}
<ul class="nav-list">
<ul role="tree" class="nav-list" id="{{ nested_nested_owned_tree_id }}">
{%- for grand_child in grand_children_list -%}
{%- unless grand_child.nav_exclude -%}
<li class="nav-list-item {% if page.url == grand_child.url %} active{% endif %}">
<a href="{{ grand_child.url | absolute_url }}" class="nav-list-link{% if page.url == grand_child.url %} active{% endif %}">{{ grand_child.title }}</a>
<li role="none" class="nav-list-item {% if page.url == grand_child.url %} active{% endif %}">
<a
role="treeitem"
{%- if page.url == grand_child.url -%}aria-current="page"{%- endif -%}
href="{{ grand_child.url | absolute_url }}"
class="nav-list-link{% if page.url == grand_child.url %} active{% endif %}"
>{{ grand_child.title }}</a>
</li>
{%- endunless -%}
{%- endfor -%}
Expand Down
48 changes: 36 additions & 12 deletions _layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
| where_exp:"item", "item.nav_exclude != true"
| size %}
{% if pages_top_size > 0 %}
{% include nav.html pages=site.html_pages key=nil %}
{% include nav.html pages=site.html_pages key=nil expanded=true %}
{% endif %}
{% if site.just_the_docs.collections %}
{% assign collections_size = site.just_the_docs.collections | size %}
Expand All @@ -75,25 +75,49 @@
{% assign collection_value = collection_entry[1] %}
{% assign collection = site[collection_key] %}
{% if collection_value.nav_exclude != true %}
{% assign owned_tree_id = collection_key | append: "_" | append: forloop.index | append: "_navitems" | replace: " ", "_" %}
{% if collections_size > 1 or pages_top_size > 0 %}
{% if collection_value.nav_fold == true %}
<ul class="nav-list nav-category-list">
<li class="nav-list-item{% if page.collection == collection_key %} active{% endif %}">
<ul
role="tree"
class="nav-list nav-category-list"
>
<li role="none" class="nav-list-item{% if page.collection == collection_key %} active{% endif %}">

{% assign collection_url_path = collection_key | append: "/index/" %}
{% assign category_comparison_url = "/" | append: collection_url_path %}
{%- if collection.size > 0 -%}
<a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
<a
role="treeitem"
aria-owns="{{ owned_tree_id }}"
aria-current="{% if page.collection == collection_key %}page{% endif %}"
href="#"
class="nav-list-expander"
><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
{%- endif -%}
{% assign collection_url_path = collection_key | append: "/index/" %}
<div class="nav-category"><a href="{{ collection_url_path | relative_url }}">{{ collection_value.name }}</a></div>
{% include nav.html pages=collection key=collection_key %}
<a
role="treeitem"
aria-owns="{{ owned_tree_id }}"
aria-current="{% if page.collection == collection_key %}page{% endif %}"
class="nav-category{% if category_comparison_url == page.url %} active{% endif %}"
href="{{ collection_url_path | relative_url }}"
>{{ collection_value.name }}</a>
{% include nav.html pages=collection key=collection_key owned_tree_id=owned_tree_id %}
</li>
</ul>
{% else %}
{% assign collection_url_path = collection_key | append: "/index/" %}
<div class="nav-category"><a href="{{ collection_url_path | relative_url }}">{{ collection_value.name }}</a></div>
{% include nav.html pages=collection key=collection_key %}
<a
role="treeitem"
aria-owns="{{ owned_tree_id }}"
aria-current="{% if page.collection == collection_key %}page{% endif %}"
class="nav-category{% if category_comparison_url == page.url %} active{% endif %}"
href="{{ collection_url_path | relative_url }}"
>{{ collection_value.name }}</a>
{% include nav.html pages=collection key=collection_key owned_tree_id=owned_tree_id %}
{% endif %}
{% else %}
{% include nav.html pages=collection key=collection_key %}
{% include nav.html pages=collection key=collection_key owned_tree_id=owned_tree_id %}
{% endif %}
{% endif %}
{% endfor %}
Expand All @@ -111,8 +135,8 @@ <h1><a href="/docs/latest/">Documentation</a></h1>
{% assign docs_version = "latest" %}
{% endif %}
<input type="text" id="search-input" class="search-input"
tabindex="0" placeholder="Search..." aria-label="Search {{ site.title }}"
data-docs-version="{{ docs_version }}" autocomplete="off">
placeholder="Search..." aria-label="Search {{ site.title }}"
data-docs-version="{{ docs_version }}" autocomplete="off">
<div class="search-spinner"><i></i></div>
<label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#svg-search"></use></svg></label>
</div>
Expand Down
12 changes: 12 additions & 0 deletions _sass/custom/custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,22 @@ code {
max-height: 100vh;
overflow-x: hidden;
min-width: 14rem;
padding-right: 1px;
padding-left: 1px;
padding-bottom: 1px;
}

nav#site-nav > .nav-list:nth-of-type(1) {
padding-top: 2px;
}

.nav-list {
margin-top: 1px;
}

.nav-category {
text-align: start;
display: block;
}

.main-content {
Expand Down
Loading

0 comments on commit 230a5da

Please sign in to comment.