Jeremy Prevost 84179b0a33
Adds accessible titles to nested page nav toggle (#950)
Adds accessible nav elements for nested pages

Why are these changes being introduced:

* The current links to show/hide the nested pages use a visual only
  svg image with no accessible affordance provided so screenreaders
  will not be able to provide appropriate context for users as to what
  they should expect when clicking these links
* You can see the problem by running a tool like ANDI on the current
  main branch of this repository and then running it again on this
  branch. ANDI shows what a screenreader would read.
* You can also use a tool like Voiceover to hear the importance of what
  this introduces to users that use that technology. Before this change,
  Voiceover would read all of these navigation links as
  "link image just-the-docs" but with this change it will read
  `link image toggle links in <categoryName> category`

Relevant ticket(s):

* This was discussed as part of the larger WCAG compliance ticket
  https://github.com/just-the-docs/just-the-docs/issues/566

How does this address that need:

* This adds an `aria-label` to the link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label

Document any side effects to this change:

It appears it might be prefereable to use `aria-labelledby` whenever
possible, but from what I can tell these links are just the visual cue
of the svg with no other affordance given to users to understand what
they'll do so there is nothing to point `aria-labelledby` at.

An `svg` title was considered, but in reading more about it it seemed
like `aria-label` was more appropriate as it puts the label on the `a`
rather than the `svg` which feels more accurate.

* https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title
* https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-labelledby

Co-authored-by: Matt Wang <matt@matthewwang.me>
2022-09-06 11:57:34 -07:00

147 lines
7.0 KiB
HTML

<ul class="nav-list">
{%- assign titled_pages = include.pages
| where_exp:"item", "item.title != nil" -%}
{%- comment -%}
The values of `title` and `nav_order` can be numbers or strings.
Jekyll gives build failures when sorting on mixtures of different types,
so numbers and strings need to be sorted separately.
Here, numbers are sorted by their values, and come before all strings.
An omitted `nav_order` value is equivalent to the page's `title` value
(except that a numerical `title` value is treated as a string).
The case-sensitivity of string sorting is determined by `site.nav_sort`.
{%- endcomment -%}
{%- assign string_ordered_pages = titled_pages
| where_exp:"item", "item.nav_order == nil" -%}
{%- assign nav_ordered_pages = titled_pages
| where_exp:"item", "item.nav_order != nil" -%}
{%- comment -%}
The nav_ordered_pages have to be added to number_ordered_pages and
string_ordered_pages, depending on the nav_order value.
The first character of the jsonify result is `"` only for strings.
{%- endcomment -%}
{%- assign nav_ordered_groups = nav_ordered_pages
| group_by_exp:"item", "item.nav_order | jsonify | slice: 0" -%}
{%- assign number_ordered_pages = "" | split:"X" -%}
{%- for group in nav_ordered_groups -%}
{%- if group.name == '"' -%}
{%- assign string_ordered_pages = string_ordered_pages | concat: group.items -%}
{%- else -%}
{%- assign number_ordered_pages = number_ordered_pages | concat: group.items -%}
{%- endif -%}
{%- endfor -%}
{%- assign sorted_number_ordered_pages = number_ordered_pages | sort:"nav_order" -%}
{%- comment -%}
The string_ordered_pages have to be sorted by nav_order, and otherwise title
(where appending the empty string to a numeric title converts it to a string).
After grouping them by those values, the groups are sorted, then the items
of each group are concatenated.
{%- endcomment -%}
{%- assign string_ordered_groups = string_ordered_pages
| group_by_exp:"item", "item.nav_order | default: item.title | append:''" -%}
{%- if site.nav_sort == 'case_insensitive' -%}
{%- assign sorted_string_ordered_groups = string_ordered_groups | sort_natural:"name" -%}
{%- else -%}
{%- assign sorted_string_ordered_groups = string_ordered_groups | sort:"name" -%}
{%- endif -%}
{%- assign sorted_string_ordered_pages = "" | split:"X" -%}
{%- for group in sorted_string_ordered_groups -%}
{%- assign sorted_string_ordered_pages = sorted_string_ordered_pages | concat: group.items -%}
{%- 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 %}">
{%- if node.has_children -%}
<a href="#" class="nav-list-expander" aria-label="toggle links in {{ node.title }} category">
<svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg>
</a>
{%- endif -%}
<a href="{{ node.url | relative_url }}" class="nav-list-link{% if page.url == node.url %} active{% endif %}">{{ node.title }}</a>
{%- if node.has_children -%}
{%- if node.child_nav_order == 'desc' -%}
{%- assign children_list = pages_list | where: "parent", node.title | where_exp:"item", "item.grand_parent == nil" | reverse -%}
{%- else -%}
{%- assign children_list = pages_list | where: "parent", node.title | where_exp:"item", "item.grand_parent == nil" -%}
{%- endif -%}
<ul class="nav-list ">
{%- 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 %}">
{%- if child.has_children -%}
<a href="#" class="nav-list-expander" aria-label="toggle links in {{ child.title }} category">
<svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg>
</a>
{%- endif -%}
<a href="{{ child.url | relative_url }}" class="nav-list-link{% if page.url == child.url %} active{% endif %}">{{ child.title }}</a>
{%- if child.has_children -%}
{%- if node.child_nav_order == 'desc' -%}
{%- assign grand_children_list = pages_list | where: "parent", child.title | where: "grand_parent", node.title | reverse -%}
{%- else -%}
{%- assign grand_children_list = pages_list | where: "parent", child.title | where: "grand_parent", node.title -%}
{%- endif -%}
<ul class="nav-list">
{%- 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 | relative_url }}" class="nav-list-link{% if page.url == grand_child.url %} active{% endif %}">{{ grand_child.title }}</a>
</li>
{%- endunless -%}
{%- endfor -%}
</ul>
{%- endif -%}
</li>
{%- endunless -%}
{%- endfor -%}
</ul>
{%- endif -%}
</li>
{%- endunless -%}
{%- endif -%}
{%- endfor -%}
{%- assign nav_external_links = site.nav_external_links -%}
{%- for node in nav_external_links -%}
<li class="nav-list-item external">
<a href="{{ node.url | absolute_url }}" class="nav-list-link external">
{{ node.title }}
{% unless node.hide_icon %}<svg viewBox="0 0 24 24" aria-labelledby="svg-external-link-title"><use xlink:href="#svg-external-link"></use></svg>{% endunless %}
</a>
</li>
{%- endfor -%}
</ul>
{%- if page.collection == include.key -%}
{%- for node in pages_list -%}
{%- if node.parent == nil -%}
{%- if page.grand_parent == node.title or page.parent == node.title and page.grand_parent == nil -%}
{%- assign first_level_url = node.url | relative_url -%}
{%- endif -%}
{%- if node.has_children -%}
{%- assign children_list = pages_list | where: "parent", node.title -%}
{%- for child in children_list -%}
{%- if child.has_children -%}
{%- if page.url == child.url or page.parent == child.title and page.grand_parent == child.parent -%}
{%- assign second_level_url = child.url | relative_url -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{% if page.has_children == true and page.has_toc != false %}
{%- assign toc_list = pages_list | where: "parent", page.title | where: "grand_parent", page.parent -%}
{%- endif -%}
{%- endif -%}