<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ShaynaProductions</title>
    <description>The latest articles on DEV Community by ShaynaProductions (@shaynaproductions).</description>
    <link>https://dev.to/shaynaproductions</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3173178%2F917422f6-23eb-4f4a-99b4-3d68dadb4777.png</url>
      <title>DEV Community: ShaynaProductions</title>
      <link>https://dev.to/shaynaproductions</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shaynaproductions"/>
    <language>en</language>
    <item>
      <title>Laying it all out on the Vertical</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Tue, 02 Jun 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/laying-it-all-out-on-the-vertical-30f1</link>
      <guid>https://dev.to/shaynaproductions/laying-it-all-out-on-the-vertical-30f1</guid>
      <description>&lt;p&gt;&lt;u&gt;Prologue&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;A while ago, I decided to develop a fully accessible main navigation component in React and write a series of articles documenting the steps it took to create a non-trivial accessible component.&lt;/p&gt;

&lt;p&gt;In my last &lt;a href="https://dev.to/shaynaproductions/are-you-my-parent-scaffolding-in-the-architecture-necessary-for-keyboard-handling-between-23dg"&gt;article&lt;/a&gt;, I covered creating the underlying data structures for supporting keyboard handling between components.&lt;/p&gt;

&lt;p&gt;This article, along with its accompanying release, focuses on the design and styling of a navigation component whose first row is laid out vertically, consistent with mobile navigation.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article is one of a series demonstrating how to build a React navigational component from scratch while considering accessibility through the process. The articles are accompanied by a &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with releases tied to one or more articles; each building on the previous, until a fully implemented navigation component is complete.&lt;/p&gt;

&lt;p&gt;Each release and its associated tag contain fully runnable code for the article. The code discussed in this article is available in the release. and may be downloaded at &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/releases/tag/v0.5.1" rel="noopener noreferrer"&gt;release 0.5.1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While code examples are written in JavaScript for brevity, all actual code is written in Typescript and targets React 19.x. Examples use Next.js 16.x, which is not required to run the navigation component.&lt;/p&gt;

&lt;p&gt;Follow along either by downloading the release and running the examples while examining the codebase, or by activating the link accompanying each code snippet to view the full file on GitHub.&lt;/p&gt;




&lt;p&gt;This article is fairly long. It contains code and explanations. The code for this release is displayed, and the corresponding GitHub source is linked.  Use these anchor links to move to the items of interest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Layout

&lt;ul&gt;
&lt;li&gt;Top Row Layout&lt;/li&gt;
&lt;li&gt;SubList Layout&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Focusable Element Standardization&lt;/li&gt;

&lt;li&gt;Separators and Weights&lt;/li&gt;

&lt;li&gt;Summary&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Earlier, I went through creating layouts for a navigation component suitable for desktop or laptop widths. This time, I want to focus on a layout for the same component that is suitable for mobile devices.&lt;/p&gt;

&lt;p&gt;Between my insistence that all my flow-control elements (those that always begin on a new line when the default positioning of static is applied) default to no specific width of their own and my use of nested CSS to style, I'm finding it much easier to achieve layouts.&lt;/p&gt;

&lt;p&gt;In my experience, the longer a website has existed, the more fragile its CSS becomes. Whether the CSS is styled in separate sheets or inside the components, it becomes a struggle to keep everything consistent. Multiple classes are chained together, and name-spaces are prepended onto them in an attempt to stop one style from stepping onto another. Styling within a component seems simpler, but is it really?&lt;/p&gt;

&lt;p&gt;Structural HTML doesn't just help screen readers; it's also useful when styling the screen. There's something freeing about styling an entire component with a single class and using descendant and sibling selectors. Styles become easier to trace, and I'm no longer puzzling over which styles are targeted, a situation that tends to hinder debugging style issues, especially if a styling library is misconfigured and production-level obfuscation is applied in development. Add layer rules, ensure browser styling is consistent, and working with CSS becomes a smooth flow rather than a fight.&lt;/p&gt;

&lt;p&gt;The selectors I used in the horizontal layout are still applicable to this vertical layout; the only differences are the initial class and the rules within the selectors. In this case, the top row will be vertically aligned rather than horizontally.  The pattern is still one of disclosure, but it should follow the keyboard rules for an &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/accordion/" rel="noopener noreferrer"&gt;accordion&lt;/a&gt; rather than a menu.&lt;/p&gt;

&lt;p&gt;Initially unstyled, the navigation component, while not yet polished, still reflects the basic shape I'm looking for. Thanks to the [data-orientation="vertical"] passed to the vertically aligned menu, the List component sets up the initial layout right away.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx8zhnwubw0zdr5x09jz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx8zhnwubw0zdr5x09jz.png" alt="screenshot of an unstyled Vertical navigation component. Buttons have their default styling, and buttons and links are slightly off on the vertical plane." width="800" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Spacing is a mess, buttons are ugly, and nothing really lines up.  However, even with these issues, it's still operable and understandable.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Layout
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Top Row Layout
&lt;/h3&gt;

&lt;p&gt;Recall that everything in React eventually becomes plain old HTML, and the structure defined for the navigation output details the styling order in Nested CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item One&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-two"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Two&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-three"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Three&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"subnav-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-four"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Four&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-five"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Five&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-six"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Six&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-seven"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Seven&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-eight"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Eight&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HTML Structure, Top row targeted in the CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;system-component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="nc"&gt;.vertical-navigation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* Layout */&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c"&gt;/* Top Row nav &amp;gt; ul &amp;gt; li  */&lt;/span&gt;

    &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;ul&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;button,&lt;/span&gt;
        &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;a[href]&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.5.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.5.1/src/folio/Pages/Examples/StyledVerticalUncontrolledPage/styledVertical.css" rel="noopener noreferrer"&gt;styledVertical.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the nav element has only one direct descendant, almost everything except padding is targeted by the unordered list's enclosing styles, which are directly contained within the nav element. Direct descendants always use a &amp;gt; and so anything contained within the direct unordered list will be styled accordingly, while nothing outside will be affected.&lt;/p&gt;

&lt;p&gt;The styling in this bit only targets the top row through another direct descendant, &lt;code&gt;&amp;amp; &amp;gt; li {}&lt;/code&gt; is set and then buttons and links that are direct descendants of the top row list items are set to justify the content within to a left alignment (flex-start), which overcomes the button's default alignment of center.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkcpchodt33q70isdrg66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkcpchodt33q70isdrg66.png" alt="screenshot of vertical navigation with top row styling applied." width="785" height="724"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h3&gt;
  
  
  SubList Layout
&lt;/h3&gt;

&lt;p&gt;The subnavigation lists and focusable elements are next.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="c"&gt;/* Top Row */&lt;/span&gt;
        &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;ul&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
          &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;button,&lt;/span&gt;
            &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;a[href]&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
              &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
              &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
              &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="err"&gt;}&lt;/span&gt;

          &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
              &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="err"&gt;}&lt;/span&gt;
        &lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any unordered lists that are the direct descendants of the top row list items are then targeted. List items are given a width of 100%  to help with the target size, and buttons and links that are direct descendants of the sub-lists are given some padding to visually distinguish them from the primary list, with the content left-aligned.&lt;/p&gt;

&lt;p&gt;Styling based on elements, descendants and siblings maps CSS onto the structure, increasing readability and maintainability. It's easier to figure out where something is being applied, which makes fixes much easier.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Focusable Element Standardization
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;a[href]{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-text-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Styling outside of components makes it easier to apply CSS consistently. Consider that buttons and links live in their own navigation components. Buttons are contained in the SubNavigation component while links live in the NavigationItem. When CSS is applied either via Tailwind classes or within the component itself, the styles need to be applied separately and maintained consistently. It's frustrating, and at some point, a developer may overlook that changes in one file require changes in another.&lt;/p&gt;

&lt;p&gt;In this case, I can target buttons and links together to maintain consistency. Spacing is made consistent by setting the link element to display: inline-block, which allows width and a minimum height to be applied, along with some top and bottom padding.&lt;/p&gt;

&lt;p&gt;Buttons and links are given a 100% width.  By expanding the button's width to fill the entire list item, the target size increases, making it easier for someone using a pointer of any sort, mouse, finger or tracking device to actually interact with a particular button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrlpohb95sbo1yo6t00s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrlpohb95sbo1yo6t00s.png" alt="screenshot of the updated navigation display. Buttons and links are styled without borders or background colors. Sublists are positioned as indented from the controlling button." width="675" height="730"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Removing the default background and border colors and standardizing the padding work wonders, moving the layout from ugly to more professional.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Separators and Weights
&lt;/h2&gt;

&lt;p&gt;The font weights are inconsistent between the buttons and links, and some separation is needed to clarify the difference between the primary and subsequent lists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="py"&gt;li&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;border-bottom-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-border-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="err"&gt;&amp;amp;:has(button[aria-expanded="true"])&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;border-bottom-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;button&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;border-bottom-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-border-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;

  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Have you ever wanted to style an element base on something it contains or an attribute a child element exposes? Modern CSS supports it through the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:has" rel="noopener noreferrer"&gt;:has&lt;/a&gt; pseudo-selector.&lt;/p&gt;

&lt;p&gt;If the list item contains a button, it is given a bottom border that disappears when the button within it is expanded. When the button is expanded, the list border is set back to transparent and the bottom border moves to the button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyccmhpg70eqruduq96pb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyccmhpg70eqruduq96pb.png" alt="Screenshot of a vertical navigation component with font-weights standardized between links and buttons and top level buttons displaying a border below." width="681" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The :has () pseudo-selector allows for the application of a style to a parent element based on specific attributes of a child element. In this case, whether the button has exposed the attribute, aria-expanded="true". When it does, both the parent and the child can be styled together by moving the colored border from the bottom of the list to the bottom of the button.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;amp;:has(button[aria-expanded="true"])&lt;/code&gt; styles the list item when it has a button with the attribute aria-expanded="true". I prefer using existing attributes rather than creating new classes. It creates a more readable, understandable stylesheet and better details the required state than something applied as a class.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b1flsm1p73broq92j0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6b1flsm1p73broq92j0b.png" alt="screenshot of a large system font showing the same ratios and proportionality as one based on a default system font size. Bottom borders have been added to buttons on the sublists." width="800" height="362"&gt;&lt;/a&gt;&lt;br&gt;
Testing with larger browser font sizes confirms proportions and ratios are consistent.&lt;/p&gt;

&lt;p&gt;Structural HTML, Layers and Nested CSS are natural allies, creating an understandable, traceable and maintainable set of styles. The stylesheet can be stored alongside the component and configured to affect only the component itself.&lt;/p&gt;

&lt;p&gt;In my next article in this series, I'll be implementing keyboard navigation using the up and down arrow keys to shift focus between components.&lt;/p&gt;

</description>
      <category>css</category>
      <category>a11y</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Are You My Parent?: Scaffolding in the architecture necessary for keyboard handling between components.</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Thu, 28 May 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/are-you-my-parent-scaffolding-in-the-architecture-necessary-for-keyboard-handling-between-dfo</link>
      <guid>https://dev.to/shaynaproductions/are-you-my-parent-scaffolding-in-the-architecture-necessary-for-keyboard-handling-between-dfo</guid>
      <description>&lt;p&gt;&lt;u&gt;Prologue&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;A while ago, I decided to develop a fully accessible main navigation component in React and write a series of articles documenting the steps it took to create a non-trivial accessible component.&lt;/p&gt;

&lt;p&gt;In my last &lt;a href="https://dev.to/shaynaproductions/laying-it-all-out-nh0"&gt;article&lt;/a&gt;, I demonstrated how structural HTML and Nested CSS go hand in hand, allowing for readable, maintainable stylesheets as work progressed on the beginnings of a styled navigation component suitable for desktop.&lt;/p&gt;

&lt;p&gt;This article and its release focus on setting up for future success by adding the underlying data handling needed to support shifting focus between lists and components.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article is one of a series demonstrating how to build a React navigational component from scratch while considering accessibility through the process. The articles are accompanied by a &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with releases tied to one or more articles; each building on the previous, until a fully implemented navigation component is complete.&lt;/p&gt;

&lt;p&gt;Each release and its associated tag contain fully runnable code for the article. The code discussed in this article is available in the release. and may be downloaded at &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/releases/tag/v0.5.1" rel="noopener noreferrer"&gt;release 0.5.1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While code examples are written in JavaScript for brevity, all actual code is written in Typescript and targets React 19.x. Examples use Next.js 16.x, which is not required to run the navigation component.&lt;/p&gt;

&lt;p&gt;You can view the &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQCNi6MdPbGeQJCJPT4GkOwqASnjGOmQzRlm4uuF3pHsDhw?e=biJzaE&amp;amp;nav=MTVfe0Y1MTVDNzlDLUEzMEYtNDg5Ni1CQ0U3LUM1MEVGMDYwMDJDMn0" rel="noopener noreferrer"&gt;requirements for the Parent Provider Release&lt;/a&gt; along with previous requirements.&lt;/p&gt;

&lt;p&gt;Follow along either by downloading the release and running the examples while examining the codebase, or by activating the link accompanying each code snippet to view the full file on GitHub.&lt;/p&gt;




&lt;p&gt;This article is fairly long. It contains code and explanations. The code for this release is displayed, and the corresponding GitHub source is linked.  Use these anchor links to move to the items of interest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Acceptance Criteria&lt;/li&gt;
&lt;li&gt;
Who is my Parent?

&lt;ul&gt;
&lt;li&gt;NavigationListProvider&lt;/li&gt;
&lt;li&gt;useNavigationList&lt;/li&gt;
&lt;li&gt;NavigationList&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Setting up the Navigation Provider

&lt;ul&gt;
&lt;li&gt;NavigationProvider&lt;/li&gt;
&lt;li&gt;useNavigation&lt;/li&gt;
&lt;li&gt;Navigation&lt;/li&gt;
&lt;li&gt;NavigationItem&lt;/li&gt;
&lt;li&gt;SubNavigation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Summary&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;There comes a point in developing a non-trivial component when handling data becomes a prime consideration, and this time has arrived in the navigation component.&lt;/p&gt;

&lt;p&gt;Whether a link or a button, a focusable item residing in a list item is unaware of its siblings or anything about the list it is not part of. One list has no way of knowing what another list contains. &lt;/p&gt;

&lt;p&gt;Keyboard handling for a single list was implemented using a context provider to hold an array of focusable elements associated with that list. It meant the current element holding focus could send a request to the hook associated with the context provider to shift focus from itself to another element in the same list without knowing anything else.&lt;/p&gt;

&lt;p&gt;Thinking ahead to the functionality required to move between components using the up and down arrow keys, along with Tab, requires each element to be able to traverse a series of lists to find the correct item to shift focus or execute other situations, such as where to place focus when a user closes the component using the keyboard. &lt;/p&gt;

&lt;p&gt;Whether a link or a button, each focusable item resides in an array held by the NavigationListProvider. A SubNavigation component holds the button that controls the sublist along the sublist itself, meaning each list can be associated with a parent and know whether its sublist is open.  &lt;/p&gt;

&lt;p&gt;A tree data structure where the button serves as the intermediary is the logical step, so the following acceptance criteria were determined. &lt;/p&gt;

&lt;h2&gt;
  
  
  Acceptance Criteria
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
AC-1 - Every focusable element should have access to the button controlling its list.&lt;/li&gt;
&lt;li&gt;
AC-2 - A navigation context provider should hold an array of navigation objects.&lt;/li&gt;
&lt;li&gt;
AC-3 - Each focusable element should register itself in the appropriate navigation object within the array.&lt;/li&gt;
&lt;li&gt;
AC-4 - Each subnavigation button should register itself in its own navigation object as the controlling element.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end, the object array should resolve to the following shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;   
    &lt;span class="na"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isSublistOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;subList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Community&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Tales&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Reference&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Community&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isSublistOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;subList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Musings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Forum&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;   
    &lt;span class="na"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tales&lt;/span&gt;
    &lt;span class="na"&gt;isSublistOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;subList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="nx"&gt;Stories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="nx"&gt;Commentary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="nx"&gt;Find&lt;/span&gt; &lt;span class="nx"&gt;Your&lt;/span&gt; &lt;span class="nx"&gt;Next&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;subList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Basic&lt;/span&gt; &lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Advanced&lt;/span&gt; &lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Find&lt;/span&gt; &lt;span class="nx"&gt;Your&lt;/span&gt; &lt;span class="nx"&gt;Next&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;isSublistOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;subList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;By&lt;/span&gt; &lt;span class="nx"&gt;Storyteller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;By&lt;/span&gt; &lt;span class="nx"&gt;Era&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Reference&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;subList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Appendices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Characters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Glossary&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;isSublistOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;subList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;Site&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Contact&lt;/span&gt; &lt;span class="nx"&gt;Us&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Privacy&lt;/span&gt; &lt;span class="nx"&gt;Policy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Accessibility&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Donate&lt;/span&gt;&lt;span class="p"&gt;,]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that every button is listed twice, once in a sublist and as a parent element. The first list will always be the first object in the array. &lt;/p&gt;

&lt;p&gt;Creating the underlying data structure and the functionality to register elements within it is the focus of this release. &lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is my Parent?
&lt;/h2&gt;

&lt;p&gt;AC-1 - &lt;strong&gt;Every focusable element should have access to the button controlling its list.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As the current architecture stands, a button can control a list but has no information about its items. At the same time, no item within a list currently has any way of finding or focusing on anything outside its own list. The solution is for each item to know its parent and to access a data structure that returns the next focusable item.&lt;/p&gt;

&lt;p&gt;Since the NavigationList component already has access to its parent and a provider, it should be fairly simple to extend it to hold a reference to its parent, which will be a button for any list held in the Subnavigation component, or null when the NavigationListProvider is initialized from the NavigationList component.&lt;/p&gt;

&lt;h3&gt;
  
  
  NavigationListProvider
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationListProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parentRef&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;navigationListReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getCurrentListItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getParentEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationListContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;getCurrentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;getParentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationListContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.5.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.5.1/src/ui/components/common/Navigation/providers/NavigationListProvider/NavigationListProvider.tsx" rel="noopener noreferrer"&gt;NavigationListProvider.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The parent reference joins the empty items array within the reducer's state. There's no need to dispatch a call to the reducer; simply returning the current property from the parentRef held in state is enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  useNavigationList
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationListContextObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NavigationListContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getCurrentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getParentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nf"&gt;returnTrueElementOrUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;navigationListContextObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;navigationListContextObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentListItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getCurrentListItems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getParentEl&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.5.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.5.1/src/ui/components/common/Navigation/hooks/useNavigationList/useNavigationList.ts" rel="noopener noreferrer"&gt;useNavigationList.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The getParentEl function is passed through to the navigation list hook, which masks the get() as a variable, as a nicety and passes it through.&lt;/p&gt;

&lt;p&gt;To guarantee data is fresh, provider functions must be called to retrieve any data held by the provider. Passing the data itself to the hook will never refresh it, and while that might be fine for a parent reference that never changes, other information retrieved needs to be up to date, so getParentEl is created for consistency.&lt;/p&gt;

&lt;h3&gt;
  
  
  NavigationList
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationList&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;}){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;

    return (
        &amp;lt;NavigationListProvider value={listContext}&amp;gt;
            &amp;lt;List key={`list-$id`} {...listProps}&amp;gt;
                {children}
            &amp;lt;/List&amp;gt;
        &amp;lt;/NavigationListProvider&amp;gt;
    );
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.5.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.5.1/src/ui/components/common/Navigation/components/NavigationList.tsx" rel="noopener noreferrer"&gt;Navigation.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All that's necessary is to pass the parentRef into any NavigationList and send it to the context provider. &lt;/p&gt;

&lt;p&gt;With a parentRef now available to any NavigationItem or SubNavigation component, I can now begin development on a new context provider to hold an array of objects, each representing a different list.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the Navigation Provider
&lt;/h2&gt;

&lt;p&gt;AC-2 - &lt;strong&gt;A navigation context provider should hold an array of navigation objects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A navigation component is composed of one or more lists, so an array of objects is appropriate. Each object should hold the parent element and another array containing the items in the specific list. Knowing whether a list is opened or closed is going to come in handy, so a navigation object's shape can be stated as an object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;navigationObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;storedParentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* parentRef.current */&lt;/span&gt;
&lt;span class="nx"&gt;storedList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* [] - an array of Focusable Elements (links and buttons) held in the list controlled by the parent */&lt;/span&gt;
&lt;span class="nx"&gt;ssSubListOpen&lt;/span&gt; &lt;span class="cm"&gt;/* boolean - reflects the current state of the stored list's visibility.  */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One object for each list held in the navigation component will be stored in the array. Each list will have access to its parent, and each item within the storedList will be able to ascertain the list's visible state. &lt;/p&gt;

&lt;p&gt;It's time to insert a new context provider into the component.&lt;/p&gt;

&lt;h3&gt;
  
  
  NavigationProvider
&lt;/h3&gt;

&lt;p&gt;A top-level context provider that wraps all the nested components that make up the lists displayed in the navigation component is required to hold all the returned data. When it's complete, the entire data structure for every link and navigation button will be stored in a reducer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;storedParentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storedParentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;storedList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;navigationReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;NavigationArray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;navigationObject&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setIsListOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;isListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_IS_LIST_OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isListOpen&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setListItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;navigationList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_LIST_ITEMS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;navigationList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;navigationList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;registerButtonAsParent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_PARENT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isListOpen&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;registerItemInNavigationArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;navigationList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setListItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;navigationList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;registerButtonAsParent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;registerItemInNavigationArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;setIsListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;setListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since updates are interdependent and registration occurs across different components, a reducer is used again to enable more granular state management. By using a reducer, each dispatch is applied to the latest state, actions can be processed in order, and all transitions are immutable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;navigationReducer&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;navigationReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_PARENT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storedParentEl&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navObj&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;storedParentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;storedList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;navObj&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_IS_LIST_OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storedParentEl&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSubListOpen&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isListOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isListOpen&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_LIST_ITEMS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storedParentEl&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;returnArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storedList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;arraysEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextList&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;storedList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nextList&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.5.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.5.1/src/ui/components/common/Navigation/providers/NavigationProvider/navigationReducer.tsx" rel="noopener noreferrer"&gt;navigationReducer.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reducers are typically handled as switch statements, based on their action types. Unlike setters derived from useState, reducers can rely on specific conditions to determine whether to update the reducer state they are responsible for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SET_PARENT&lt;/strong&gt; - checks for the existence of the passed-in parent element within the navigation array.  If it doesn't exist, a new navigation object is created with the parent, an empty sublist, and whether the sublist is visible, and it is stored in the array.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SET_IS_LIST_OPEN&lt;/strong&gt; - updates the boolean value on the object where the parent element matches the passed-through parent, only if the value has changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SET_LIST_ITEMS&lt;/strong&gt; - updates the storedList within the object whose parent element matches the passed-through parent, only when the stored list doesn't match the list being passed through.&lt;/p&gt;

&lt;h3&gt;
  
  
  useNavigation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useNavigation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationContextObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NavigationContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;registerItemInNavigationArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;registerButtonAsParent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setIsListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;returnTrueElementOrUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;navigationContextObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;navigationContextObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;registerItemInNavigationArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;registerButtonAsParent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setIsListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.5.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.5.1/src/ui/components/common/Navigation/hooks/useNavigation/useNavigation.ts" rel="noopener noreferrer"&gt;useNavigation.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The public functions are returned from the NavigationProvider and passed through by a new hook, useNavigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigation
&lt;/h3&gt;

&lt;p&gt;The context provider needs to be established within the navigation component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...}){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parentRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...};&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationContextProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;storedParentEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;storedList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationListProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NavigationListProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...,&lt;/span&gt;
        &lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationProvider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;navigationContextProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;navigationProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationList&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;navigationListProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationList&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.5.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.5.1/src/ui/components/common/Navigation/components/Navigation.tsx" rel="noopener noreferrer"&gt;Navigation.tsx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When initializing the first object to be stored in the array, not much is known. There are no items in the list, and the parent element for the top row will always be null. All that is really known is whether the list is open, which, for a horizontally aligned, uncontrolled component, is always true. &lt;/p&gt;

&lt;p&gt;A parentRef is provided to be passed through to the NavigationList component, and an initial object is formed, which will always be the first object in the array. The top-level list will never have a controlling element, and the storedList is always sent in as an empty array to be filled during the registration process. Every other list is rendered in the SubNavigation component, and so has a valid parent element: the button that controls it.&lt;/p&gt;

&lt;p&gt;With the provider in place, it's time to register the information. &lt;/p&gt;

&lt;h3&gt;
  
  
  NavigationItem
&lt;/h3&gt;

&lt;p&gt;AC-3 - &lt;strong&gt;Each focusable element should register itself in the appropriate navigation object within the array.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationItem&lt;/span&gt;&lt;span class="p"&gt;({...})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;registerItemInNavigationArray&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevCurrentListItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePrevious&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prevCurrentListItems&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;arraysEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prevList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;registerItemInNavigationArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;prevCurrentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;registerItemInNavigationArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ListItem&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;listItemProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;linkProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ListItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.5.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.5.1/src/ui/components/common/Navigation/components/NavigationItem.tsx" rel="noopener noreferrer"&gt;NavigationItem.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within the NavigationItem component, a new useEffect hook is added that passes the currentItemsList and the parent element retrieved from the useNavigationList hook into the navigationArray held by the NavigationProvider. &lt;/p&gt;

&lt;p&gt;Effectively, this useEffect should run the registration function only once under very specific conditions. The issue is that the first time this hook is called, the linkRef will return null because the link element hasn't yet been initialized and needs to run after initial rendering. Which means it will run when the dependency array changes. I can leverage React's batch updates and send over the list of focusable elements maintained by the navigation list context provider rather than continuously updating it.&lt;/p&gt;

&lt;p&gt;A usePrevious hook retrieves the previous makeup of the currentListItems array, which is the single list array stored in the NavigationListProvider. The function that registers the item into the navigation array is only run when the link element is known and no longer null, and the list actually contains a non-empty array that does not match the previous list. &lt;/p&gt;

&lt;p&gt;The same registration needs to be added to the SubNavigation component to register the button into the navigation array as a focusable element.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subnavigation
&lt;/h3&gt;

&lt;p&gt;AC-4 - &lt;strong&gt;Each subnavigation button should register itself in its own navigation object as the controlling element.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SubNavigation&lt;/span&gt;&lt;span class="p"&gt;({...})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;registerButtonAsParent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;registerItemInNavigationArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setIsListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;buttonEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setButtonEl&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;closeSubNavigation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setIsListOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buttonEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setIsSubListOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;buttonEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsSubListOpen&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openSubNavigation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setIsListOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buttonEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setIsSubListOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;buttonEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsSubListOpen&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nf"&gt;registerButtonAsParent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;registerButtonAsParent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prevCurrentListItems&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;arraysEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prevList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;registerItemInNavigationArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parentEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;prevCurrentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;registerItemInNavigationArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlePress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;closeSubNavigation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;openSubNavigation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationListProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NavigationListProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
            &lt;span class="na"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  &lt;span class="p"&gt;...&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.5.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.5.1/src/ui/components/common/Navigation/components/Subnavigation.tsx" rel="noopener noreferrer"&gt;Subnavigation.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The handlePress function is refactored to call a function based on the current sublist's visibility, rather than toggling its open state. Both the sublist visibility held in the component's state and the call to update the object in the NavigationProvider's reducer are set to true or false in the same function. &lt;/p&gt;

&lt;p&gt;When the button element has been rendered, not only is it registered in the current list, but the button is registered as a parent within the navigation array; and finally, when the button element meets the same conditions as the link did earlier, it registers itself into the correct navigation array as a focusable element along with the parent it retrieves from the NavigationListProvider.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Consistent data registration and updating of each list's open state has been the priority of this release. There isn't anything visible on the screen, but a console.log(state.navigationArray) placed in the registerItemInNavigationArray function will show the completed array. &lt;/p&gt;

&lt;p&gt;With the scaffolding complete, attention in the next release can turn to making those up and down arrow keys actually work. In the meantime, I'll be turning back to styling the navigation component for a vertical layout in the next article.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Laying it all Out</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Tue, 26 May 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/laying-it-all-out-nh0</link>
      <guid>https://dev.to/shaynaproductions/laying-it-all-out-nh0</guid>
      <description>&lt;p&gt;&lt;u&gt;Prologue&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;A while ago, I decided to develop a fully accessible main navigation component in React and write a series of articles documenting the steps it took to create a non-trivial accessible component.&lt;/p&gt;

&lt;p&gt;In my last &lt;a href="https://dev.to/shaynaproductions/single-list-keyboard-handling-254g"&gt;article&lt;/a&gt;, functionality for keyboard handling on a single list was added, and I discussed how a lot of keyboard handling was to aid those who &lt;a href="https://dev.to/shaynaproductions/the-modalities-of-accessibility-2hhe"&gt;perceive through a screen and operate through the keyboard&lt;/a&gt;; a combination I realized has not been commonly considered by many of the developers I've worked with.&lt;/p&gt;

&lt;p&gt;This article focuses once again on the screen's perceivability, with design considerations at the forefront.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article is one of a series demonstrating how to build a React navigational component from scratch while considering accessibility through the process. The articles are accompanied by a &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with releases tied to one or more articles; each building on the previous, until a fully implemented navigation component is complete.&lt;/p&gt;

&lt;p&gt;Each release and its associated tag contain fully runnable code for the article. The code discussed in this article is available in the release. and may be downloaded at &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/releases/tag/v0.4.0" rel="noopener noreferrer"&gt;release 0.4.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Examples have been updated in this release, enabling keyboard handling for a single list. Examples include a vertically aligned single list and horizontally aligned components with links and buttons for verifying operability.&lt;/p&gt;

&lt;p&gt;While code examples are written in JavaScript for brevity, all actual code is written in Typescript and targets React 19.x. Examples use Next.js 16.x, which is not required to run the navigation component.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQCNi6MdPbGeQJCJPT4GkOwqASnjGOmQzRlm4uuF3pHsDhw?e=lhom18&amp;amp;nav=MTVfe0I2OTAxRDlELUJENDAtNEZFOC04OUZDLTQ0RUM1OUUzQTM5Qn0" rel="noopener noreferrer"&gt;design requirements for this release are available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Follow along either by downloading the release and running the examples while examining the codebase, or by activating the link accompanying each code snippet to view the full file on GitHub.&lt;/p&gt;




&lt;p&gt;This article is fairly long. It contains code and explanations. The code for this release is displayed, and the corresponding GitHub source is linked.  Use these anchor links to move to the items of interest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Layout

&lt;ul&gt;
&lt;li&gt;Top Row Layout&lt;/li&gt;
&lt;li&gt;
SubList Layout

&lt;ul&gt;
&lt;li&gt;Sharing Information&lt;/li&gt;
&lt;li&gt;SubNavigation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

Appearance

&lt;ul&gt;
&lt;li&gt;Buttons and Links&lt;/li&gt;
&lt;li&gt;SubLists&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Summary&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;With an accessible HTML structure and the ability to transform objects into navigation, attention can finally be turned to styling. In this article, I'm focusing on the layout of the horizontal navigation, and then I'll apply some styling to buttons and links to achieve consistency and fit within the layout.&lt;/p&gt;

&lt;p&gt;For all its promise, CSS has been notoriously difficult to create and maintain, relying on long chains of selectors to achieve specificity. These long selector chains hinder understanding and maintainability. Switching to nested CSS alongside structural HTML elements and implementing the @layer rule has been a boon, making it much simpler to create and maintain consistent layouts.&lt;/p&gt;

&lt;p&gt;Any layout, whether component or page, needs to handle &lt;a href="https://dev.to/shaynaproductions/spacing-considerations-in-accessible-design-47ad"&gt;resizing without breaking proportions&lt;/a&gt; and styling, whether through browser zoom or when a user changes the base font size. Without a solid layout, any resizing required by &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#resize-text" rel="noopener noreferrer"&gt;WCAG success criteria 1.4.4 Resize Text&lt;/a&gt; is not achievable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnp8illnik7no23a71s24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnp8illnik7no23a71s24.png" alt="A screenshot of an unstyled horizontal navigation component. The top row is displayed horizontally, and the vertical subnavigation lines up under its top-row parents." width="798" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image above, using the browser default font size of 16px, is unstyled except for the styling applied to the individual base components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvr6tuzxio9dhwjy477h5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvr6tuzxio9dhwjy477h5.png" alt="A screenshot of the same unstyled horizontal navigation component with a very large system font applied" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even unstyled, resizing text doesn't break much, and a basic layout has been achieved thanks to the minimal CSS and theming applied to the base components. There's some shifting going on, but that will be handled as styles are applied.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Layout
&lt;/h2&gt;

&lt;p&gt;Layouts are styled first, and while padding and positioning might need work later, even a rough layout helps.&lt;/p&gt;

&lt;p&gt;Desktop navigation typically requires a top row laid out horizontally, with any sublists displayed vertically. So layouts for the top row and the sublist need to be styled separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Top Row Layout
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;system-component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="nc"&gt;.horizontal-navigation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* Layout */&lt;/span&gt;
        &lt;span class="py"&gt;--min-list-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;ul&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="py"&gt;justify-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;column-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nl"&gt;align-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;button,&lt;/span&gt;
                &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;a[href]&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                    &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/folio/Pages/Examples/StyledHorizontalUncontrolledPage/styledHorizontal.css" rel="noopener noreferrer"&gt;styledHorizontal.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A horizontal navigation can be considered a system component, so its styling is placed in the system-component layer. In a nested CSS structure, everything can be styled with a single class applied to the top-level element, in this case &amp;lt;nav /&amp;gt;. Top and bottom padding are applied to the nav element to provide some space. A design token --min-list-width, to be discussed later, is set purely as a default.&lt;/p&gt;

&lt;p&gt;Working on the top row first, rules are set for the nav element's only direct descendant, the topmost unordered list; The list element already sets display: flex and the basics for both horizontal and vertical displays, so the only necessary rules here are around alignment and setting a 24 relative-pixel column gap. Only list items that are directly descended from the element's top unordered list are given position: relative and have some flex alignment rules applied. The top-row buttons and links remove any left padding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqimz2f5918cmfhy30uwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqimz2f5918cmfhy30uwg.png" alt="Screenshot of the horizontal navigation with top row styling applied. A dashed line has been added to demonstrate that the text for both links and buttons sits on the same vertical plane." width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, a straight, horizontal line can be drawn at the element's base to verify that the top row links and the button text are aligned. Spacing is consistent across the top row, and with a 24 relative-pixel column gap, there is plenty of room between the focusable elements to meet &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#target-size-minimum" rel="noopener noreferrer"&gt;WCAG success Criterion 2.5.8, Target Size (minimum)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h3&gt;
  
  
  SubList Layout
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;system-component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="nc"&gt;.horizontal-navigation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* Layout */&lt;/span&gt;
        &lt;span class="c"&gt;/* Top Row nav &amp;gt; ul &amp;gt; li */&lt;/span&gt;

        &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;ul&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
            &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="err"&gt;...&lt;/span&gt;
                    &lt;span class="c"&gt;/* sub navigation (not top row) */&lt;/span&gt;

                &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;ul&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                    &lt;span class="nl"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--min-list-width&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
                    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;36&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fit-content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                    &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                        &lt;span class="err"&gt;&amp;amp;:first-child&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                            &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;

                        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                            &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                            &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                            &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                            &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                    &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="m"&gt;0&lt;/span&gt;
                                    &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;

                    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                        &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                            &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="err"&gt;}&lt;/span&gt;
                &lt;span class="err"&gt;}&lt;/span&gt;
            &lt;span class="err"&gt;}&lt;/span&gt;
        &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/folio/Pages/Examples/StyledHorizontalUncontrolledPage/styledHorizontal.css" rel="noopener noreferrer"&gt;styledHorizontal.css&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Sharing Information
&lt;/h4&gt;

&lt;p&gt;Subnavigation lists can be styled as a direct unordered list descended from any list item in the top row. These lists are positioned as absolute, tied to their top-row list item, which is set to a relative position. Subsequent unordered lists are repositioned as relative, and the first and last list items within the subnavigation list receive extra vertical padding. Most of the padding is applied to the button and the link, along with flex styling.&lt;/p&gt;

&lt;p&gt;The unordered list containing all subnavigation beneath a top-row button has a minimum width set via the design token &lt;strong&gt;--min-list-width&lt;/strong&gt;. While a default was added, the question becomes, where is this token actually set?&lt;/p&gt;

&lt;p&gt;I touched on this technique when discussing the Icon component in &lt;a href="https://dev.to/shaynaproductions/foundational-accessibility-begins-with-the-base-components-4f5p/#icon"&gt;my article on base components&lt;/a&gt;, using the style attribute to communicate information between JavaScript and CSS. In this case, I want to guarantee the minimum width for a sublist is the same as the width of its button in the top row. So modifications need to be made to the SubNavigation component.&lt;/p&gt;

&lt;h4&gt;
  
  
  SubNavigation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SubNavigation&lt;/span&gt;&lt;span class="p"&gt;({...})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsSubListOpen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;listWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setListWidth&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="err"&gt;…&lt;/span&gt;
  &lt;span class="nf"&gt;useLayoutEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setListWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setListWidth&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listItemProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--min-list-width&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;listWidth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;CSSProperties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/components/SubNavigation.tsx" rel="noopener noreferrer"&gt;SubNavigation.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A listWidth is set up in state, and a useLayoutEffect calls a function to set the list width, passing the buttonRef and dispatch to a custom utility function. The result is sent to the ListItem's style attribute through the design token, and the sub-list defined in SubNavigation uses the token to set a min-width.&lt;/p&gt;

&lt;p&gt;You'll note the use of useLayoutEffect in the code. It is a synchronous function that runs only after React has performed all DOM mutations, but before the browser repaints, making it useful for DOM measurements. In this case, I'm using the button's offsetWidth property as the value for the design token I'm passing to the list item's style attribute.&lt;/p&gt;

&lt;p&gt;I'm not a fan of pushing a lot of styles through the style attribute, but I do find it useful to send information only available to JavaScript to CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setSubListWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;refObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setListWidth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setListWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;refObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/components/utilities.ts" rel="noopener noreferrer"&gt;utilities.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The read-only offsetWidth property is available on any HTML element. It returns a pixel measurement of an element's width, including borders and padding. Sublists can use the returned width, as defined by the top-row button, to set a relative pixel width, guaranteeing the list appears at least as wide as the button that controls it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77r3cpoayz4mihh83oli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77r3cpoayz4mihh83oli.png" alt="horizontal layout applied, large font size" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While nothing appears to be broken at any browser font size, it's hard to tell whether the layout is correct without applying other styles.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Appearance
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;system-component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="nc"&gt;.horizontal-navigation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* Layout */&lt;/span&gt;
        &lt;span class="py"&gt;--min-list-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c"&gt;/* Top Row nav &amp;gt; ul &amp;gt; li */&lt;/span&gt;

        &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;ul&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;ul&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
            &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;button,&lt;/span&gt;
            &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;a[href]&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-text-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/folio/Pages/Examples/StyledHorizontalUncontrolledPage/styledHorizontal.css" rel="noopener noreferrer"&gt;styledHorizontal.css&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Buttons and Links
&lt;/h3&gt;

&lt;p&gt;The component-level gap is unset for each ul directly descended from the top-level ul, and buttons and links have their appearance standardized. Background and border colors are set to transparent, allowing the elements to blend into the designated background color. A border-width is applied, along with a transparent border color, to prevent state changes from causing label shifting. Colors are applied through the &lt;a href="https://dev.to/shaynaproductions/theming-in-the-modern-age-1je5"&gt;theming system&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I want buttons and links to take up the entire list item, so the width is set to 100%. This increases the target size to that of the list item, which, while also visually appealing, conforms to  &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#target-size-minimum" rel="noopener noreferrer"&gt;WCAG success Criterion 2.5.8, Target Size (minimum)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some changes to the underlying component styling are necessary. A gap originally set up in the styles associated with the list component is unset, and text alignment is reset to left instead of the original button style of center. Additionally, any item within a list item is set to keep text on a single line rather than wrap over multiple lines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd53ib45ramrl7ujxn1e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd53ib45ramrl7ujxn1e2.png" alt="IA screenshot of the layout with list, links and buttons standardized." width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;p&gt;The styling is showing promise, but there's still more to do with the sublists.&lt;/p&gt;

&lt;h3&gt;
  
  
  SubLists
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;system-component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="nc"&gt;.horizontal-navigation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* Layout */&lt;/span&gt;

        &lt;span class="err"&gt;...&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;ul&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
            &lt;span class="err"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;button,&lt;/span&gt;
                &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;a[href]&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                    &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--theme-background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-border-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nl"&gt;border-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;button,&lt;/span&gt;
                    &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;a[href]&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
                        &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;

                    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;

                    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="err"&gt;}&lt;/span&gt;
        &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/folio/Pages/Examples/StyledHorizontalUncontrolledPage/styledHorizontal.css" rel="noopener noreferrer"&gt;styledHorizontal.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A background for links and buttons is finally applied, so text under the absolutely positioned sublists no longer bleeds through. Font weights are applied along with a border.&lt;/p&gt;

&lt;p&gt;Is it perfect? There's always more to do, but both the top row and the displayed sublists are readable, and each focusable element in the sublists has a target area larger than the minimum target size.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqlqou9gelz7mnn5naov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqlqou9gelz7mnn5naov.png" alt="A screenshot of the complete layout applied to a horizontally displayed navigation component." width="771" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also looks consistently proportioned when the browser font size is increased.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rnf7piscv7dczkkyncc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rnf7piscv7dczkkyncc.png" alt="A screenshot of the complete layout when the system Font size is increased to very large." width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The initial layout of a horizontal navigation component is simplified by nesting the CSS under a single class and using direct descendant selectors to target the top row and its sublists. Layout is separated from appearance, and the component remains consistent in proportions and ratios when a larger browser font is applied.&lt;/p&gt;

</description>
      <category>css</category>
      <category>a11y</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Single List Keyboard Handling</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Thu, 21 May 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/single-list-keyboard-handling-1fji</link>
      <guid>https://dev.to/shaynaproductions/single-list-keyboard-handling-1fji</guid>
      <description>&lt;p&gt;&lt;u&gt;Prologue&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;A while ago, I decided to develop a fully accessible main navigation component in React and write a series of articles documenting the steps it took to create a non-trivial accessible component.&lt;/p&gt;

&lt;p&gt;In my last &lt;a href="https://dev.to/shaynaproductions/structure-and-transformation-first-steps-in-navigation-implementation-2ml9"&gt;article&lt;/a&gt;, the focus was actually on creating the components and adding a transformation utility to convert JavaScript objects into actual navigation. The base navigation component at this stage supports screen reader functionality through structured HTML and WAI-ARIA attributes, the ability to open and close a list through pointers and the Enter and Space keys.&lt;/p&gt;

&lt;p&gt;This article, along with its accompanying release, focuses on basic keyboard handling for screen/keyboard users in a single list.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article is one of a series demonstrating how to build a React navigational component from scratch while considering accessibility through the process. The articles are accompanied by a &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with releases tied to one or more articles; each building on the previous, until a fully implemented navigation component is complete.&lt;/p&gt;

&lt;p&gt;Each release and its associated tag contain fully runnable code for the article. The code discussed in this article is available in the release. and may be downloaded at &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/releases/tag/v0.4.0" rel="noopener noreferrer"&gt;release 0.4.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Examples have been updated in this release, enabling keyboard handling for a single list. Examples include a vertically aligned single list and horizontally aligned components with links and buttons for verifying operability.&lt;/p&gt;

&lt;p&gt;While code examples are written in JavaScript for brevity, all actual code is written in Typescript and targets React 19.x. Examples use Next.js 16.x, which is not required to run the navigation component.&lt;/p&gt;

&lt;p&gt;You can view the &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQCNi6MdPbGeQJCJPT4GkOwqASnjGOmQzRlm4uuF3pHsDhw?e=IQJcbn&amp;amp;nav=MTVfezE2NDhFMEZELTVGOTgtNDQzRi1COTI3LTg0MzdFRTNENTA0MX0" rel="noopener noreferrer"&gt;requirements for the Single List Keyboard Release&lt;/a&gt; along with previous requirements.&lt;/p&gt;

&lt;p&gt;Follow along either by downloading the release and running the examples while examining the codebase, or by activating the link accompanying each code snippet to view the full file on GitHub.&lt;/p&gt;




&lt;p&gt;This article is fairly long. It contains code and explanations. The code for this release is displayed, and the corresponding GitHub source is linked.  Use these anchor links to move to the items of interest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Acceptance Criteria&lt;/li&gt;
&lt;li&gt;
Holding Data in a Provider

&lt;ul&gt;
&lt;li&gt; NavigationListProvider
&lt;/li&gt;
&lt;li&gt;navigationListReducer&lt;/li&gt;
&lt;li&gt; useNavigation
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Registering a Focusable Element

&lt;ul&gt;
&lt;li&gt;NavigationList&lt;/li&gt;
&lt;li&gt;NavigationItem&lt;/li&gt;
&lt;li&gt;SubNavigation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Keyboard Handler

&lt;ul&gt;
&lt;li&gt;useNavigationList&lt;/li&gt;
&lt;li&gt;
NavigationItem

&lt;ul&gt;
&lt;li&gt;handleCommonKeyDown&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;SubNavigation&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Summary&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This article is the first of three detailing keyboard handling in a universally accessible navigation component; It is also the simplest.&lt;/p&gt;

&lt;p&gt;In my experience, many developers seem to expect keyboard handling to be a browser feature, and it's been rare on the contracts I've worked on to see code that handles much custom keyboard input. Keyboard handling works well with native browser elements, but not as well with custom widgets, where developers need to handle code navigation requirements.&lt;/p&gt;

&lt;p&gt;While most developers seem to understand that a keyboard is necessary for screen reader users, the fact that many people use a keyboard alongside a screen to navigate isn't always obvious. Users of screen readers have a variety of key combinations they may use to navigate through structures such as headings, links, form elements and tables. Users who navigate the screen with a pointer can simply move their cursor to a specific element and click. Unfortunately, the keyboard flexibility is limited for screen/keyboard users, who are the only ones who must navigate a page linearly. Navigation is not as easy for someone who can see a screen and depends on a keyboard for both input and navigation. &lt;/p&gt;

&lt;p&gt;Those who use a screen and keyboard have expectations that developers should not only be aware of, but should strive to match. For those developers who work with a screen, testing how focus moves within a component is actually easy; just use the keyboard. Developers should always ensure a component is fully navigable with the Tab/Shift+Tab key combinations, which are required for both screen and screen reader users, and that any custom keyboard handling for screen users is implemented and works correctly.&lt;/p&gt;

&lt;p&gt;To do so, developers need to receive acceptance criteria that detail what happens when a key is used.&lt;/p&gt;

&lt;p&gt;When developers don't receive information about keyboard handling requirements when implementing a custom widget, efforts to bring the code into compliance with accessibility standards can run into snags. Keyboard handling can be compromised, and what actually gets implemented might be more focused on the letter of the law than the spirit, as is demonstrated by the following video.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/FBzcGg4Q9GE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Since the focus of this navigation component is accessibility, the acceptance criteria must specify what happens on each key press.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Acceptance Criteria
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Single List Keyboard Handling&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
AC 1 - Pressing the HOME Key should take a user to the first item in the current List.&lt;/li&gt;
&lt;li&gt;
AC 2 - Pressing the END Key should take a user to the last item in the current list.&lt;/li&gt;
&lt;li&gt;
AC 3 - Pressing the LEFT-ARROW key should take a user to the previous item in the current list.&lt;/li&gt;
&lt;li&gt;
AC 4 -  If focus is already on the first item in the current list, pressing the LEFT-ARROW key should take the user to the last item in the current list.&lt;/li&gt;
&lt;li&gt;
AC 5 - Pressing the RIGHT-ARROW Key should take a user to the next item in the current list.&lt;/li&gt;
&lt;li&gt;
AC 6 - If focus is already on the last item in the current list, pressing the RIGHT-ARROW Key should take a user to the first item in the current list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The keyboard support section in the &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/#kbd_label" rel="noopener noreferrer"&gt;Disclosure Navigation pattern in the APG&lt;/a&gt; requires interpretation. The guide references moving buttons to buttons and links to links. Both are focusable elements, and depending on where each lies, navigation can move from a button to a link, or from a link to a button, within a single list.&lt;/p&gt;

&lt;p&gt;Hand-eye coordination is key in this instance. We expect the cursor to move in the direction indicated by the arrow keys. When the cursor moves to an unexpected location, it's jarring; if it disappears entirely, the site can appear broken.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Holding Data in a Provider
&lt;/h2&gt;

&lt;p&gt;Navigation in a sublist requires a focusable element, in this case either a button or a link, to be able to determine its sibling in a list and move according to the acceptance criteria.&lt;/p&gt;

&lt;p&gt;Each link and button in a list is rendered in its own component, with no real way to know about, much less access, the others.&lt;/p&gt;

&lt;p&gt;Data for each focusable item in a particular list can be stored in a context provider, along with functions to register and retrieve the collective data. Since each focusable element is part of a list, the best data structure to hold the information is an array.&lt;/p&gt;

&lt;h3&gt;
  
  
  NavigationListProvider
&lt;/h3&gt;

&lt;p&gt;Context providers hold data along with functions for retrieving and setting it. Each list works with its own copy of the provider, and the data in its array consists of each individual link or button element within the list items it contains. Each focusable element, whether a button or a link, can only focus on siblings contained in the list it resides in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationListProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;navigationListReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getCurrentListItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;focusableEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;REGISTER_ITEM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;focusableEl&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationListContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;getCurrentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationListContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;NavigationListProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NavigationListContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/providers/NavigationListProvider/NavigationListProvider.tsx" rel="noopener noreferrer"&gt;NavigationListProvider.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Given the nature of the data, useReducer is a better solution than useState. A reducer still uses the state object but can manage more complex logic.  Since state updates to the NavigationListProvider affect multiple components and changes might depend on others, it makes sense to use the provided reducer hook rather than the state hook.&lt;/p&gt;

&lt;h4&gt;
  
  
  navigationListReducer
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;navigationListReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;REGISTER_ITEM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/providers/NavigationListProvider/navigationListReducer.ts" rel="noopener noreferrer"&gt;navigationListReducer.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like most reducers, actions are held in a switch, even though there is only one action type, REGISTER_ITEM. When called, a focusable element (action.item) is passed through and checked to determine if it already exists in the array. If not, it is added in.&lt;/p&gt;

&lt;p&gt;A context provider is not exposed to public components; instead, a hook is used to execute functionality that can be passed through the registration function and to add additional functionality when necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  useNavigationList
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationListContextObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NavigationListContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nf"&gt;returnTrueElementOrUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;navigationListContextObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;navigationListContextObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A common pattern for a hook associated with a context provider is to load the provider's public functions and either use them in the hook or pass them through to another component. For the moment, the registration function is just passed through, so it may be imported into the navigation components.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Registering a Focusable Element
&lt;/h2&gt;

&lt;p&gt;In order for the array to be used with keyboard handling, the focusable elements must be registered (added) into the data array. The first step is to wrap each list within its own context provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  NavigationList
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationList&lt;/span&gt;&lt;span class="p"&gt;({...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listProps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationListProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`list-$id`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;listProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationListProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/components/NavigationList.tsx" rel="noopener noreferrer"&gt;NavigationList.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the NavigationListProvider now wrapping the List component, each list item can access any other list item stored in its copy of the data array. It's important to understand that each list maintains its own array of items and cannot access items across lists.&lt;/p&gt;

&lt;h3&gt;
  
  
  NavigationItem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationItem&lt;/span&gt;&lt;span class="p"&gt;({...})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;


  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listItemProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/components/NavigationItem.tsx" rel="noopener noreferrer"&gt;NavigationItem.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code that has already been discussed in previous releases is represented by ellipses; only new code is given.&lt;/p&gt;

&lt;p&gt;Focusable elements are stored in ref objects, but reading the element through ref.current can lead to unreliable code during renders. Since the elements held in the ref object are just pointers to the DOM elements, it's safe to extract them and store them separately as read-only.&lt;/p&gt;

&lt;p&gt;References to elements are not populated right away; the focusable element, in this case a link, needs to be rendered before the information is available, so the useEffect() that registers the link into the currentlistitems array only runs when the ref. current is not null.&lt;/p&gt;

&lt;h3&gt;
  
  
  SubNavigation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SubNavigation&lt;/span&gt;&lt;span class="p"&gt;({...})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsSubListOpen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlePress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIsSubListOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/components/SubNavigation.tsx" rel="noopener noreferrer"&gt;SubNavigation.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code to register a button is almost identical to the code registering a link. The only difference is that the reference being passed is a button element.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Keyboard Handler
&lt;/h2&gt;

&lt;p&gt;With the data structure set up and items registered, it's finally time to shift the focus to handling the appropriate keys, and attention turns back to the acceptance criteria.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AC 1 - Pressing the HOME Key should take a user to the first item in the current List.&lt;/li&gt;
&lt;li&gt;AC 2 - Pressing the END Key should take a user to the last item in the current list.&lt;/li&gt;
&lt;li&gt;AC 3 - Pressing the LEFT-ARROW key should take a user to the previous item in the current list.&lt;/li&gt;
&lt;li&gt;AC 4 -  If focus is already on the first item in the current list, pressing the LEFT-ARROW key should take the user to the last item in the current list.&lt;/li&gt;
&lt;li&gt;AC 5 - Pressing the RIGHT-ARROW Key should take a user to the next item in the current list.&lt;/li&gt;
&lt;li&gt;AC 6 - If focus is already on the last item in the current list, pressing the RIGHT-ARROW Key should take a user to the first item in the current list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only keys being handled now are home, end, and the left and right arrows. If the focus is on the first element in the list and the left arrow key is pressed, then focus should jump to the last element in the list, and the opposite should happen if the focus is on the last element and the right key is pressed. Focus should move to the first element.&lt;/p&gt;

&lt;h3&gt;
  
  
  useNavigationList
&lt;/h3&gt;

&lt;p&gt;Since the functionality needs to access data stored in the context provider, the functions are created in the hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationListContextObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NavigationListContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getCurrentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nf"&gt;returnTrueElementOrUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;navigationListContextObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;navigationListContextObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentListItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getCurrentListItems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_getCurrentIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentlyFocusedEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentlyFocusedEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shiftFocus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;focusableEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;focusableEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;preventScroll&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setFirstFocus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;shiftFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setLastFocus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;shiftFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setNextFocus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;currentlyFocusedEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_getCurrentIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentlyFocusedEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setFirstFocus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;shiftFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setPreviousFocus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;currentlyFocusedEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_getCurrentIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentlyFocusedEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setLastFocus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;shiftFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setFirstFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setLastFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setNextFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;setPreviousFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;shiftFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/hooks/useNavigationList/useNavigationList.tsx" rel="noopener noreferrer"&gt;useNavigationList.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A reminder that the code discussed earlier is represented by ellipses; only the new code is shown.&lt;/p&gt;

&lt;p&gt;It's useful to know when a private or public function is used, and I do so by prefacing private functions with an underscore.&lt;/p&gt;

&lt;p&gt;To provide a fresh copy of the data to the hook, don't call the data directly; it won't refresh. Instead, a getter is retrieved from the context provider, getCurrentListItems(). You'll note an alias for currentListItems that calls the getter each time. When used this way, the code always returns an updated copy of the array, making it more natural to work with.&lt;/p&gt;

&lt;p&gt;A custom function, shiftFocus(), is used instead of implementing focus within each publicly called function to standardize how scrolling is handled. In these cases, scrolling should be prevented when navigation is displayed in a horizontal layout to prevent extraneous shifts when sublists open and close.&lt;/p&gt;

&lt;p&gt;The rest of the code is self-explanatory; focus is shifted depending on the key pressed: Home and End, sends focus to the first or last children in the list, while the right or left arrow key sets focus depending on where the currently focused element is; If the focus is at the end of the list when setNextFocus is called, focus then moves to the first element and if the focus is at the beginning of the list when setPreviousFocus is called, focus moves to the end. Otherwise, focus shifts to the respective sibling on either side of the current element.&lt;/p&gt;

&lt;p&gt;With the focus functions created, it's time to use them.&lt;/p&gt;

&lt;h3&gt;
  
  
  NavigationItem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;setFirstFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;setLastFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;setNextFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;setPreviousFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="err"&gt;…&lt;/span&gt;

 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleKeyDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HOME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;END&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LEFT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RIGHT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
          &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stopPropagation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
          &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nf"&gt;handleCommonKeyDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;linkEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setFirstFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setLastFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setNextFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setPreviousFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="err"&gt;…&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="na"&gt;onKeyDown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;handleKeyDown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linkRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(..);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The setters from the hook are retrieved, and a handleKeyboard function is created.  Rather than setting preventDefault and stopPropagation in each case statement, I use a switch that sets them on all the keys at once. And because both links and buttons handle these keys in the same way, a common keyboard handler is created and called rather than duplicating the code across components.&lt;/p&gt;

&lt;p&gt;When calling a function outside the render, everything necessary must be passed in, including all the hook calls.&lt;/p&gt;

&lt;h4&gt;
  
  
  handleCommonKeyDown
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCommonKeyDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;currentlyFocusedEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;setFirstFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;setLastFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;setNextFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;setPreviousFocus&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HOME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nf"&gt;setFirstFocus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;END&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nf"&gt;setLastFocus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LEFT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nf"&gt;setPreviousFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentlyFocusedEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RIGHT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nf"&gt;setNextFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentlyFocusedEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/utlitiies/handleCommonKeyDown/handleCommonKeyDown.ts" rel="noopener noreferrer"&gt;handleCommonKeyDown.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The common key handler is quite straightforward; each specific key triggers a function in the hook to decide the next item to shift to.&lt;/p&gt;

&lt;h3&gt;
  
  
  SubNavigation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SubNavigation&lt;/span&gt;&lt;span class="p"&gt;({...})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;currentListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;registerListItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setFirstFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setLastFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setNextFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;setPreviousFocus&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;registerListItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="nx"&gt;setFirstFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="nx"&gt;setLastFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="nx"&gt;setNextFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="nx"&gt;setPreviousFocus&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigationList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentButtonEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentButtonEl&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nf"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentButtonEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;buttonEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerItemInCurrentList&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleKeyDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HOME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;END&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LEFT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RIGHT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;handleCommonKeyDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="nx"&gt;buttonEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="nx"&gt;setFirstFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="nx"&gt;setLastFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="nx"&gt;setNextFocus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="nx"&gt;setPreviousFocus&lt;/span&gt;
       &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;buttonProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="na"&gt;onKeyDown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;handleKeyDown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;handlePress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.4.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.4.0/src/ui/components/common/Navigation/components/SubNavigation.tsx" rel="noopener noreferrer"&gt;SubNavigation.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice how stopPropagation() is not included in the top switch. This is because the button component I use from react-aria-components already calls stopPropagation() itself, so I don't need to set it. This may differ from the button component you are working with.  Otherwise, the code for SubNavigation is similar to that already seen in NavigationItem.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Handling link references to multiple components becomes straightforward when a provider holds the data and the functions that call and manipulate it. A hook passes through necessary provider functions as well as its own to provide keyboard handling within a single list.&lt;/p&gt;

&lt;p&gt;With all the code added to support single-list keyboard handling, the question arises: Does it work?&lt;/p&gt;

&lt;p&gt;Part of the issue with demonstrating keyboard handling is the inability to show which key is being used as focus moves. It's one of the reasons keyboard accessibility is so hard to demonstrate during sprint demos. I'll be providing videos I make that detail what I am doing and which keys I'm pressing as I guide you through the enhancements.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/dR6NB9l_X_M"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I'll be back with another article soon, focusing on CSS design and applying a layout to the default horizontal navigation.&lt;/p&gt;

</description>
      <category>react</category>
      <category>a11y</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Structure and Transformation: First Steps in Navigation Implementation</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Tue, 19 May 2026 13:25:33 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/structure-and-transformation-first-steps-in-navigation-implementation-2ml9</link>
      <guid>https://dev.to/shaynaproductions/structure-and-transformation-first-steps-in-navigation-implementation-2ml9</guid>
      <description>&lt;p&gt;&lt;u&gt;&lt;em&gt;Prologue&lt;/em&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;A while ago, I decided to develop a fully accessible main navigation component in React and write a series of articles documenting the steps it took to create a non-trivial accessible component.&lt;/p&gt;

&lt;p&gt;In the last article, the focus was on wiring a theme into the foundational components that render valid HTML elements. This article focuses on creating the navigation structure and on transforming objects into a navigation component suitable for further work by developers for operability and by designers for perceivability.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article is one of a series demonstrating how to build a React navigational component from scratch while considering accessibility through the process. The articles are accompanied by a &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with releases tied to one or more articles; each building on the previous, until a fully implemented navigation component is complete.&lt;/p&gt;

&lt;p&gt;Each release and its associated tag contain fully runnable code for the article. The code discussed in this article is available in the release. and may be downloaded at &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/releases/tag/v0.3.1" rel="noopener noreferrer"&gt;release 0.3.1&lt;/a&gt;. A page showcasing these base components may be run locally through this release.&lt;/p&gt;

&lt;p&gt;While code examples are written in JavaScript for brevity, all actual code is written in Typescript and targets React 19.x. Examples use Next.js 16.x, which is not required to run the navigation component.&lt;/p&gt;

&lt;p&gt;You can view the &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQCNi6MdPbGeQJCJPT4GkOwqASnjGOmQzRlm4uuF3pHsDhw?e=CtCLH4&amp;amp;nav=MTVfe0QxODUzM0FBLTg4MzgtNENBNC1BMTYxLTRGMkQ2NjgzQzcyN30" rel="noopener noreferrer"&gt;requirements for the Structure and Transformation Release&lt;/a&gt; along with previous requirements.&lt;/p&gt;

&lt;p&gt;Follow along either by downloading the release and running the examples while examining the codebase, or by activating the link accompanying each code snippet to view the full file on GitHub.&lt;/p&gt;

&lt;p&gt;-—&lt;/p&gt;

&lt;p&gt;This article is fairly long. It contains code and explanations. The code for this release is displayed, and the corresponding GitHub source is linked.  Use these anchor links to return to the discussions of the individual components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Acceptance Criteria&lt;/li&gt;
&lt;li&gt;
Structure

&lt;ul&gt;
&lt;li&gt;NavigationList&lt;/li&gt;
&lt;li&gt;NavigationItem&lt;/li&gt;
&lt;li&gt;SubNavigation&lt;/li&gt;
&lt;li&gt;Navigation&lt;/li&gt;
&lt;li&gt;navigation.css&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;a href=""&gt;Transformation&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href=""&gt;Summary&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Non-trivial component development requires progressively enhancing code through a layered approach. Each release builds on the previous release, adding accessibility, functionality, and even some styling to the earlier work. Consider building these components on a feature branch and merging into main only after they are complete.&lt;/p&gt;

&lt;p&gt;With the &lt;a href="https://dev.to/shaynaproductions/foundational-accessibility-begins-with-the-base-components-2nac"&gt;base components&lt;/a&gt; completed, attention turns to the components necessary to render the nested structure of unordered lists contained in the  landmark element. Screen reader accessibility and minimal target functionality via button activation are also added, resulting in a fully rendered navigation component that can be displayed in examples and used in testing.&lt;/p&gt;

&lt;p&gt;All examples display the default choice for an uncontrolled component with full aria capabilities, along with some slight styling to provide developers with visual indications of placement. When run locally, the home page exposes three ugly, yet operable examples for development and testing. Taken together, the three examples cover all of the scenarios necessary to create a robust, uncontrolled navigation component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fapavkrmz8td6szgfg027.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fapavkrmz8td6szgfg027.png" alt="A screenshot of the examples home page listing the various examples created in the release.description" width="797" height="786"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Acceptance Criteria
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Structure and Transformation Release&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
AC 1 - The Navigation Component should be contained in a  landmark region&lt;/li&gt;
&lt;li&gt;
AC 2 - The navigation should be presented as a nested structure of unordered lists within the   landmark region&lt;/li&gt;
&lt;li&gt;
AC 3  - Lists should present with a role of "list", list Items should present with a role of "listitem".&lt;/li&gt;
&lt;li&gt;
AC 4 - Buttons are associated with a sublist and indicate if the sublist is open or closed.&lt;/li&gt;
&lt;li&gt;
AC 5 - The navigation component should be able to be presented as horizontal (desktop - default).&lt;/li&gt;
&lt;li&gt;
AC 6 - When navigation is displayed in a horizontal layout, the first row of focusable elements should display as open by default.&lt;/li&gt;
&lt;li&gt;
AC 7 - The navigation component should be able to be presented as vertical (mobile presentation).&lt;/li&gt;
&lt;li&gt;
AC 8 - A visual indicator is used to represent the state of the sublist's expanded status.&lt;/li&gt;
&lt;li&gt;
AC 9 - A link should contain a method of informing users which link corresponds to the current page for both screen and screen readers.&lt;/li&gt;
&lt;li&gt;
AC 10 - A sublist may be toggled to open or close when the button associated with it is pressed.&lt;/li&gt;
&lt;li&gt;
AC 11 - The state of a list's visible or hidden state should be easily perceived by any user&lt;/li&gt;
&lt;li&gt;
AC 12 - Unexpanded sublists should be hidden from the screen, but available through the DOM when they are closed.&lt;/li&gt;
&lt;li&gt;
AC 13 -A JavaScript object containing a properly formed object should be able to be transformed into properly formed ListItems and Subnavigation lists.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While most of the requirements were known during the &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQCNi6MdPbGeQJCJPT4GkOwqASnjGOmQzRlm4uuF3pHsDhw?e=VVE8fZ&amp;amp;nav=MTVfe0VGNTU2NjJDLUY2NkEtNDI3RC05RTQ2LTU1RDJDNDlDMzFFM30" rel="noopener noreferrer"&gt;initial requirements gathering phase&lt;/a&gt;, two more have been added.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AC 12&lt;/strong&gt; represents the decision to render unopen lists in the DOM while restricting their visibility on a screen. This decision and the reasons for it were made in the &lt;a href="https://dev.to/shaynaproductions/creating-initial-requirements-for-an-accessible-navigation-component-3gdg/#handling-list-exposure"&gt;initial requirements gathering phase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AC 13&lt;/strong&gt; requires a utility function that can take a JavaScript object and output a fully formed set of navigation lists and links to form the nested structure necessary.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure
&lt;/h2&gt;

&lt;p&gt;Given the requirements, the following components are necessary and will be built in the following order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NavigationList&lt;/strong&gt;: A wrapper around the List component that allows for children and designates whether the list itself is displayed on the screen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NavigationItem&lt;/strong&gt;: Renders a Navigation Link within a ListItem and reveals the link referring to the current page. (aria-current).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SubNavigation&lt;/strong&gt;: Renders both a button and its accompanying sublist within a listItem. Handles displaying or hiding the sublist on the screen when the button is pressed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Navigation&lt;/strong&gt;: Renders the entire navigation lists and sublists within a  HTML element.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  NavigationList
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria Realized&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AC 3 - &lt;u&gt;Lists should present with a role of "list"&lt;/u&gt;, list Items should present with a role of "listitem".&lt;/li&gt;
&lt;li&gt;AC 5 - The navigation component should be able to be presented horizontally (desktop presentation).&lt;/li&gt;
&lt;li&gt;AC 7 - The navigation component should be able to be presented as vertical (mobile presentation).&lt;/li&gt;
&lt;li&gt;AC 12 - Unexpanded sublists should be hidden from the screen, but available through the DOM when they are closed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationList&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;classNames&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;srOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isOpen&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`list-$id`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;listProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.3.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.3.1/src/ui/components/common/Navigation/components/NavigationList.tsx" rel="noopener noreferrer"&gt;NavigationList.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A NavigationList wraps around the previously created List component, which renders the structural HTML (AC 3). An unordered list (ul) has a default role of "list".&lt;/p&gt;

&lt;p&gt;While not detailed in the code, an orientation prop is passed to the List component via …rest, that indicates whether the list is displayed horizontally or vertically (AC 5 and 7). This was placed into the &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.3.1/src/ui/components/base/List/List.tsx" rel="noopener noreferrer"&gt;List component&lt;/a&gt; during the base component functionality phase.&lt;/p&gt;

&lt;p&gt;The isOpen prop controls the screen visibility of the specific list by applying the .srOnly class when the list is unexpanded and removing it when isOpen is true, satisfying AC 12. A screen reader-only class hides the content from the screen while still making it available to screen readers.&lt;/p&gt;

&lt;p&gt;Because the transform utility iterates over an array, a key is passed to the List component.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h3&gt;
  
  
  NavigationItem
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria Realized&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AC 3 - Lists should present with a role of "list", &lt;u&gt;list Items should present with a role of "listitem"&lt;/u&gt;.&lt;/li&gt;
&lt;li&gt;AC 9 - A link should contain a method of informing users which link corresponds to the current page for both screen and screen readers.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NavigationItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePathname&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;currentPath&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listItemProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListItemProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;children&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LinkProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;children&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-current&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;returnTrueElementOrUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPath&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; navigation`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pageURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ListItem&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;listItemProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;linkProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ListItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.3.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.3.1/src/ui/components/common/Navigation/components/NavigationItem.tsx" rel="noopener noreferrer"&gt;NavigationItem.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While not a detailed requirement, and mostly useful for tests and examples, the system does check for anchors passed through, and if an anchor is the only href aspect passed through, the path of the currently loaded page is prepended to the URL, which is ultimately passed to the link. Care should be taken that any objects used in production do not allow the passage of "/#".&lt;/p&gt;

&lt;p&gt;When a link is identical to the page currently loaded, the aria-current prop should be set to "page" (AC 9) but otherwise should be undefined. I'm using the NextJS function usePathname() to achieve this; your solution may be different.&lt;/p&gt;

&lt;p&gt;Even though nothing in the acceptance criteria requires it, an experienced developer will add information to the link about its purpose. Adding "navigation" to the label helps satisfy &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/?showtechniques=136#link-purpose-link-only" rel="noopener noreferrer"&gt;WCAG 2.4.9 Link Purpose&lt;/a&gt; by guaranteeing anyone using a screen reader understands that the links in the elements list/rotor are navigation-related. The label is prepended to the "navigation" description, satisfying &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/?showtechniques=136#label-in-name" rel="noopener noreferrer"&gt;WCAG 2.5.3 Label in Name&lt;/a&gt; for those who use their voice to interact with the component.&lt;/p&gt;

&lt;p&gt;Once again, a key is added to the ListItem component call since a ListItem can be rendered through an array map iteration.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h3&gt;
  
  
  SubNavigation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria Realized&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AC 4 - Buttons are associated with a sublist and indicate if the sublist is open or closed.&lt;/li&gt;
&lt;li&gt;AC 8 - A visual indicator is used to represent the state of the sublist's expanded status.&lt;/li&gt;
&lt;li&gt;AC 10 - A sublist may be toggled to open or close when the button associated with it is pressed.&lt;/li&gt;
&lt;li&gt;AC 11 - The state of a list's visible or hidden state should be easily perceived by any user
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SubNavigation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsSubListOpen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlePress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIsSubListOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-controls&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-expanded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; subnavigation`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;handlePress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iconProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;IconComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChevronRightIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isSilent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listItemProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationListProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isSubListOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-list`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ListItem&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;listItemProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;buttonProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Icon&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;iconProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationList&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`list-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;navigationListProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationList&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ListItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.3.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.3.1/src/ui/components/common/Navigation/components/SubNavigation.tsx" rel="noopener noreferrer"&gt;SubNavigation.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The entire subnavigation component is wrapped in a ListItem, which contains a Button and a NavigationList. This is the basis for creating a properly nested list within the navigation component. As with the NavigationItem component, the ListItem must include a key to meet React's requirements when generating the navigation from a JavaScript object.&lt;/p&gt;

&lt;p&gt;A button that controls another element, in this case the NavigationList component, associates itself with the NavigationList via the aria-controls attribute, which links to the NavigationList's id. Buttons also use the aria-expanded attribute to denote whether the item it controls is visible (aria-expanded ="true") or hidden (aria-expanded="false"). It's one of the few aria attributes where both true and false give meaning, and so it is always a boolean value. Additionally, an icon is included as a child of Button, indicating to screen-viewing users that the item is not a link and, when toggled, rotating between 0 and 90 degrees to indicate the list's visibility, satisfying AC 8. The actual visibility of the list can also be said to achieve AC 8.&lt;/p&gt;

&lt;p&gt;Along with their link counterparts, buttons are available in a different collection of a screen reader's list elements/rotor, and appending "subnavigation" satisfies the same WCAG success criterion.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria Realized&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AC 1 - The Navigation Component should be contained in a  landmark region.&lt;/li&gt;
&lt;li&gt;AC 2 -  The navigation should be presented as a nested structure of unordered lists within the  landmark region.&lt;/li&gt;
&lt;li&gt;AC 6 - When navigation is displayed in a horizontal layout, the first row of focusable elements should display as open by default.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;orientation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;horizontal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigationListProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;navigationProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationList&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;navigationListProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationList&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.3.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.3.1/src/ui/components/common/Navigation/components/Navigation.tsx" rel="noopener noreferrer"&gt;Navigation.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The navigation component wraps the first call to the NavigationList component within the  landmark, indicating that the component represents navigation and includes a label that identifies it to a screen reader. (AC 1). An uncontrolled component will always return the initial state of the top row as open and set an orientation of horizontal on the first row (AC 6), which is passed through to the NavigationList.&lt;/p&gt;

&lt;p&gt;Minimal styling is applied to the navigation component to rotate the icon when a button is toggled.&lt;/p&gt;

&lt;h3&gt;
  
  
  navigation.css
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;common-components&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;svg&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;aria-expanded&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"true"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="py"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90deg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.3.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.3.1/src/ui/components/common/Navigation/navigation.css" rel="noopener noreferrer"&gt;navigation.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most styling of a navigation component will take place elsewhere, but spacing and rotation of the icon are best handled within the component itself. As I mentioned before, I find it useful to style based on aria attributes rather than adding a class, letting my CSS add a small accessibility enforcement.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Transformation
&lt;/h2&gt;

&lt;p&gt;When a developer manually creates navigation code can look similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationItem&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item-one"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/one"&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Item One"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationItem&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item-two"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/two"&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Item Two"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SubNavigation&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Sub-One"&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Sub Nav One"&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationItem&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"item-three"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/tree"&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Item Three"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SubNavigation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, creating all the variants for examples and testing can be tedious, and realistically, the component's information will be read from a JavaScript object, whether from a static JSON file or an API via GraphQL. I also like standardizing examples across testing and browsers to make it easier to identify and fix issues.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tales&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tales-menu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;menu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;search-menu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;menu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Basic Search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;basic-search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/#basicsearch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Advanced Search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;advanced-search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/#advsearch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All Stories&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all-stories&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/#all-stories&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All Commentary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all-commentary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/#all-commentary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Find Your Next Story&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;find-next-story&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;menu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;By Storyteller&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;by-storyteller&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/#by-storyteller&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;By Era&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;by-era&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/#by-era&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;},]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JSON Navigation Example&lt;/strong&gt;  GitHub (release 0.3.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.3.1/src/ui/__static__/multiple-lists-buttons.json" rel="noopener noreferrer"&gt;multiple-lists-buttons.json&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A subset of the multiple-lists-buttons.json file is detailed above. Upon examination, any link will have a valid href, and any button will contain a menu array. While the href attribute on a button isn't used, it must still be present to conform to the object type. Theoretically, subnavigation objects may be nested indefinitely, but for testing purposes, only two levels are featured.&lt;/p&gt;

&lt;p&gt;The transform utility will take a full object and return the appropriately nested components to be rendered within the Navigation component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria Realized&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AC 13 - A JavaScript object containing a properly formed object should be able to be transformed into properly formed ListItems and Subnavigation lists.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformNavigation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;navigationArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Fragment&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`navigation-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;menu&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SubNavigation&lt;/span&gt;
                    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="na"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;testId&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;transformNavigation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SubNavigation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationItem&lt;/span&gt;
                    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="na"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;testId&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Fragment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.3.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.3.1/src/ui/components/common/Navigation/utilities/transformNavigation/transformNavigation.tsx" rel="noopener noreferrer"&gt;transformNavigation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The transform utility is recursive, calling itself for objects contained in a menu array. Other than recursion, it's fairly straightforward. Loop through the object; if it contains a menu, render the Subnavigation component, then call itself to render the children defined in the menu object. If the item mapped does not have a menu, render a NavigationItem component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ogk577t34mbx0tmrcyv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ogk577t34mbx0tmrcyv.gif" alt="Animated gif depicting basic navigation and demonstrating how drop downs react when the top row button is clicked." width="800" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When run in examples, the transformation returns a full navigation menu. And while it's obvious that a lot of work still needs to be done, there's now a solid foundation to work with.&lt;/p&gt;

&lt;p&gt;Return to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;With the transform utility, examples are now available in the release with just enough CSS to make operability feasible. Work can begin on horizontal and vertical menu styling.&lt;/p&gt;

&lt;p&gt;At this moment, the navigation component meets screen reader perceivability requirements. It can be used via the keyboard with the Tab Key and the Enter or Space keys to toggle the sublist availability. All links and buttons are available in the screen reader elements list and correctly denote their purpose. Not bad for just a skeleton; in fact, I know several teams that would consider the navigation component complete at this point. I'm not one of them, though.&lt;/p&gt;

&lt;p&gt;Next up will be the first of three releases dedicated solely to keyboard handling, concentrating on keyboard navigation through a single list.&lt;/p&gt;

</description>
      <category>react</category>
      <category>a11y</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Theming in the Modern Age</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Thu, 14 May 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/theming-in-the-modern-age-51ke</link>
      <guid>https://dev.to/shaynaproductions/theming-in-the-modern-age-51ke</guid>
      <description>&lt;p&gt;&lt;u&gt;&lt;em&gt;Prologue&lt;/em&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;A while ago, I decided to develop a fully accessible main navigation component in React and write a series of articles documenting the steps it took to create a non-trivial accessible component.&lt;/p&gt;

&lt;p&gt;In the last article, the focus was on the operability of foundational components that render valid HTML elements. This article focuses on screen perceivability and the foundational aspects around theming, design and CSS.&lt;/p&gt;

&lt;p&gt;CSS is used to illustrate design concepts. To that end, the theming system I'm using is solely composed of stylesheets.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article is one of a series demonstrating how to build a React navigational component from scratch while considering accessibility through the process. The articles are accompanied by a &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with releases tied to one or more articles; each building on the previous, until a fully implemented navigation component is complete.&lt;/p&gt;

&lt;p&gt;Each release and its associated tag contain fully runnable code for the article. The code discussed in this article is available in the release. and may be downloaded at &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/releases/tag/v0.2.1" rel="noopener noreferrer"&gt;release 0.2.1&lt;/a&gt;. A page showcasing these base components may be run locally through this release.&lt;/p&gt;

&lt;p&gt;While code examples are written in JavaScript for brevity, all actual code is written in Typescript and targets React 19.x. Examples use Next.js 16.x, which is not required to run the navigation component.&lt;/p&gt;

&lt;p&gt;Follow along either by downloading the release and running the examples while examining the codebase, or by activating the link accompanying each code snippet to view the full file on GitHub.&lt;/p&gt;




&lt;h2&gt;
  
  
  Content Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Primitive Components&lt;/li&gt;
&lt;li&gt;Santitization Scripts&lt;/li&gt;
&lt;li&gt;CSS Cascade Layers&lt;/li&gt;
&lt;li&gt;CSS Nesting&lt;/li&gt;
&lt;li&gt;Colors&lt;/li&gt;
&lt;li&gt;Design Tokens for Theming&lt;/li&gt;
&lt;li&gt;Component Theming&lt;/li&gt;
&lt;li&gt;Component Styling&lt;/li&gt;
&lt;li&gt;Box-Sizing with Border-Box&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In modern web development, theming systems are everywhere. Many of them integrate directly with JavaScript frameworks and support component styling by converting JavaScript objects into CSS with preprocessors like Styled Components or CSS-in-JS. Not surprisingly, I have thoughts around this.&lt;/p&gt;

&lt;p&gt;A tightly integrated theming system tied directly to JavaScript, such as Material-UI or Radix-UI, along with the requirement to write CSS within component files, can cause issues when upgrading or even moving to a different framework.&lt;/p&gt;

&lt;p&gt;This tight integration breaks the principle of separation of concerns. A theming system should sit alongside the project it affects and be available no matter the framework or language used. To my mind, a theming system should work just as well in a static HTML site as it does within a front-end framework such as Angular or React and work seamlessly when something in the stack needs to change.&lt;/p&gt;

&lt;p&gt;Modern CSS has evolved in leaps and bounds over the last few years. Psuedo-selectors such as :has() and :not() make targeting parent elements based on their children's attributes, or lack thereof, a reality. It's worth &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS" rel="noopener noreferrer"&gt;revisiting&lt;/a&gt; if you haven't looked at it in a while.&lt;/p&gt;

&lt;p&gt;I've had a love/hate relationship with CSS for a long time. I love the cascade aspect of CSS, but most styling frameworks seem to give it up in favor of writing styles directly in JSX or TSX files, with everything applied as classes. This approach adds complexity and reduces maintainability, especially when tracing style issues across components. I find it harder to maintain consistent styling when CSS can't be applied consistently across components. Is it doable? Yes. Is it easy and intuitive? No.&lt;/p&gt;

&lt;p&gt;For most of my career, CSS has seemed like something I fight rather than something that just works. Dealing with browser inconsistencies and the battle between the styles set by third-party component libraries, the desires of the various design teams I've worked with, alongside the requirement to keep all styling in components and style everything in a class, has been my reality for years. Working with designs created by those who've rarely considered specificity or cross-browser styles has been challenging. Not to mention the issues of overriding a component library's styles to conform to another's vision.&lt;/p&gt;

&lt;p&gt;My vision for a theming system is one built on modern CSS, which, for the most part, sits alongside my React components. I've built it on four pillars.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;u&gt;Primitive components&lt;/u&gt;: are those components where the focus by the developers has been on operability and functionality, not on perceivability. These components are released without any CSS styles and are styled only by the browser in which it is run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;u&gt;Sanitization scripts&lt;/u&gt;: to standardize styles across browsers and, in many cases, removing most of the visual styling, goes a long way toward reducing the headache of trying to make something look the same way across browsers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;u&gt;CSS Cascade Layers&lt;/u&gt;: widely supported across browsers, allows for defining explicit contained layers of specificity, reducing the need for long strings of classes and the use of !important.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;u&gt;CSS Nesting&lt;/u&gt;: allows for writing more modular, maintainable and readable CSS. It's similar to SASS nesting, using the same &amp;amp; operator, but it also supports all the newer pseudo-element selectors, which sadly SASS hasn't kept up with.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Primitive Components
&lt;/h2&gt;

&lt;p&gt;Open source primitive component libraries abound. Radix, React Aria Components, Reach, Reakit and AriaKit all provide unstyled components that emphasize operability and accessibility. There's no fighting over opinionated CSS because there is no opinion on how to style these components other than those of the people responsible for the design.&lt;/p&gt;

&lt;p&gt;My current implementation uses react-aria-components, an underlying primitives library provided by Adobe.&lt;/p&gt;

&lt;p&gt;Primitive libraries, which feature operable components with no styling applied, have reduced the need to reconcile component-agnostic styling with corporate directives. I will admit I was intimidated by the idea of adding all the styling necessary to components, but the payoff has been worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Santitization Scripts
&lt;/h2&gt;

&lt;p&gt;A good set of sanitization scripts goes a long way towards sane styling. Sanitization scripts remove the inconsistencies across browsers, and the one I use removes most visual styling altogether.&lt;/p&gt;

&lt;p&gt;Developing a vanilla theming system using modern CSS, along with robust sanitization scripts and primitive components that are initially operable but not perceivable, has changed the way I think about the HTML elements I work with every day. The first time I loaded a sanitized, unstyled, empty button onto a page, I thought I did something wrong. My screen was blank; the only way I knew a button was loaded was by checking the DOM. I added a border width and style, still nothing. It was only when I applied a color to the border that a small box appeared. I added text to my button, and to my amazement, it was flexible: it had no specified height or width, and no padding or margins; it hugged its content tightly.&lt;/p&gt;

&lt;p&gt;Standardizing on &lt;code&gt;box-size: border-box&lt;/code&gt; made a huge difference. Suddenly, setting a specific width meant the element's width never changed. Border widths and padding sizes are part of the set width. True consistency is achievable.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Cascade Layers
&lt;/h2&gt;

&lt;p&gt;CSS &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@layer" rel="noopener noreferrer"&gt;Layers&lt;/a&gt; applies an order of precedence based on an @rule, reducing the need for specificity. Styles lower in the layer hierarchy are easily overridden by styles in higher layers, reducing the need for !important declarations and long, hard-to-follow selectors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default-theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base-component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;common-component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system-component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/blob/v0.2.1/src/theme-system/base/layers.css" rel="noopener noreferrer"&gt;Theming System - layers.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Layers within a theming system are self-defined. We determine which layers exist and which layers are higher in precedence. Layers are applied from left to right; any overrides in a layer defined to the right are applied without additional specificity or the need for !important.&lt;/p&gt;

&lt;p&gt;In my layer system, I begin with reset, which contains my sanitization scripts that remove all padding and borders and standardize elements across browsers.&lt;/p&gt;

&lt;p&gt;Anything defined in the reset layer may be overridden by the other layers, including the system layer, which holds design tokens for colors and underlying choices, such as the creation of my relative pixel base size and global srOnly class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--sizing-base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sizing-base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.0625&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--shadow-opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--overlay-opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.srOnly&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* 1 */&lt;/span&gt;
    &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* 2 */&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* 3 */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/blob/v0.2.1/src/theme-system/base/layers.css" rel="noopener noreferrer"&gt;Theming System - base.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While layers reduce the need for the keyword, !important, it still has its uses. In the case of my srOnly class, the properties overflow, position and whitespace may not be overwritten no matter what. Since those three properties define removing the class applied element from the screen, they are integral to the style.&lt;/p&gt;

&lt;p&gt;Layers address many of the issues around specificity and are well worth the time to get to know them. They form an integral part of my theming system.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Nesting
&lt;/h2&gt;

&lt;p&gt;Nested CSS, a fully supported feature of CSS, mimics SASS in some ways, and when implemented inside @layer, removes the need for chaining selectors and allows for more modularity. When base components render into actual structured HTML elements, the need for adding a class to everything disappears.&lt;/p&gt;

&lt;p&gt;I think the mindset around CSS usage has suffered from the overuse of classes, and I blame Macromedia for their decision when creating Dreamweaver to make everything a class, which in turn has influenced a generation of developers. Trying to debug conflicting styles when everything is styled via a string of classes to provide enough specificity has turned many stylesheets into a morass where developers fear to tread.&lt;/p&gt;

&lt;p&gt;When nested CSS is used alongside HTML elements rather than classes, everything starts to make sense.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;#base-components&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;ul.general&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;column-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;list-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inside&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-border-width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;border-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--purple-3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;list-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="err"&gt;&amp;amp;:first-child&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;border-left-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.general&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;list-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;li&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;47%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;radial-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="m"&gt;#0000&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-1&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;38.85&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/blob/v0.2.1/src/folio/Pages/BaseComponentsPage/baseComponentsPage.css" rel="noopener noreferrer"&gt;baseComponentsPage.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The example above is a snippet styling the base components example page in the demo. Notice how everything cascades from a single id, using descendant selectors to drill down into elements and apply styling. All widths and gaps are either percentages or derived as relative pixels using the technique I described in a previous article, &lt;a href="https://dev.to/shaynaproductions/spacing-considerations-in-accessible-design-47ad"&gt;Spacing Considerations In Acessible Design&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With these four pillars in place, everything I dreaded about working with CSS disappeared. Instead of fighting CSS specificity and trying to debug why a particular style was being overridden and from where within a sea of CSS within components, something changed. CSS flowed, it was easy and best of all, it just worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Colors
&lt;/h2&gt;

&lt;p&gt;Perceivable colors that automatically work in both light and dark modes, and that provide sufficient color contrast between foreground and background, are not hard to achieve, especially when each color is separated into a set of colors sharing the same hue, varying only saturation and lightness.&lt;/p&gt;

&lt;p&gt;Using human-readable color spaces such as LCH or HSL is preferable to hex codes or RGB because colors can be computed from a given hue. Both are human-readable and fully supported across browsers. I've used both in this theming system across two colors: gray uses HSL, and purple uses LCH. I'm starting to prefer HSL for the many generators available and its ease of readability, which is easier to understand than LCH.&lt;/p&gt;

&lt;p&gt;Colors are stored in color files, each of which can define 7 or 12 design tokens that differ mostly in saturation and lightness. Definitions in the color files can be set to automatically change based on a user's light or dark mode preference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/*Based off hue 151 */&lt;/span&gt;
  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/*Light Desaturated - Background */&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;96.73%&lt;/span&gt; &lt;span class="m"&gt;0.00508&lt;/span&gt; &lt;span class="m"&gt;325.62&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90.813%&lt;/span&gt; &lt;span class="m"&gt;0.02278&lt;/span&gt; &lt;span class="m"&gt;321.35&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;84.919%&lt;/span&gt; &lt;span class="m"&gt;0.03759&lt;/span&gt; &lt;span class="m"&gt;320.35&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c"&gt;/* Light Saturated */&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;79.126%&lt;/span&gt; &lt;span class="m"&gt;0.0733&lt;/span&gt; &lt;span class="m"&gt;320.93&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;73.236%&lt;/span&gt; &lt;span class="m"&gt;0.0934&lt;/span&gt; &lt;span class="m"&gt;321.48&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;67.281%&lt;/span&gt; &lt;span class="m"&gt;0.10972&lt;/span&gt; &lt;span class="m"&gt;321.13&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c"&gt;/* Medium */&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;62.241%&lt;/span&gt; &lt;span class="m"&gt;0.10499&lt;/span&gt; &lt;span class="m"&gt;321.38&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="py"&gt;--raw-purple-8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;55.082%&lt;/span&gt; &lt;span class="m"&gt;0.09248&lt;/span&gt; &lt;span class="m"&gt;321.86&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;48.822%&lt;/span&gt; &lt;span class="m"&gt;0.08156&lt;/span&gt; &lt;span class="m"&gt;321.03&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c"&gt;/* Dark */&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;42.402%&lt;/span&gt; &lt;span class="m"&gt;0.07362&lt;/span&gt; &lt;span class="m"&gt;322.08&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-11&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;36.178%&lt;/span&gt; &lt;span class="m"&gt;0.06256&lt;/span&gt; &lt;span class="m"&gt;322.17&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--raw-purple-12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;29.673%&lt;/span&gt; &lt;span class="m"&gt;0.05099&lt;/span&gt; &lt;span class="m"&gt;322.32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="py"&gt;--purple-1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-6&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-7&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-9&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-10&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-11&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-11&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;--purple-12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--raw-purple-12&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c"&gt;/*Light Desaturated - Background */&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;96.73%&lt;/span&gt; &lt;span class="m"&gt;0.00508&lt;/span&gt; &lt;span class="m"&gt;325.62&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-11&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90.813%&lt;/span&gt; &lt;span class="m"&gt;0.02278&lt;/span&gt; &lt;span class="m"&gt;321.35&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;84.919%&lt;/span&gt; &lt;span class="m"&gt;0.03759&lt;/span&gt; &lt;span class="m"&gt;320.35&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="c"&gt;/* Light Saturated */&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;79.126%&lt;/span&gt; &lt;span class="m"&gt;0.0733&lt;/span&gt; &lt;span class="m"&gt;320.93&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;73.236%&lt;/span&gt; &lt;span class="m"&gt;0.0934&lt;/span&gt; &lt;span class="m"&gt;321.48&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;67.281%&lt;/span&gt; &lt;span class="m"&gt;0.10972&lt;/span&gt; &lt;span class="m"&gt;321.13&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c"&gt;/* Medium */&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;62.241%&lt;/span&gt; &lt;span class="m"&gt;0.10499&lt;/span&gt; &lt;span class="m"&gt;321.38&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="py"&gt;--raw-purple-5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;55.082%&lt;/span&gt; &lt;span class="m"&gt;0.09248&lt;/span&gt; &lt;span class="m"&gt;321.86&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;48.822%&lt;/span&gt; &lt;span class="m"&gt;0.08156&lt;/span&gt; &lt;span class="m"&gt;321.03&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="c"&gt;/* Dark */&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;42.402%&lt;/span&gt; &lt;span class="m"&gt;0.07362&lt;/span&gt; &lt;span class="m"&gt;322.08&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;36.178%&lt;/span&gt; &lt;span class="m"&gt;0.06256&lt;/span&gt; &lt;span class="m"&gt;322.17&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="py"&gt;--raw-purple-1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;29.673%&lt;/span&gt; &lt;span class="m"&gt;0.05099&lt;/span&gt; &lt;span class="m"&gt;322.32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/blob/v0.2.1/src/theme-system/base/colors/purple.css" rel="noopener noreferrer"&gt;Theming System - purple.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The color file for purple, shown above, defines the same colors in both light and dark color schemes as the raw variables, which are then defined using oklch(). This enables an automatic dark color scheme and allows using the --raw variables when opacity needs to be adjusted. My initial foray into this was discovering the custom palettes available through &lt;a href="https://www.radix-ui.com/colors/custom" rel="noopener noreferrer"&gt;Radix-UI&lt;/a&gt;, though I don't use their generator at all.&lt;/p&gt;

&lt;p&gt;A color sheet created in this manner also allows for easily achievable color contrast. Formulas for non-vibrant colors achieve color contrast with variables -1 through -4 when paired with any color in the -8 through -12 range. You can see this in a palette color theming system called &lt;a href="https://primer.style/prism/" rel="noopener noreferrer"&gt;primer prism&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkn34uamoydfba2d3ob5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkn34uamoydfba2d3ob5.png" alt="Primer Prism screen shot implementing the purple colors detailed earlier" width="800" height="701"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Tokens for Theming
&lt;/h2&gt;

&lt;p&gt;CSS variables are not just for setting colors. They are flexible and mutable, allowing themselves to be set and reset to affect only those elements contained in a selector. Design tokens can be used by base components, tying them into the design system in a way that goes far beyond simple color selection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"initial"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"secondary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Hello World&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consider the HTML code above. Two series of nested empty divs, with the second series also holding a button in the innermost div.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#initial&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--theme-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--red-1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;160&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;div&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--theme-background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--theme-border-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;div&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="py"&gt;--theme-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--purple-2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;div&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;--theme-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3jzn78aleaz5041qrvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3jzn78aleaz5041qrvu.png" alt="A rendered example of the html and css code showing different colored backgrounds achieved solely by resetting the theme-background design token" width="412" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The CSS sets the —theme-background token to a light red and applies it to every div in the DOM, along with padding. Using Nested CSS and the descendant selector, I can target the individual divs nested within each other and change the theme background.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#secondary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--theme-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;-160&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;180&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;div&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--theme-background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--theme-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;div&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="py"&gt;--theme-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--red-3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; &lt;span class="err"&gt;button&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;--button-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--purple-6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="py"&gt;--button-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhb4o3o9pe53aidddwt52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhb4o3o9pe53aidddwt52.png" alt="A rendered example showing both the initial and secondary styling with the secondary div showing a gray background, superseded by a brighter red background and finally a button whose background becomes a deep purple with white lettering spelling out " width="610" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the secondary example, a button is targeted by a —button-background token, along with setting the text color to a lighter value.&lt;/p&gt;

&lt;p&gt;Variables set at a specific point in the DOM affect only the items contained within it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component Theming
&lt;/h2&gt;

&lt;p&gt;The theming I'm using in the repository is pared down to the bare minimum, and isn't the best representation of what it will eventually become. But it's sufficient to demonstrate the power of plain CSS and Structural HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Button*/&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Common widths and spacing */&lt;/span&gt;
  &lt;span class="py"&gt;--button-padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--button-font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--button-line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--button-letter-spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* theme - Solid */&lt;/span&gt;
  &lt;span class="py"&gt;--button-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--purple-2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-background-disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-background-interactive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--purple-3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-background-pressed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--purple-4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="py"&gt;--button-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-border-color-disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-border-color-interactive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-border-color-pressed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-border-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="py"&gt;--button-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-color-disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-color-interactive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--purple-11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-color-pressed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray-11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="py"&gt;--button-fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--purple-12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-fill-disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-color-disabled&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-fill-interactive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-color-interactive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--button-fill-pressed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-color-pressed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c"&gt;/* Ghost  */&lt;/span&gt;
  &lt;span class="py"&gt;--button-ghost-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--button-ghost-border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/theme-system/themes/default/components/component.css" rel="noopener noreferrer"&gt;component.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm going to use the button component to demonstrate the theming. You'll notice that design tokens have been set up not only for background, border and text colors, but also for states. There are tokens to hold colors for interactive states, including :hover and :focus, and the pressed variables hold changes when the :active state is in place. Because buttons can hold icons, tokens for various fill states are also set.&lt;/p&gt;

&lt;p&gt;With the base button tokens defined, it's time to add them to the actual component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component Styling
&lt;/h2&gt;

&lt;p&gt;Component stylesheets live in the same folder as their component, and, since I'm using Next.js, are side-loaded into the globals.css file to ensure they are loaded only once. Not every base component needs to include specific styling; where styling is present, it should be generic. Styling for base components is applied in an &lt;code&gt;@layer base-component{element{}}&lt;/code&gt; to ensure initial styling is available regardless of where the HTML element is located.&lt;/p&gt;

&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Button/button.css" rel="noopener noreferrer"&gt;button.css&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;  &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c"&gt;/* Layout */&lt;/span&gt;
      &lt;span class="nl"&gt;align-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-padding&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fit-content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every button starts with a flex layout that centers its content and initially sets its width to fit the content. Padding is wired in through the button-padding token since that can and will be changed regularly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;   &lt;span class="c"&gt;/* continued */&lt;/span&gt;
  &lt;span class="c"&gt;/* Text */&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-font-size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-font-weight&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;letter-spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-letter-spacing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-line-height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* Appearance */&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-border-radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-border-width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Text and appearance depend on more tokens, which can be overridden wherever necessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;   &lt;span class="c"&gt;/* continued */&lt;/span&gt;
&lt;span class="c"&gt;/* Colors */&lt;/span&gt;
&lt;span class="py"&gt;--svg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="py"&gt;--svg-fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-fill&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-border-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All colors associated with the button are set to the tokens by default. Either the background-color or the token may be overridden.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;   &lt;span class="c"&gt;/* continued */&lt;/span&gt;
    &lt;span class="c"&gt;/* States - */&lt;/span&gt;
    &lt;span class="err"&gt;&amp;amp;[aria-disabled="true"]&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="py"&gt;--button-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-background-disabled&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="py"&gt;--button-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-border-color-disabled&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="py"&gt;--button-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-color-disabled&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="py"&gt;--svg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-color-disabled&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="py"&gt;--svg-fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-fill-disabled&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:focus-visible&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--focus-outline&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--focus-outline-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nl"&gt;outline-offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--focus-outline-offset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="py"&gt;--button-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-background-interactive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="py"&gt;--button-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-border-color-interactive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="py"&gt;--button-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-color-interactive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="py"&gt;--svg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-color-interactive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="py"&gt;--svg-fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--button-fill-interactive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it comes to state changes, I prefer to style them using either aria- attributes or pseudo-classes such as :focus and :hover. Styling on aria- attributes reinforces accessibility. If the aria- attribute is required, why not style it through the attribute rather than adding in yet another class that needs to be deciphered?&lt;/p&gt;

&lt;p&gt;In the article &lt;a href="https://dev.to/shaynaproductions/foundational-accessibility-begins-with-the-base-components-2nac/#button-component"&gt;Foundational Accessibility Begins with the Base Components&lt;/a&gt;, I explained how the disabled attribute causes issues with screen readers and proposed a fix that used aria-disabled instead. The styles around the aria-disabled attribute are the last aspect necessary. Note how every line in the rule simply replaces the original token with one based on a disabled state. That's all that is necessary. It's the same with the focus and hover pseudo-classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Box-Sizing with Border-Box
&lt;/h2&gt;

&lt;p&gt;My sanitization scripts apply the &lt;code&gt;box-sizing: border-box&lt;/code&gt; rule to every element. This box-sizing rule defines the width and height to include content, padding, and borders. I've found this rule makes it easier to work with positioning and layout, since a component's width and height remain constant regardless of padding or borders.&lt;/p&gt;

&lt;p&gt;When using "border-box", note that changing from "border: none" to "border: solid" or adjusting the border-width during a state change will shift the component's content. My solution is to set the border width in advance and use "color: transparent" to emulate a no-border effect. In this scenario, a user sees a borderless box since the transparent border sits on top of the background. During a state change, there is no shifting, since the border simply swaps colors. Make sure the border-width remains consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Adding a theming system doesn't have to be complicated or require another package. Regardless of the theming system you use, wiring the components that render to HTML into your system will save a lot of time and headaches down the road.&lt;/p&gt;

&lt;p&gt;With the base components added in and connected to the theming systems, the next step will be to create the actual components of the Navigation system.&lt;/p&gt;

</description>
      <category>css</category>
      <category>designsystem</category>
      <category>a11y</category>
      <category>theming</category>
    </item>
    <item>
      <title>Foundational Accessibility Begins with the Base Components</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Tue, 12 May 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/foundational-accessibility-begins-with-the-base-components-2nac</link>
      <guid>https://dev.to/shaynaproductions/foundational-accessibility-begins-with-the-base-components-2nac</guid>
      <description>&lt;p&gt;&lt;u&gt;&lt;em&gt;Prologue&lt;/em&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;A while ago, I decided to develop a fully accessible main navigation component in React and write a series of articles documenting the steps it took to create a non-trivial accessible component.&lt;/p&gt;

&lt;p&gt;This article is part of the series and marks the first time code will be introduced and discussed. It's all about the base.&lt;/p&gt;

&lt;p&gt;I define base components as components that wrap elements that ultimately render to plain HTML from React. If your base components don't take accessibility into consideration, achieving accessibility becomes infinitely harder. A website or application can only be as accessible as its base components allow.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article is one of a series demonstrating how to build a React navigational component from scratch while considering accessibility through the process.  The articles are accompanied by a &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with releases tied to one or more articles; each building on the previous, until a fully implemented navigation component is complete.&lt;/p&gt;

&lt;p&gt;Each release and its associated tag contain fully runnable code for the article. The code discussed in this article is available in the release. and may be downloaded at &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/releases/tag/v0.2.1" rel="noopener noreferrer"&gt;release 0.2.1&lt;/a&gt;. A page showcasing these base components may be run locally through this release.&lt;/p&gt;

&lt;p&gt;While code examples are written in JavaScript for brevity, all actual code is written in Typescript and targets React 19.x. Examples use Next.js 16.x, which is not required to run the navigation component.&lt;/p&gt;

&lt;p&gt;Follow along either by downloading the release and running the examples while examining the codebase, or by activating the link accompanying each code snippet to view the full file on GitHub.&lt;/p&gt;




&lt;h2&gt;
  
  
  Content Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Base Components&lt;/li&gt;
&lt;li&gt;Text Component&lt;/li&gt;
&lt;li&gt;Icon Component&lt;/li&gt;
&lt;li&gt;List and ListItem Components&lt;/li&gt;
&lt;li&gt;Button Component&lt;/li&gt;
&lt;li&gt;Link Component&lt;/li&gt;
&lt;li&gt;Box Component&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Universal accessibility depends on structural and semantic HTML. Semantics convey meaning to screen readers and other assistive technologies. No matter what language or framework is ultimately used, in the end, every user interface component ultimately renders into plain &lt;a href="[https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements"&gt;HTML Elements&lt;/a&gt;, which, for all intents and purposes, exposes the same information across browsers and devices. Whether a component or a page, your code can only be as accessible as the base components it is built on.&lt;/p&gt;

&lt;p&gt;Why do developers love divs so much? Why is the use of divs and classes so prevalent when structural HTML conveys more information, and the underlying components are built within browsers to be accessible?&lt;/p&gt;

&lt;p&gt;Divs are flexible, with no formatting applied.  They have no specified height or width, and no padding or margins; they hug their content tightly. They make styling easier, since they aren't subject to the style choices of third-party component libraries or the underlying browser style sheets.&lt;/p&gt;

&lt;p&gt;But what if almost every structural HTML component was available with styling stripped out? What if almost every HTML element could be set to be as flexible as a div, with no height or width, no specified borders and no padding. What if each HTML element hugged its content as tightly as a div does?  Would you use it then?&lt;/p&gt;

&lt;p&gt;An accessible website limits the use of &amp;lt;div /&amp;gt;'s to containers for positioning or the creation of custom widgets.  &amp;lt;div /&amp;gt;, like its cousin &amp;lt;span /&amp;gt; conveys no semantic meaning. If a &amp;lt;div /&amp;gt; is used as the basis for a custom widget, it needs to pass both role and label.&lt;/p&gt;

&lt;p&gt;In a previous article, &lt;a href="https://dev.to/shaynaproductions/the-modalities-of-accessibility-2hhe"&gt;Modalities of Accessibility&lt;/a&gt;, I discussed applying the first two principles of the &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/" rel="noopener noreferrer"&gt;Web Content Accessibility Guidelines&lt;/a&gt; through the lens of different peripherals. How something &lt;em&gt;operates&lt;/em&gt; has little if anything to do with how it is &lt;em&gt;perceived&lt;/em&gt;. When developing a component, I have no opinion on its styling; my focus is on ensuring it meets the stated operable requirements. Styling and design are separate concerns from coding for operability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Base Components
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fixing and Expanding Accessibility and Functionality&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Base components can be imported from a third-party library or written in-house. They wrap around and ultimately render a single HTML element. In either case, modifications can be made to fix issues, expand and enhance functionality, and make it easier for developers to achieve accessibility when using these components.&lt;/p&gt;

&lt;p&gt;Using structural HTML and Accessible Rich Internet Applications (ARIA) is part of the toolkit when creating an accessible website, but knowing when to use those tools is just part of it. Developers need to know when it's appropriate to use an aria attribute and when it's not. There's a reason the phrase "No Aria is better than Bad Aria" is widely known.&lt;/p&gt;

&lt;p&gt;In some cases, existing operability can actually interfere with accessibility. Consider the &lt;u&gt;&amp;lt;button disabled="true" /&amp;gt;&lt;/u&gt; situation. Every browser/screen reader combination exhibits the same issue. If a button is disabled by setting the &lt;strong&gt;disabled&lt;/strong&gt; attribute, it is invisible to a screen reader when the user navigates the screen when using Tab. Any button built will have this issue unless it is addressed in the base component. This issue will be examined when discussing the Button component.&lt;/p&gt;

&lt;p&gt;The base components I'll be using in this demo will differ from the components you will have available to you. I'm using a combination of react-aria-components, a Next.js link, and even rolling a few of my own. Consider this article and release as roadmaps to help you enhance your own components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item One&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-two"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Two&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-three"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Three&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"subnav-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-four"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Four&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-five"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Five&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-six"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Six&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-seven"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Seven&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-eight"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Eight&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[HTML output structure for a navigation component]&lt;/p&gt;

&lt;p&gt;When examining the agreed-upon HTML navigation structure, the following Base components are required.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;lt;List /&amp;gt; - (renders &amp;lt;ul  /&amp;gt; or &amp;lt;ol /&amp;gt;)&lt;/li&gt;
&lt;li&gt;&amp;lt;ListItem /&amp;gt; - (renders &amp;lt;li /&amp;gt;) valid only when a direct child of &amp;lt;List /&amp;gt;&lt;/li&gt;
&lt;li&gt;&amp;lt;Button /&amp;gt; - (renders &amp;lt;button /&amp;gt;&lt;/li&gt;
&lt;li&gt;&amp;lt;Link /&amp;gt; - (renders &amp;lt;a href /&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Link component also contains other components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;lt;Icon /&amp;gt; - (renders a react-icon) - used in the &amp;lt;Link /&amp;gt;  component.&lt;/li&gt;
&lt;li&gt;&amp;lt;Text /&amp;gt; - (renders &amp;lt;p /&amp;gt; or &amp;lt;span /&amp;gt;) wraps around text not directly contained within a component.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, I'll address the creation of a &amp;lt; Box /&amp;gt; component, as it requires special handling when creating composite widgets.&lt;/p&gt;

&lt;p&gt;Some of these components (Button, Link, and Text) will wrap components from third-party libraries, and other components (List, ListItem, Box) will wrap HTML elements. Additional functionality, either security- or accessibility-focused, will be applied to most of these components.&lt;/p&gt;

&lt;p&gt;Where do the accessibility requirements for these components come from? Some of the requirements are lifted from the &lt;a href="https://media.dequeuniversity.com/en/docs/web-accessibility-checklist-wcag-2.2.pdf" rel="noopener noreferrer"&gt;Web Accessibility Checklist&lt;/a&gt; from Deque. Additional requirements are in place to enhance the developer experience and make it easier for them to apply accessibility features specific to the component.&lt;/p&gt;

&lt;p&gt;The requirements can be found in the &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQC-Dx1VN2b7Raew3h7PpGiSAagY51mt1-0oEayL_qfWIlQ?e=rDitPz" rel="noopener noreferrer"&gt;Accessible Base Component Requirements&lt;/a&gt; spreadsheet and are also listed in this article under the appropriate component.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;A Word on Typing and Testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code in the &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;repository&lt;/a&gt; is fully typed and tested against the acceptance criteria. Typing is removed from the example code presented in the articles for brevity, but the code required through typing is included. A test file is created alongside the component, and each test is initially set up to conform to one or more acceptance criteria.  While I won't detail all the tests in the article, the first component discussed will present a test skeleton, and the full tests are a part of each release.&lt;/p&gt;




&lt;h3&gt;
  
  
  Text Component
&lt;/h3&gt;

&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Text" rel="noopener noreferrer"&gt;components/base/Text&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A paragraph has semantic meaning. It's a block of text containing related sentences with distinct beginnings and ends. On a screen, we can discern different paragraphs by the vertical margins between them. A screen reader uses &amp;lt;p /&amp;gt; as an indication to pause before reading the next paragraph. And while a &amp;lt;span /&amp;gt; has no semantic meaning, it's useful for styling or marking up text with attributes, such as language&lt;br&gt;
changes, denoting an abbreviation or using another &lt;a href="https://www.tutorialspoint.com/html/html_phrase_elements.htm" rel="noopener noreferrer"&gt;phrase control&lt;/a&gt; element to add semantic meaning into text content.&lt;/p&gt;

&lt;p&gt;My text component wraps around its undocumented namesake in react-aria-components. The main thrust of the code is to provide enhancements that allow a screen reader to access information without displaying it on screen. Feel free to use the code I provide to enhance your own text component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria&lt;/strong&gt; - Text Component&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text AC 1 - Containing elements are restricted to &amp;lt;p&amp;gt; (default) and &amp;lt;span&amp;gt;.&lt;/li&gt;
&lt;li&gt;Text AC 2 - Text may be hidden from view while still available to a screen reader.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many component libraries, including &lt;a href="https://github.com/adobe/react-spectrum/blob/main/packages/react-aria-components/src/Text.tsx" rel="noopener noreferrer"&gt;react-aria-components&lt;/a&gt;, allow their Text component to be rendered as any of several HTML elements, which can be passed in. I'm not fond of the approach since the odds of creating a fully accessible component that works seamlessly as the element sent through aren't very good. The underlying react-aria-component will be used to keep consistency, while restricting it to paragraphs and spans.&lt;/p&gt;

&lt;p&gt;In development, situations arise when an aria-label or aria-describedby cannot provide screen readers with an equitable experience, and additional text, not visible on the screen, is useful. A number of component libraries include a &amp;lt;Hidden /&amp;gt; or &amp;lt;VisuallyHidden /&amp;gt; component for these circumstances, but I've found it makes more sense to just expand the functionality of Text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing Skeleton&lt;/strong&gt;&lt;br&gt;
As mentioned earlier, testing is integral to component development. The acceptance criteria are mapped to the test, and tests are fleshed out as the component is built. The initial test file for Text is shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;Text /&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should be WCAG compliant as a Phrase control&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* Conforms to Text AC 1 */&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should be WCAG compliant as a Flow control&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* Conforms to Text AC 1 */&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should load as inline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* Conforms to Text AC 1 */&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should be visually hidden when isHidden is true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* Conforms to Text AC 2 */&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most testing begins with a simple test to confirm a component is mounted, but I've found that substituting automated accessibility testing using jest/axe for the mount makes more sense. While automated accessibility testing can only catch objective issues, such as when interactive items are nested within one another or when something lacks a label, using it as a first test can still help catch issues early. Automated axe testing cannot evaluate subjective criteria, such as whether labels or text adequately convey the required information, but it's a step in the right direction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;isHidden&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;IsInline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;textProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;classNames&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;srOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isHidden&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-testid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;elementType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isInline&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;span&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RACText&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;textProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;RACText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Text/Text.tsx" rel="noopener noreferrer"&gt;Text.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two props are added to enhance the underlying component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When &lt;strong&gt;isHidden&lt;/strong&gt; is set to true, a class of &lt;a href="https://dev.to/shaynaproductions/creating-initial-requirements-for-an-accessible-navigation-component-526p"&gt;&lt;em&gt;.srOnly&lt;/em&gt;&lt;/a&gt; is sent into the component, effectively removing the component from the screen, while still keeping it in the DOM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;isInline&lt;/strong&gt; property restricts rendering to &amp;lt; span /&amp;gt; or &amp;lt;p /&amp;gt;. A span is considered phrase control, which means it can be used within text content and is typically used with a &lt;code&gt;display: inline&lt;/code&gt; or one of its offshoots. Paragraphs are considered flow control and always start on a new line.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any attribute passed to my components that isn't explicitly pulled out is sent to the HTML element. This allows any specific aria attributes to be passed through without having to specify each one. Linting will throw an error if a non-viable HTML attribute is passed in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Icon Component
&lt;/h3&gt;

&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Icon" rel="noopener noreferrer"&gt;components/base/Icon folder&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a variety of ways to add icons into your application. I use the react-icons library; your code might use another library, such as FontAwesome or hand-built SVGs. While the react-icons library can be used directly, I prefer to wrap the icons into their own component to extend its functionality. The &amp;lt;Icon /&amp;gt; component receives the icon it is to display and applies accessibility checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Icon AC 1 - When not decorative or duplicative of meaning, an icon shall have a label describing its function.&lt;/li&gt;
&lt;li&gt;Icon AC 2 - When an icon is decorative or the meaning is already expressed by the element wrapping the icon, the icon shall be hidden from the screen reader.&lt;/li&gt;
&lt;li&gt;Icon AC 3: Either a label or a directive to hide the icon from screen readers is required, not both.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Icons are images and, as such, need to be labeled when the information they convey isn't already available. If the meaning is already available through a parent element, such as an aria-label on a button that wraps the icon, then the icon should be hidden from screen readers since the information it conveys is already available. Any description of an icon should not describe what it looks like; rather, it should describe the &lt;br&gt;
functionality it conveys.&lt;/p&gt;

&lt;p&gt;AC 1 and AC 2 describe two competing requirements.  Either a label is necessary and should be passed in, or the label is not necessary, and the icon should be silent and hidden from screen readers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;IconComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isSilent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;proceed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isSilent&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dev Error: (Icon) - WCAG 1.1.1: Label must be provided when isSilent is not set.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;proceed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isSilent&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dev Error: (Icon) - WCAG 1.1.1 Label may not be defined when isSilent is set to true.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;proceed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proceed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iconProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-hidden&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;returnTrueElementOrUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;isSilent&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;classNames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svg-icon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-testid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;graphics-symbol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IconComponent&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;iconProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Icon/Icon.tsx" rel="noopener noreferrer"&gt;Icon.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The acceptance criteria state that either a label is present or isSilent is true, which means neither prop can be required. Since both props are conditional, console errors are thrown when neither condition is met or when both conditions exist, and the component returns nothing in development or testing environments. To render an icon, a developer must meet the acceptance criteria conditions. Checks are ignored in production, so the icon will always be rendered.&lt;/p&gt;

&lt;p&gt;It's fairly easy to set any icon without a label to aria-hidden; however, not every developer understands the need to ensure a label is present when an icon is not decorative and is not associated with text that will substitute for labeling. Simply hiding all labels when none are passed is a sure way to fail an accessibility audit. Instead, a developer is reminded to either explicitly set isSilent or to pass a label.&lt;/p&gt;

&lt;p&gt;Adding a check like this and preventing rendering when conditions aren't met is necessary. I've seen developers ignore or actively try to suppress console error messages without actually fixing the issue when the component renders with the error. Exposing error messages in a development environment serves as a reminder to developers that accessibility needs to be considered.&lt;/p&gt;

&lt;p&gt;An icon's role is "graphics-symbol," and so is explicitly set across any icon.&lt;/p&gt;

&lt;p&gt;"aria-hidden" in IconProps calls &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/utilities/returnTrueElementOrUndefined" rel="noopener noreferrer"&gt;&lt;strong&gt;returnTrueElementOrUndefined()&lt;/strong&gt;&lt;/a&gt;, a custom function, to return undefined if isSilent is false. It's used because several aria attributes should not be sent when the boolean value is false.&lt;/p&gt;

&lt;p&gt;To illustrate this point, consider a grouping of ten checkboxes, of which two are checked, exposing an aria-checked="true". When a Boolean value is passed, and the other eight are set to "false," then a screen reader will announce the check status for every item, resulting in aural clutter. ("Checkbox 1, checked. Checkbox 2, unchecked. Checkbox 3, unchecked.") By sending aria-checked only when true, only the selected checkboxes will be announced as checked, while the others will not. ("Checkbox 1, checked. Checkbox 2, Checkbox 3).&lt;/p&gt;

&lt;p&gt;I wrote the "returnTrueElementOrUndefined" function to replace the alternative &lt;code&gt;"aria-hidden": isSilent ? true : undefined&lt;/code&gt; scenario, which requires testing for both situations everywhere it's used. By utilizing this function, I'm relieved of the requirement to test every component for undefined scenarios.&lt;/p&gt;

&lt;p&gt;You might be wondering why an aria-label is being used instead of using a &amp;lt;title /&amp;gt;. One reason is that the title isn't easily exposed in the icon library I'm using. Depending on how it's used, SVG titles are primarily used for tooltips on mobile devices, and that implementation is inconsistent. A more consistent approach is to use the aria-label attribute.&lt;/p&gt;

&lt;h3&gt;
  
  
  List and ListItem Components
&lt;/h3&gt;

&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/List" rel="noopener noreferrer"&gt;components/base/List folder&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The entire navigation component will consist of unordered lists, links and buttons. This example wraps the HTML elements required for lists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List AC 1 - Lists must be constructed using the appropriate semantic markup with either ul (default) or ol surrounding list items.&lt;/li&gt;
&lt;li&gt;List AC 2 - The list may be displayed horizontally or vertically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The HTML standard states that the only direct child element of either an unordered or ordered list is a list item (&amp;lt;li /&amp;gt;). Checking for this will be handled by jest/axe testing.&lt;/p&gt;

&lt;p&gt;The second acceptance criterion just makes it easier to render a list in either a vertical (default) or horizontal orientation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;List&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isOrdered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;orientation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vertical&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-orientation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-testid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isOrdered&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;listProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;listProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/List/List.tsx" rel="noopener noreferrer"&gt;List.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since lists may be ordered or unordered, the system returns the correct HTML element based on a boolean flag. Unordered lists are the default because they are used more frequently than their ordered counterparts. Lists can also be displayed horizontally or vertically, depending on a dataset prop.&lt;/p&gt;

&lt;p&gt;For those who have an awareness of aria, you might be wondering why I'm including a data-orientation and not an aria-orientation. It's because the aria-orientation property is only used in specific roles, and neither list nor listitem supports the role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ListItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;}){&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listItemProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-testid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;listItemProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/List/ListItem.tsx" rel="noopener noreferrer"&gt;ListItem.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ListItem component simply wraps the &amp;lt;li /&amp;gt; element. Providing a simple component remains beneficial, as properties, such as cx instead of className, can be standardized.&lt;/p&gt;

&lt;h3&gt;
  
  
  Button Component
&lt;/h3&gt;

&lt;p&gt;GitHub (release 0.2.1) -&lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Button" rel="noopener noreferrer"&gt;components/base/Button folder&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AC 1 - Every button shall have an accessible label&lt;/li&gt;
&lt;li&gt;AC 2 - Click, Space or Enter activates the button&lt;/li&gt;
&lt;li&gt;AC 3 - When disabled, aria-disabled should be set to true and the event handler should be dissociated from the button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every button must have a label, either as text in its children or via an aria-label, especially when the button surrounds an image. Buttons should be activatable with a pointer or the keyboard.&lt;/p&gt;

&lt;p&gt;The last acceptance criterion requires more explanation.&lt;/p&gt;

&lt;p&gt;HTML allows the disabled attribute to be applied to many interactive elements. Most browsers handle it in a way that causes issues in screen readers. When interactive elements are marked as disabled through the disabled attribute, screen readers will only acknowledge their presence in the elements list/rotor forms control panel. A disabled element is not present at all when tabbing through a page's focusable elements.&lt;/p&gt;

&lt;p&gt;This disparity creates a disconnect in perceivability between the screen and the screen reader. It forces a screen reader user to hunt for a disabled, focusable element in the elements list/rotor rather than navigating the DOM directly. This can be considered an equitable use failure, since a screen reader user would have to realize the button is missing and then jump back and forth between the element list/rotor and the page.&lt;/p&gt;

&lt;p&gt;When someone is navigating visually, they can still see that a button exists, even if it is disabled. The visual styling, inability to click, and cursor changes help solidify their understanding.&lt;/p&gt;

&lt;p&gt;A screen reader user who chooses to navigate a page or form using the tab key may have no idea the disabled control even exists. Instead, the button and its disabled state are only available through the elements list/rotor, and the user must know to check it.&lt;/p&gt;

&lt;p&gt;Why do we disable focusable components rather than removing them? The message sent to someone viewing a screen is that something may require their attention to enable it. Perhaps a submit button that only enables when every field in the form meets the requirements (which I do not recommend). How can a user dependent upon screen reader software determine how to enable a button if they are unaware of its existence?&lt;/p&gt;

&lt;p&gt;The solution to this issue is to reframe the disabled state by omitting the disabled attribute and event handler, and using the aria-disabled attribute instead. CSS can be styled based on the aria-disabled attribute, and the button will be available to both screen readers and the screen when a user navigates the DOM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isDisabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-disabled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;returnTrueElementOrUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;isDisabled&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-testid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;returnTrueElementOrUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isDisabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RACButton&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;buttonProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;RACButton&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Button/Button.tsx" rel="noopener noreferrer"&gt;Button.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When isDisabled is set to true, the "aria-disabled" attribute is set on the props, and onPress is removed.&lt;/p&gt;

&lt;p&gt;The onPress property combines keyboard, click and pointer handlers and is specific to the component library I'm using and also demonstrates another use of returnTrueElementOrUndefined: it returns the onPress event only when the button isn't disabled. The isDisabled prop is a valid prop to send to the &lt;a href="https://react-aria.adobe.com/Button" rel="noopener noreferrer"&gt;react-aria-component button&lt;/a&gt;, but since sending it triggers the disabled attribute on the button, it is never sent through.&lt;/p&gt;

&lt;p&gt;If you are using another component library for your button, you might need to send a single handler to each of the onClick, onKeyDown and onPointerDown events to achieve the same effect.&lt;/p&gt;

&lt;p&gt;Styling can be applied through the aria-disabled attribute in the stylesheet. Any focusable element should select state changes based on either the value of an aria or pseudo-classes. Additional data attributes may also be used if an appropriate pseudo-class or aria attribute isn't available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Link Component
&lt;/h3&gt;

&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Link" rel="noopener noreferrer"&gt;components/base/Link folder&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AC 1 - Links must be constructed using an &amp;lt;a /&amp;gt; element with a valid href.&lt;/li&gt;
&lt;li&gt;AC 2 - Links may only take a user to another location and may not be used for button-type functionality&lt;/li&gt;
&lt;li&gt;AC 3 - A link must have programmatically discernible text.&lt;/li&gt;
&lt;li&gt;AC 4 - The link should indicate if it will launch a new tab or window.&lt;/li&gt;
&lt;li&gt;AC 5 - All hrefs should be sanitized before being exposed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Link component wraps the link provided by Next/js, which itself extends the &amp;lt;a /&amp;gt; HTML component with a few router-based props.&lt;/p&gt;

&lt;p&gt;SEO emphasizes the use of links, not buttons, for navigation. Links and buttons have different semantic meanings and cannot be used interchangeably. A link's sole purpose is to navigate a user to another page, either to a section on the same page they are already on (an anchor) or to an entirely new page, either within or outside the current site. A button executes a process on the current page and, when activated, may or may not redirect the user to another page upon completion.&lt;/p&gt;

&lt;p&gt;When a link opens a new browser tab or window to load a new page, it should notify the user before the link is activated. Failure to do so, especially when a user relies on a screen reader, can leave them disoriented and unable to determine what has changed or even where they are relative to their last action. Typically, an icon with a label, or simply hidden text, should indicate that the link opens in a new browser tab or window before the user activates it.&lt;/p&gt;

&lt;p&gt;For security, every href should be sanitized to strip out any malicious code inserted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;newTabText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;opens in a new tab&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;openInNewTab&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;suppressNewIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getLinkTarget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getIsTargetSpecific&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getNewTab&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getSafeHref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nf"&gt;useLink&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;safeHref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getSafeHref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Link/Link.tsx" rel="noopener noreferrer"&gt;Link.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most cybersecurity attacks start with a simple link, so securing links within the component that renders them is important. If you're not sure whether your link component sanitizes the href it receives, find out; if it doesn't, add a check to your component.&lt;/p&gt;

&lt;p&gt;In this case, several utility functions are stored in the useLink hook, including getSafeHref.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useLink&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getSafeHref&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sanitizeUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Link/useLink.tsx#L44" rel="noopener noreferrer"&gt;useLink.tsx - getSafeHref() - Line 44&lt;/a&gt;&lt;br&gt;
If the href exists, then a third-party utility from &lt;a href="https://www.npmjs.com/package/@braintree/sanitize-url" rel="noopener noreferrer"&gt;braintree&lt;/a&gt; is used to remove any compromising content. It runs whenever an href is passed through.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkTarget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getLinkTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;openInNewTab&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isTargetSpecific&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getIsTargetSpecific&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Link/Link.tsx" rel="noopener noreferrer"&gt;Link.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Returning to the Link component, more calls are made to the hook, specifically regarding the criteria for opening in new browser tabs or windows and the required output.&lt;/p&gt;

&lt;p&gt;A named or standard target can be passed to the link component.  When a new browser tab or window is opened, any subsequent links to a named target will open in the same tab or window. Only when the target is not already available will a new tab open. Targets may include custom names or standardized &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#target" rel="noopener noreferrer"&gt;keywords&lt;/a&gt;, which are always prefaced with an underscore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getLinkTarget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;openInNewTab&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;openInNewTab&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_blank&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_self&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Link/useLink.tsx#L15" rel="noopener noreferrer"&gt;useLink.tsx - getLinkTarget() - Line 15&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A target is a separate entity from _blank, which requests a new browser tab, or _self, which loads the content into the active tab.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getIsTargetSpecific&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nonTargeted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_parent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_self&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_top&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nonTargeted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Link/useLink.tsx#L8" rel="noopener noreferrer"&gt;useLink.tsx - getIsTargetSpecific() - Line 8&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once a linkTarget is known, the system returns information to determine whether to open a new browser tab. Some standardized target types are not candidates, and they need to be accounted for.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...  &lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;willOpenInNewTab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;openInNewTab&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isTargetSpecific&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newTab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNewTab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newTabText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;suppressNewIcon&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-testid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;safeHref&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linkTarget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NextLink&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;linkProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;willOpenInNewTab&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;newTab&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NextLink&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Link/Link.tsx" rel="noopener noreferrer"&gt;Link.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A tab will open in a new window only if the functionality is explicitly requested via openInNewTab or when the target is deemed specific.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNewTab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;suppressNewIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="nx"&gt;newTabText&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iconProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;IconComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NewWindowIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newTabText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;suppressNewIcon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt; &lt;span class="na"&gt;isInline&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;isHidden&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newTabText&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Icon&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;iconProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Link/useLink.tsx#L25" rel="noopener noreferrer"&gt;useLink.tsx - getNewTab() - Line 25&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While it's preferable to display information on-screen when a link opens a new tab, an icon may not always fit the system design. In that case, hidden text is placed in the DOM instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Box Component
&lt;/h3&gt;

&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Box" rel="noopener noreferrer"&gt;components/base/Box folder&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While I don't call &amp;lt; Box /&amp;gt; in the navigation component, I thought it was worth going through because it's such a common use case and, like the Icon component, can help guide developers toward proper ARIA usage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AC 1 - If a role is not passed through on a div, then no aria may be present.&lt;/li&gt;
&lt;li&gt;AC 2 - If a role is passed through on a div, then a label or reference to a label must be present unless the role is "presentation" or "none".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Box can render as a &amp;lt; div /&amp;gt;, denoting a flow control or a &amp;lt; span /&amp;gt;, which is a phrase control. For the most part, both &amp;lt; div /&amp;gt; and &amp;lt; span /&amp;gt; are non-semantic elements, meaning they don't add anything to the conversation. They're useful for grouping and adding spacing between elements and denoting a custom widget with an explicit role.&lt;/p&gt;

&lt;p&gt;Every structural HTML element other than &amp;lt; div /&amp;gt; or &amp;lt; span /&amp;gt; contains an inherent role. Composite widgets start with a &amp;lt; div /&amp;gt; to which a role has been explicitly applied. Think of dialog boxes, progress bars, and switches. A Box component must support the implementation of a composite widget, including ARIA, while ensuring ARIA is not applied when a role is absent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isHidden&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;proceed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ariaLabelledby&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-labelledby&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ariaLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ariaRole&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-role&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;excludedRoles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AriaRole&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;presentation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// If the role or aria role doesn't exist or has no meaning, then no aria can be passed.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ariaRole&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ariaFound&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ariaFound&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dev Error: (Box) - Aria attributes may not be passed when no role is defined.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;proceed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ariaLabel&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ariaLabelledby&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;excludedRoles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;excludedRoles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ariaRole&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dev Error: (Box) - Must pass label, aria-label or aria-labelledby when a role is set.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;proceed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// check for singular label&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ariaLabel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ariaLabelledby&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ariaLabel&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ariaLabelledby&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dev Error: (Box) - Only one of  label, aria-label or aria-labelledby may be passed when a role is set.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;proceed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Box/Box.tsx" rel="noopener noreferrer"&gt;Box.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like the Icon component, the Box component only renders in development and test environments when conditions that can't be enforced solely through Typescript are met. The idea remains the same: educate developers on what makes good accessibility.&lt;/p&gt;

&lt;p&gt;Because aria attributes are not easily accessed through destructuring, and the component has no idea of what is being passed, the props component is passed through and destructured separately, while the system checks to see if any aria- prepended variables have been passed through.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;componentProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;classNames&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;srOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isHidden&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-testid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-labelledby&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-labelledby&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proceed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;componentProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;componentProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;divProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub (release 0.2.1) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.1/src/ui/components/base/Box/Box.tsx" rel="noopener noreferrer"&gt;Box.tsx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Labels can be passed in a few ways; one is through an exposed "label" prop, which generates an aria-label. An aria-label can still be passed through and used when the label is undefined. If another element is tagged as the label, the id of that element is passed via aria-labelledby. Only one of the three may be passed and used, so the earlier checks enforce that supposition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Base components can enhance and enforce security and accessibility. Code can be added to enable developers to provide accessibility easily and to prevent common antithetical choices.&lt;/p&gt;

</description>
      <category>react</category>
      <category>a11y</category>
      <category>code</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Spacing Considerations in Accessible Design</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Thu, 07 May 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/spacing-considerations-in-accessible-design-47ad</link>
      <guid>https://dev.to/shaynaproductions/spacing-considerations-in-accessible-design-47ad</guid>
      <description>&lt;p&gt;&lt;u&gt;&lt;em&gt;Prologue&lt;/em&gt;&lt;/u&gt; &lt;/p&gt;

&lt;p&gt;A while ago, I decided to develop a fully accessible main navigation component in React. &lt;/p&gt;

&lt;p&gt;While a preliminary set of requirements has been assembled for the component itself, design requirements still need to be considered. &lt;/p&gt;

&lt;p&gt;Most WCAG requirements regarding visual perceivability affect CSS and, by extension, design. If a design prototype in a system like Figma does not meet those visual requirements, it doesn't matter how clean the component code is; the visual aspect will not be accessible. This article considers design requirements, especially those related to WCAG success criterion &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#resize-text" rel="noopener noreferrer"&gt;1.4.4, Resizing Text&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;As I've &lt;a href="https://dev.to/shaynaproductions/who-is-actually-responsible-for-web-accessibility-hdj"&gt;mentioned before&lt;/a&gt;, development isn't the only engineering area where accessibility has to be considered. Whether it's a functional prototype in a tool such as Figma, or implementing the CSS from such a design, there are several success criteria from the Web Content Accessibility Guidelines that must be met, and so those criteria are pulled into the &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQCNi6MdPbGeQJCJPT4GkOwqASnjGOmQzRlm4uuF3pHsDhw?e=cv9Abu&amp;amp;nav=MTVfe0I2OTAxRDlELUJENDAtNEZFOC04OUZDLTQ0RUM1OUUzQTM5Qn0" rel="noopener noreferrer"&gt;requirements matrix&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unlike a developer who only needs to be &lt;a href="https://dev.to/shaynaproductions/the-modalities-of-accessibility-2hhe"&gt;aware of and develop&lt;/a&gt; the peripherals associated with perception (screen and screen reader) and operability (pointer and keyboard), team members responsible for the design and styling of a website, regardless of the tools they use, need to be conscious of both neurodiversity and &lt;a href="https://www.caorda.com/blog/web-sight-designing-for-the-visually-impaired/" rel="noopener noreferrer"&gt;variations of visual impairment&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adchitects.co/blog/design-for-neurodiversity" rel="noopener noreferrer"&gt;Neurodiversity requires care&lt;/a&gt; when designing the overall site and pages to reduce sensory overload, shorten blocks of text, and maintain high color contrast. Keeping layouts and navigation consistent also enables these users to navigate a website or page effectively.&lt;/p&gt;

&lt;p&gt;A user's vision may be corrected with visual aids, such as glasses, or other assistive technology, or it may not. Users may be able to identify the colors chosen, or they may not. Some users may experience difficulties with small text or low contrast and need support, particularly as they age. The Web Content Accessibility Guidelines (WCAG) requirements for vision are intended to support users who experience these issues. Other requirements, while still visual, are intended to support keyboard focus or to enable adequate targeting of interactive objects.&lt;/p&gt;

&lt;p&gt;I want to group the requirements around sizing, as detailed in the requirements matrix, and discuss them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Text should be able to be resized without assistive technology up to 200 percent without the loss of content or functionality. &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#resize-text" rel="noopener noreferrer"&gt;WCAG 1.4.4 Resize Text (A)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not every user can assimilate small text. Current recommendations are that most text on your page should have a font size of at least 16 pixels. Care should be taken to ensure not only that text can be enlarged, but also that, when a user enlarges a page, everything on it remains proportional regardless of the browser's font size.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure no loss of content or functionality occurs when text spacing properties are set to specific values—&lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#text-spacing" rel="noopener noreferrer"&gt;WCAG 1.4.12 Text Spacing (AA)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contrary to popular opinion, not every user will see your design the way you intended. Users can &lt;a href="https://www.makethingsaccessible.com/guides/using-a-portable-stylesheet-across-the-web/" rel="noopener noreferrer"&gt;create their own stylesheets&lt;/a&gt; and override your styles. These should be implementable without breaking your entire site. Text spacing properties include the CSS properties line-height, letter-spacing, and word-spacing, along with the margins between paragraphs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any keyboard operation should make a focus indicator visible. &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#focus-visible" rel="noopener noreferrer"&gt;WCAG 2.4.7 Focus Visible (AA)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When using a keyboard, the focus-visible pseudo-class is triggered as focus shifts to a focusable element, allowing a user to visually identify which element has focus. Styling should be applied, either globally or to a specific element, to help screen and keyboard users know where focus is on the screen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The size of the target for pointer inputs should be at least 24 x 24 pixels or should have padding around it to conform to a spacing of 24 x 24 pixels between it and any other pointer input—(WCAG 2.5.8 Target Size (Minimum) (A)](&lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#target-size-minimum" rel="noopener noreferrer"&gt;https://www.w3.org/WAI/WCAG22/quickref/#target-size-minimum&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;People don't have a fixed finger size. Small target areas are difficult for people with larger fingers or those with shaky hands, especially when targets overlap. Creating sufficient spacing between interactive elements ensures the intended target is actually triggered.&lt;/p&gt;

&lt;p&gt;Although it isn't specifically mentioned in the WCAG guidelines, there should also be visual indications when an element is hovered over. Focus is for keyboards, hover is for pointers. In many cases, focus and hover states should be similar, if not identical, after all, they convey the same message.&lt;/p&gt;

&lt;p&gt;All of these requirements can be implemented through a theming system. A well-designed theming system can automatically apply many of these accessibility features. Conversely, a poorly thought-out theming system can make styling harder to implement and break the accessibility of your screen display.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;repository&lt;/a&gt; I created for this series contains a slimmed-down version of the theming system I'm building. The theming system is built on standard CSS, defining colors and spacing and integrates with foundational components to support a default theme. &lt;/p&gt;

&lt;p&gt;Theming systems should integrate with browser settings to enable automatic adjustments aligned with specific accessibility features, such as dark mode or font customization, especially sizing.&lt;/p&gt;

&lt;p&gt;When using Zoom controls (Ctrl+/Ctrl-) to enlarge a page, every browser simply increases the pixel size. Actual font sizes are not affected. But what happens when the underlying font size itself changes?&lt;/p&gt;

&lt;p&gt;Every browser sets a font size, which can be defined as 1rem (root em). Every browser sets the default font size to 16px. Almost every corporate and government website uses a design that assumes the font size is set to 16 pixels.&lt;/p&gt;

&lt;p&gt;Why 16 pixels? As a geometric progression, the doubling of numbers: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 is a consistent progression within both computer hardware and software. Screens are designed to have pixel sizes evenly divisible by these numbers. The progression, though not a true Fibonacci sequence, is aesthetically pleasing and has become a de facto industry standard.&lt;/p&gt;

&lt;p&gt;When a user changes the default font size, the 1rem unit also scales. Instead of 1rem being equivalent to 16 pixels, 1rem can be returned as a different number of pixels, depending on the browser's font-size setting.&lt;/p&gt;

&lt;p&gt;Every browser has a setting to adjust the default font size. Chrome and Edge use a "small, medium, large" basic setting while also allowing more granular changes to font face and size.  Firefox lets you choose the default font size, while Safari only lets you restrict the smallest font size. Realistically, there's no way to determine how many pixels actually make up 1rem on a user's browser.&lt;/p&gt;

&lt;p&gt;I'm sure this realization comes as a surprise to many people, especially designers, and it can and does cause issues when a design or theming system doesn't account for a possible change in rem units.&lt;/p&gt;

&lt;p&gt;Change the font size while browsing your site and see how it fares:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chrome: Settings -&amp;gt; Appearance -&amp;gt; Font size&lt;/li&gt;
&lt;li&gt;FireFox: Settings -&amp;gt; Language and Appearance -&amp;gt; Fonts&lt;/li&gt;
&lt;li&gt;Edge: Settings -&amp;gt; Appearance -&amp;gt; Fonts -&amp;gt; Font Size&lt;/li&gt;
&lt;li&gt;Safari: Settings -&amp;gt; Advanced -&amp;gt; Never use font sizes smaller than [select size]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Sam's Club homepage is an example of what happens when the default font size changes and the application doesn't account for it. I increased the font size in Chrome to "very large," which set the rem value to 24px. The website mixes px and rem, which contributes to the issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F59gh56ntykd9qafc8k2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F59gh56ntykd9qafc8k2d.png" alt="Display of the Sam's Club home page in the default browser font size (16px)" width="800" height="480"&gt;&lt;/a&gt;&lt;br&gt;
[Screenshot of the Sam's Club home page using the default browser font size of 16px]&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow4x53fj3vjl9ef689a3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow4x53fj3vjl9ef689a3.png" alt="Display of the Sam's Club home page using a " width="800" height="479"&gt;&lt;/a&gt;&lt;br&gt;
[Screenshot of the Sam's Club home page with the browser font size set to "very large" (24px)]&lt;/p&gt;

&lt;p&gt;Notice the obvious changes in the header and the tags just below. Vertical spacing is no longer centered, and the dollar amount is obscured because it now sits on top of the bottom wheels, forming the cart icon.&lt;/p&gt;

&lt;p&gt;Suddenly, a design is being driven by incorrect pixel values. After all, 0.5rem off a 24 pixel base font is 12px, not 8, and .25rem is 6px, not 4. Carefully designed ratios and proportions can and will be thrown off.&lt;/p&gt;

&lt;p&gt;Having a user adjust the browser font size shouldn't disrupt your design, but when the system isn't designed for proportional scaling, the results are obvious and unprofessional.&lt;/p&gt;

&lt;p&gt;Take your own site for a spin, reset the browser font size and see what happens. I'll wait.&lt;/p&gt;

&lt;p&gt;Designing for user-defined font sizes is possible without sacrificing the base-16 design assumptions. Theming systems can accommodate this by standardizing the relative pixel value to 1/16 of a rem, regardless of the actual rem value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;--sizing-base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="py"&gt;--sp-px&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--sizing-base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.0625&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/blob/v0.2.1/src/theme-system/base/base.css" rel="noopener noreferrer"&gt;base.css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I use the —sp namespace to ensure no other variable can override my choice, and a relative px is 1/16th of the browser's font size. Everything, depending on placement — padding, font-size, width, or positioning — uses &lt;code&gt;calc(var(--sp-px) * #)&lt;/code&gt;, where # is the number of pixels. This guarantees that the ratio and proportions remain consistent regardless of the user's chosen font size.&lt;/p&gt;

&lt;p&gt;CSS cascade layers solve an issue with specificity by allowing themes to set layers of specificity and the order in which styles can be overridden. In this case, the system layer is near the bottom of the layers I've defined for my site, '@layer reset, system, default-theme, base-component, common-component, system-component, main;`; meaning it will be applied early in the process.&lt;/p&gt;

&lt;p&gt;The more thought and functionality the theming system receives, the easier it will be to implement accessibility across design and development for designers and developers. As an added bonus, appearance can be guaranteed to be consistent and usable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Before a clickable prototype can be created, base components must be created and updated, and their styles need to be tied to the theming system. The requirements for these components can be found in the &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQC-Dx1VN2b7Raew3h7PpGiSAagY51mt1-0oEayL_qfWIlQ?e=7lGKeR" rel="noopener noreferrer"&gt;accessibility requirements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'll be covering this in the next article.&lt;/p&gt;

</description>
      <category>design</category>
      <category>webdev</category>
      <category>a11y</category>
      <category>css</category>
    </item>
    <item>
      <title>Creating Initial Requirements for an Accessible Navigation Component</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Tue, 05 May 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/creating-initial-requirements-for-an-accessible-navigation-component-3gdg</link>
      <guid>https://dev.to/shaynaproductions/creating-initial-requirements-for-an-accessible-navigation-component-3gdg</guid>
      <description>&lt;p&gt;&lt;u&gt;&lt;em&gt;Prologue&lt;/em&gt;&lt;/u&gt; &lt;/p&gt;

&lt;p&gt;A while ago, I decided to develop a fully accessible main navigation component in React after a fruitless search through third-party component libraries, npm packages and even GitHub repositories. &lt;/p&gt;

&lt;p&gt;A complex component needs requirements around all aspects of the component, and this article begins the process of defining those requirements.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article is one of a series demonstrating building a React navigation component from scratch while considering accessibility through the process. This article addresses requirements gathering and architectural decisions to be considered before code is written.&lt;/p&gt;

&lt;p&gt;This article is fairly long, and so a set of content links is provided.&lt;/p&gt;




&lt;h2&gt;
  
  
  Content Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Wishlist&lt;/li&gt;
&lt;li&gt;
Gathering Requirements

&lt;ul&gt;
&lt;li&gt;APG&lt;/li&gt;
&lt;li&gt;Deque Accessibility Checklist&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Development Requirements

&lt;ul&gt;
&lt;li&gt;Requirements Discussion&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;HTML Structure&lt;/li&gt;

&lt;li&gt;Handling List Exposure&lt;/li&gt;

&lt;li&gt;Next Steps&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This article is the second in a series in which I walk through the steps I've taken to create an accessible navigation component with React. In my &lt;a href="https://dev.to/shaynaproductions/hunting-for-an-accessible-react-navigation-component-35h8"&gt;previous article&lt;/a&gt;, I covered the basic requirements for evaluating third-party components while seeking an accessible navigation component.&lt;/p&gt;

&lt;p&gt;When I didn't find any component that met even the minimal requirements, I decided to build my own, which means gathering even more requirements.&lt;/p&gt;

&lt;p&gt;Whether you call them acceptance criteria or requirements, it means the same thing—instructions detailing what is required for a ticket to be considered complete. Acceptance criteria are a contract between those who assign the tickets, those who code and those who test.&lt;/p&gt;

&lt;p&gt;I've seen very few tickets over the course of my career that offer detailed user stories. Many lack adequate acceptance criteria as well. And that might be well and good if developers and testers were fully conversant with accessibility and the requirements for any specific component.&lt;/p&gt;

&lt;p&gt;That isn't our reality, and depending on an LLM to add in accessibility basically sets you up for failure. Detailed requirements require detailed knowledge. If your business analysts lack the knowledge, depending on your developers to bring it probably won't help.&lt;/p&gt;

&lt;p&gt;I've seen more than my share of tickets where scrum masters have decided that marking "Must conform to WCAG" as the definition of done is adequate, with no further consideration of what that entails. Even worse is having that phrase show up as an acceptance criterion. What does a phrase like that mean for the development and testing of a specific component?&lt;/p&gt;

&lt;p&gt;I'm not saying that every requirement for a complex widget whose development will span across sprints needs to be in place before the first ticket is written. But the most important and consequential requirements, the ones that will drive how a component is architected, have to be there before the first ticket is scheduled and ready to be picked up.&lt;/p&gt;

&lt;p&gt;If I'm going to take the &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQCNi6MdPbGeQJCJPT4GkOwqASnjGOmQzRlm4uuF3pHsDhw?e=0igbTB&amp;amp;nav=MTVfezIzQTlDRUUzLTcxMkEtNEJGOS05RjkxLTcyOEEyN0E1RjVCRH0" rel="noopener noreferrer"&gt;requirements&lt;/a&gt; I used to analyze third-party packages and expand them to create a universally accessible component, I have to consider exactly what I want from the navigation component of my dreams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wishlist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The ability for the component to display as either controlled (opened and closed from another component) or uncontrolled, so that I can use the same component when rendering for desktop and mobile.&lt;/li&gt;
&lt;li&gt;The ability for the top row of the component to be displayed horizontally (desktop) or vertically (mobile).&lt;/li&gt;
&lt;li&gt;The ability to render a JavaScript object into a properly formed navigation component.&lt;/li&gt;
&lt;li&gt;The ability to render links and buttons, manage sublists within the same list, and support nesting down to at least two levels of navigation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Back to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Gathering Requirements
&lt;/h2&gt;

&lt;p&gt;Requirements for users of screen and pointer are fairly easy to come up with, and without specific acceptance criteria, would most likely be what is coded for a ticket with a user story of "As a user, I want to be able to access the main navigation and move to another page on the website."&lt;/p&gt;

&lt;p&gt;But I want more.  I want to be sure my navigation component is perceivable through both screen and screen reader and operable through pointers, keyboard and voice.&lt;/p&gt;

&lt;p&gt;Wearing my business analyst hat (🖊), the first question that comes to mind is: Where can I find the starting requirements for a main navigation component?&lt;/p&gt;

&lt;h3&gt;
  
  
  APG
&lt;/h3&gt;

&lt;p&gt;I'll start by returning to the disclosure navigation menu pattern available in the &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/" rel="noopener noreferrer"&gt;Aria Pattern Guide&lt;/a&gt;, also known as the APG.&lt;/p&gt;

&lt;p&gt;The APG isn't as consistent as I would like; requirements have to be extrapolated rather than being considered canon. Accessibility features and keyboard support especially need to be considered holistically, not as blueprints.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The main list is wrapped in a &amp;lt; nav / &amp;gt; element.&lt;/li&gt;
&lt;li&gt;Open dropdowns should close when Escape is pressed, or focus moves out of the navigation region.&lt;/li&gt;
&lt;li&gt;There should be a visual indicator of the show/hide state.&lt;/li&gt;
&lt;li&gt;Navigating through a horizontal navigation component should prevent the default page scroll behavior.&lt;/li&gt;
&lt;li&gt;Navigating with arrow keys does not replace tabbing through the buttons and links.&lt;/li&gt;
&lt;li&gt;Keyboard behavior

&lt;ul&gt;
&lt;li&gt;See &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/#kbd_label" rel="noopener noreferrer"&gt;Keyboard support&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Keyboard behavior, as written, is inconsistent and must be extrapolated. When the reference is from link to link or from button to button, it assumes the navigation must conform to the sample code displayed. Not every navigation will be this rigid; buttons opening sublists may, in fact, be somewhere within another sublist, not just on the top row. The requirement to change the current page when pressing the Enter Key or to display a visual indicator of the show/hide state is also a function of the example and not a specific requirement. However, it does highlight the need for a high-contrast theme (which is not included in this demonstration).&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/#rps_label" rel="noopener noreferrer"&gt;Role, Property, State and TabIndex&lt;/a&gt; section is specific to the aria attributes necessary.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;aria-controls - requires each button controlling a list to be linked to the list via an ID on the list.&lt;/li&gt;
&lt;li&gt;aria-expanded (true/false) indicates the state of the list's visibility on the button.&lt;/li&gt;
&lt;li&gt;aria-current (page) indicates a link associated with the current page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deque Accessibility Checklist
&lt;/h3&gt;

&lt;p&gt;There's another list to refer to: &lt;a href="https://dequeuniversity.com/checklists/web/" rel="noopener noreferrer"&gt;Deque's accessibility checklist&lt;/a&gt;. I find the PDF useful because some requirements are scattered across topics, and I can search it.&lt;/p&gt;

&lt;p&gt;The requirements I'm looking for are under &lt;a href="https://dequeuniversity.com/checklists/web/site-navigation" rel="noopener noreferrer"&gt;site navigation&lt;/a&gt;, where three topics are listed: Consistency, Multiple Ways and Navigation Lists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency&lt;/strong&gt; is achieved by developing a component that works in both desktop/laptop and mobile environments and delivers the same navigation across pages. The development of the component that can be activated in the header achieves this goal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiple Ways&lt;/strong&gt; requires that multiple ways to find other pages on the site be available. Developing a navigation component is one way.&lt;/p&gt;

&lt;p&gt;These aren't requirements for this component, though they are important at the site-wide level. The requirements I need are in the last topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Navigation Lists&lt;/strong&gt; have two basic requirements: Markup, which requires the navigation list to be contained within a &amp;lt;nav/&amp;gt; element; and a user must always have an indication of which page in the list is the page the user is currently viewing. The requirement specifies that indicators must be set up for both screen and screen reader users.&lt;/p&gt;

&lt;p&gt;Back to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Requirements
&lt;/h2&gt;

&lt;p&gt;Back when waterfall development was a thing, all requirements had to be gathered before any programming began. Agile, on the other hand, either crams requirements into a Confluence or SharePoint space, rarely acknowledges them on tickets, or skips detailing front-end requirements and relies on developers' expertise to build a component properly, usually based on a design document.&lt;/p&gt;

&lt;p&gt;Acceptance criteria are the requirements that direct developers to the outcomes required and provide a clear path for testing them. In my experience, across government agencies and private companies, it's been rare to see any acceptance criteria that spell out accessibility requirements beyond the vaguely worded "must meet WCAG 2.x".&lt;/p&gt;

&lt;p&gt;Why aren't accessibility requirements spelled out? My guess is that no criteria are given because it's rare for someone to understand accessibility and craft the specific requirements around it. It sets up a fail spiral, or at least creates a lot of hard-to-fix tech debt.&lt;/p&gt;

&lt;p&gt;If a component will be developed over a series of sprints, I don't think all specific requirements need to be finalized before the first ticket is assigned; however, all accessibility requirements for a particular ticket should be fully defined before work begins.&lt;/p&gt;

&lt;p&gt;Between the wishlist, evaluation requirements and the information I've extrapolated, I can begin assembling a list of requirements/acceptance criteria and specify which ticket each is associated with. Below is a list of headings indicating possible tickets to write, along with some of the requirements.&lt;/p&gt;

&lt;p&gt;You'll note that the earliest ticket, Structure and Transformation, has the most requirements, while subsequent tickets are less precise, and some have no requirements yet, only the knowledge that they will be necessary. That's Agile: the requirements/acceptance criteria only need to be in place before ticket grooming.&lt;/p&gt;

&lt;p&gt;A list of the &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQCNi6MdPbGeQJCJPT4GkOwqASnjGOmQzRlm4uuF3pHsDhw?e=VVE8fZ&amp;amp;nav=MTVfe0VGNTU2NjJDLUY2NkEtNDI3RC05RTQ2LTU1RDJDNDlDMzFFM30" rel="noopener noreferrer"&gt;initial development requirements&lt;/a&gt; may be found on the Requirements Matrix and are also given below.&lt;/p&gt;

&lt;p&gt;You may skip to the requirements discussion if you are viewing the matrix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure and Transformation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Navigation Component should be contained in a  landmark region.
The navigation should be presented as a nested unordered list within the &amp;lt; nav/&amp;gt; landmark region.&lt;/li&gt;
&lt;li&gt;Lists should present with a role of "list", list Items should present with a role of "listitem".&lt;/li&gt;
&lt;li&gt;The navigation component should be able to be presented as horizontal (desktop - default) or vertical (mobile presentation).&lt;/li&gt;
&lt;li&gt;When navigation is displayed as uncontrolled in a horizontal layout (the default behavior), the first row of focusable elements should display as open by default.&lt;/li&gt;
&lt;li&gt;Buttons are associated with a sublist and indicate if the sublist is open or closed.&lt;/li&gt;
&lt;li&gt;A visual indicator is used to represent the state of the sublist's expanded status.&lt;/li&gt;
&lt;li&gt;A sublist may be toggled to open or close when the button associated with it is pressed.&lt;/li&gt;
&lt;li&gt;The state of a list's visible or hidden state should be easily perceived by any user&lt;/li&gt;
&lt;li&gt;A link should inform users if it corresponds to the current page for both screen and screen readers.&lt;/li&gt;
&lt;li&gt;A JavaScript object containing a properly formed object should be able to be transformed into properly formed ListItems, Buttons and Subnavigation lists.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The structure and transformation requirements detail the main HTML structure and state changes when a sublist is closed or opened. After the requirements in this section are completed, a skeleton and pointer usable navigation component should be fully realized. Enough to be able to support concurrent design and styling work, and as a base for adding in all the rest of the requirements to enable full accessibility, including keyboard handling.&lt;/p&gt;

&lt;p&gt;Back to Content Links&lt;/p&gt;

&lt;h3&gt;
  
  
  Single List Keyboard Handling
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A Single List should implement Keyboard navigation with the following Keys: Home, End and the arrow keys.&lt;/li&gt;
&lt;li&gt;Within a single list, the arrow keys should shift focus to the next (right arrow) or previous (left arrow) focusable element within the current list.&lt;/li&gt;
&lt;li&gt;Within a single list, the Home key should shift focus to the first element on the current list.&lt;/li&gt;
&lt;li&gt;Within a single list, the End Key should shift focus to the last element on the current list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keyboard handling begins with handling focus for just a single list. Nothing more. &lt;/p&gt;

&lt;h3&gt;
  
  
  Data Handling Between Components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No requirements detailed yet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While not much is known yet, it's clear that finding list items within list components will require a link or button in a list to access information, not only within the elements in the list it resides in, but also in other nested lists associated with focusable elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboarding Between Components Up/Down
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Down Key should shift focus to the next element within a list and down between open sublists.&lt;/li&gt;
&lt;li&gt;The Up Key should shift focus to the previous element within a list and up between open sublists.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another keyboard ticket, this time for allowing focus to shift between list components, dependent on data handling. &lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboarding Between Components Tab/Shift+Tab
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Shift+Tab Key should shift focus to the previous element within a list and up between open sublists.&lt;/li&gt;
&lt;li&gt;The Tab Key should shift focus to the next element within a list and down between open sublists.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tab and Shift+Tab should always move the focus to the next item in the DOM. &lt;/p&gt;

&lt;p&gt;Back to Content Links&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Handling For Closings
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No requirements detailed yet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What happens when a list is closed? How does it handle other open lists? While not enough is known to begin creating requirements at this stage, it's possible some data will need to be passed between list items residing in different components. The requirements in the next section: Closings, Entries and Exits should help drive the requirements for data handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closings, Entries and Exits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Tab and Shift Tab Keys should allow exiting the component at both the first and last focusable elements.&lt;/li&gt;
&lt;li&gt;When Escape is pressed anywhere in an uncontrolled navigation component, all open sublists close and focus shifts to the topmost parent.&lt;/li&gt;
&lt;li&gt;When focus shifts outside the navigation component, all open sublists close.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A complete component allows for movement into and out of itself using the Tab Keys. Requirements are also necessary to determine what happens with any open sublists when a component is exited.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controlled Navigation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When the controlling element is activated, and the navigation component is closed, the navigation component should open and set focus on the first child in the first row.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rather than create two separate components for desktop and mobile, the goal is to combine them into a single component. There will be differences to handle when a button controls the navigation component and displays the top row vertically rather than horizontally. Any differences in display and keyboarding will need requirements moving forward.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements Discussion
&lt;/h3&gt;

&lt;p&gt;If it wasn't obvious before, this component won't be a simple one-sprint-and-done. It's going to take time, thought and resources. It's okay at this stage to know something needs to be done, even if you don't know the exact specifications. The component will need to manage data, but what the data is and how it should be managed still needs to be considered.&lt;/p&gt;

&lt;p&gt;Grouping requirements allows similar work to be handled in a single ticket and layers accessibility into development through progressive enhancement, which is how these articles and the code will be structured.&lt;/p&gt;

&lt;p&gt;Back to Content Links&lt;/p&gt;

&lt;p&gt;Speaking of structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML Structure
&lt;/h2&gt;

&lt;p&gt;When possible, a valid HTML structure should be decided upon before any code or design work is begun. Knowing what the rendered code should look like and working towards a skeleton component that provides the structure first means design and development can proceed concurrently, ensuring styling and operability can be easily integrated.&lt;/p&gt;

&lt;p&gt;When it comes to development, operability has to come first. It doesn't matter how much time and effort have gone into making something look good if the underlying structure supporting it makes it harder to operate or style. A developer should be tasked with making sure the component works correctly before being required to make it look a certain way.&lt;/p&gt;

&lt;p&gt;Conversely, those tasked with creating a design, especially if they're also familiar with CSS, can receive a skeleton component with basic functionality or just the HTML structure requirements for a Figma or other design system output, and ensure the design works with the structure.&lt;/p&gt;

&lt;p&gt;In this case, the structure output should resemble the HTML below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item One&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-two"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Two&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-three"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Three&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"subnav-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-four"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Four&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-five"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Five&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-six"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Six&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-seven"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Seven&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-eight"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item Eight&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agreed-upon HTML structure must be considered valid; this can be verified by running the code through an HTML validator. I use the &lt;a href="https://validator.w3.org/nu/" rel="noopener noreferrer"&gt;W3C Nu HTML Checker&lt;/a&gt;, which can test code from a URL or a file upload, as well as rendered code copied from a browser's dev tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8jc45ph7yj2cgbtvcyql.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8jc45ph7yj2cgbtvcyql.png" alt="A screen shot of the W3C HTML validator indicating the HTML structure is valid with no errors or warnings." width="800" height="483"&gt;&lt;/a&gt;&lt;br&gt;
Screenshot showing validated HTML structure&lt;/p&gt;

&lt;p&gt;Back to Content Links&lt;/p&gt;
&lt;h2&gt;
  
  
  Handling List Exposure
&lt;/h2&gt;

&lt;p&gt;Currently, the requirements specify opening and closing subnavigation lists but don't specify how to do so, leaving it to the developer assigned to the ticket.  How the list is rendered makes a big difference to accessibility, so the determination and acceptance criteria for how sublists are rendered should be written before the first ticket is in progress.&lt;/p&gt;

&lt;p&gt;There are three ways to disclose previously hidden subnavigation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose only to render the subnavigation when it is open &lt;code&gt;{open &amp;amp;&amp;amp; (&amp;lt;ul&amp;gt;…&amp;lt;/ul&amp;gt;}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Choose to hide closed navigation lists using &lt;code&gt;display: none&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Choose to hide the list from screen view, while still exposing it to screen readers using a screen reader-only class (.srOnly).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To adequately assess these choices, an informed understanding of how users interact with screen readers is necessary. Every screen reader provides multiple options for finding specific element types that are rendered on a page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to a specific landmark role or heading and then use the tab key to move through the page from that particular point.&lt;/li&gt;
&lt;li&gt; Pull up a list of similar structural elements and allow the user to move through the list regardless of where those elements are located on a page. This is called the elements list in NVDA and Jaws, while VoiceOver calls it a rotor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most disclosure patterns in React tend toward option 1: render the list only when it is visible. The second option, using &lt;code&gt;display: none&lt;/code&gt;, effectively hides the closed sublist from both screen and screen readers, and is the behavior demonstrated in the example shown for the &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation" rel="noopener noreferrer"&gt;APG Navigation Disclosure pattern&lt;/a&gt;. Neither option exposes the full list of navigation links within the elements list/rotor and forces screen reader users to navigate the list in the same way a screen user does, by navigating to sublists and finally finding the link they want.&lt;/p&gt;

&lt;p&gt;Within a screen reader, the elements list/rotor exposes all interactive and structural elements, such as landmarks and headings, available on a page when it loads or re-renders. This includes all the other links contained in the header and footer. Since screen reader users regularly use the elements list/rotor to navigate a site, is it equitable to only provide links if they are visible on the screen?&lt;/p&gt;

&lt;p&gt;Option 3 makes the full list of navigation links available in the elements list/rotor as soon as the page is fully loaded. I would argue that the main navigation links should be fully accessible to screen readers at all times, enabling a screen reader user to seamlessly discover their next navigation target regardless of how they choose to find it.&lt;/p&gt;

&lt;p&gt;A class that hides items from the screen while still keeping them available in the DOM should be globally available. The class is fairly common, and variations can be found through web searches. The one I use is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.srOnly&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="err"&gt;.srOnly&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this option adds some complexity for screen/keyboard users, so this architectural decision should be considered early in the process. A requirement detailing the decision has been added to the Structure and Transformation group.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sublists should be hidden from the screen, but available through the DOM when they are closed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Back to Content Links&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;I've created a repository, &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;accessible-react-navigation-demo&lt;/a&gt;, to store the code that will be built. It's built on Yarn 4.1.2, Next.js 16.x, and React 19.x, using TypeScript. The code will be released as progressive enhancements, building off the prior release and adding functionality and accessibility throughout. Each release will be linked to an article that provides links to the code for that release, along with examples.&lt;/p&gt;

&lt;p&gt;Why release this as a demonstration series rather than a third-party library ready for integration? I firmly believe that learning to work with accessibility is a process, and what better way to learn than to go through it?&lt;/p&gt;

&lt;p&gt;Besides, I'm using third-party base components and hooks as well as a simplified, still-rough version of the theming system I'm currently building for my website, which likely aren't in your libraries.&lt;/p&gt;

&lt;p&gt;The initial repository setup included everything necessary in package.json and configuration, and added code to implement testing using Jest and &lt;a href="https://testing-library.com/docs/react-testing-library/intro/" rel="noopener noreferrer"&gt;react-testing-library&lt;/a&gt;. I plan to aspire to 100% code coverage (with judicious use of &lt;a href="https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md" rel="noopener noreferrer"&gt;ignore commands&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Before a clickable prototype can be delivered, any components that render HTML elements must be imported and updated to verify they meet accessibility requirements and to make it easier for developers to add accessibility while coding. &lt;/p&gt;

&lt;p&gt;There's still more to get through before we begin coding the navigation component. I want to set this project up for success, and that means preliminary work must be in place before coding starts.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>softwaredevelopment</category>
      <category>analyst</category>
    </item>
    <item>
      <title>Hunting for an Accessible React Navigation Component</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Thu, 30 Apr 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/hunting-for-an-accessible-react-navigation-component-56mi</link>
      <guid>https://dev.to/shaynaproductions/hunting-for-an-accessible-react-navigation-component-56mi</guid>
      <description>&lt;p&gt;&lt;u&gt;&lt;em&gt;Prologue&lt;/em&gt;&lt;/u&gt; &lt;br&gt;
When I needed a main navigation component, I did what most developers do: I went looking for one. My requirements were simple: I wanted a navigation component that properly identified itself, that worked with both keyboard and mouse and was properly structured to support screen reader use. &lt;/p&gt;

&lt;p&gt;I didn't find one. &lt;/p&gt;

&lt;p&gt;So I ended up writing my own, and along the way, I thought it might be a good idea to document my progress to help educate others about what it takes to create an accessible complex widget. &lt;/p&gt;

&lt;p&gt;I wrote the component as a demonstration to expose the process of thinking about accessibility at every step. The code base (excluding the third-party libraries I've used) can be copied and pasted into your code base, with changes made where appropriate (using your own base components and hooks, as well as your own theming and design system). &lt;/p&gt;

&lt;p&gt;Through a series of releases and accompanying articles, I'll guide you through incorporating additional accessibility into your base components, then layering functionality and accessibility at every step until a fully accessible navigation component capable of displaying as a desktop or mobile menu is achieved. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo" rel="noopener noreferrer"&gt;repository code&lt;/a&gt; is fully typed and tested to 100% code coverage (with the help of a few Istanbul ignore comments). Each release is tied to one or more articles and contains multiple example pages with code examples that link to the appropriately tagged release on GitHub.&lt;/p&gt;

&lt;p&gt;Be warned, some of these articles are fairly long. This particular article marks the beginning of the process, focusing on what to look for when seeking a third-party component.&lt;/p&gt;




&lt;p&gt;What do you look for when tasked to find a complex third-party component? &lt;/p&gt;

&lt;p&gt;It's not uncommon for developers to hunt for existing components in third-party component libraries, the NPM library, or code in active repositories, then run examples and click around to confirm it meets the requirements for a particular need.&lt;/p&gt;

&lt;p&gt;The challenge, of course, is that accessibility needs to be considered, but what kind of standards can be applied during an evaluation? A full audit of a component using something like &lt;a href="https://accessibilityinsights.io/" rel="noopener noreferrer"&gt;Accessibility Insights&lt;/a&gt; might be useful, but only once a preliminary analysis indicates its potential.&lt;/p&gt;

&lt;p&gt;The success criteria of the &lt;a href="https://www.w3.org/WAI/WCAG22/quickref/" rel="noopener noreferrer"&gt;Web Content Accessibility Guidelines&lt;/a&gt;, also known as WCAG, serve as the ultimate arbiter but are deliberately written to encompass a wide range of technologies and, as I've mentioned before, are set as general guidelines rather than focusing on any one technology.&lt;/p&gt;

&lt;p&gt;Fortunately, there are two other resources I am aware of: the &lt;a href="https://www.w3.org/WAI/ARIA/apg/" rel="noopener noreferrer"&gt;ARIA Authoring Practices Guide&lt;/a&gt;, also known as the APG and the &lt;a href="https://media.dequeuniversity.com/en/docs/web-accessibility-checklist-wcag-2.2.pdf" rel="noopener noreferrer"&gt;Web Accessibility Checklist&lt;/a&gt; maintained by DeQue.&lt;/p&gt;

&lt;p&gt;The APG outlines best practices for labeling, keyboard navigation, and ARIA compliance in accessible components. However, its guidance is often based on simplified examples and should not be taken as the only way to achieve accessibility. The APG site is organized into patterns and practices, with most component information provided in patterns. &lt;/p&gt;

&lt;p&gt;Deque's Web Accessibility Checklist can be helpful by specifying techniques for specific component types and linking them to WCAG Success Criteria or Best Practices.&lt;/p&gt;

&lt;p&gt;I want to share how I went through the process when I needed a main navigation component while working on the revised version of the &lt;a href="https://nudgestories.com" rel="noopener noreferrer"&gt;nudgestories&lt;/a&gt; website.&lt;/p&gt;

&lt;p&gt;We often call a component like this a menu, and developers often adapt a menu component for this purpose. But is that really the right call? Are menus really usable for navigation? The first place I went to answer this question and gather requirements for evaluation was the APG, which lists an example of a &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/menubar/examples/menubar-navigation/" rel="noopener noreferrer"&gt;menubar navigation pattern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this case, a prominent caution box appeared on the page, with the following warning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficb4s1r3u63wkx7ytilk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficb4s1r3u63wkx7ytilk.png" alt="Warning from caution box: Read This First&amp;lt;br&amp;gt;
The code in this example is not intended for production environments. Before using it for any purpose, read this to understand why.&amp;lt;br&amp;gt;
About This Example&amp;lt;br&amp;gt;
Caution!&amp;lt;br&amp;gt;
Before considering the use of the Menubar Pattern for site navigation, it is important to understand:&amp;lt;br&amp;gt;
The menubar pattern requires complex functionality that is unnecessary for typical site navigation, which is styled to look like a menubar with expandable sections or flyouts. A pattern more suited for typical site navigation with expandable groups of links is the Disclosure Navigation Menu Pattern." width="769" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Warnings exist for a reason, and the requirements for this pattern make it clear that the menubar adds unnecessary complexity to the main navigation component. &lt;/p&gt;

&lt;p&gt;I then visited the recommended link for the &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/" rel="noopener noreferrer"&gt;Example Disclosure Navigation Menu&lt;/a&gt; and compiled a wish list of requirements to use in my evaluations.&lt;/p&gt;

&lt;p&gt;Each pattern in the APG identifies the roles, along with the aria attributes, notes keyboard support and accessibility features. Keyboard and accessibility support are tied to the relatively simple examples, and the actual requirements must be extrapolated rather than simply accepted.&lt;/p&gt;

&lt;p&gt;I identified my requirements using the concepts of &lt;a href="https://dev.to/shaynaproductions/the-modalities-of-accessibility-2hhe"&gt;Perceivability and Operability&lt;/a&gt; from WCAG, and mapped them to the corresponding success criteria, which can be &lt;a href="https://1drv.ms/x/c/0a06b27aad8039af/IQCNi6MdPbGeQJCJPT4GkOwqASnjGOmQzRlm4uuF3pHsDhw?e=VO9x7K&amp;amp;nav=MTVfezIzQTlDRUUzLTcxMkEtNEJGOS05RjkxLTcyOEEyN0E1RjVCRH0" rel="noopener noreferrer"&gt;viewed&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Perceivable&lt;/strong&gt; - The component should be perceivable to every person who encounters it.

&lt;ul&gt;
&lt;li&gt;The Navigation Component should be contained in a &amp;lt;nav /&amp;gt; landmark region. (&lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#identify-purpose" rel="noopener noreferrer"&gt;1.3.6 Identify Purpose&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt; Navigation should be presented as a nested structure of unordered lists.(&lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#info-and-relationships" rel="noopener noreferrer"&gt;1.3.1 Info and Relationships&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Lists should present with a role of "list" (inherent in an &amp;lt;ul /&amp;gt; element), items should present with a role of "listitem"  (inherent in a &amp;lt; li /&amp;gt; element). (1.3.6 Identify Purpose) &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The first three requirements explicitly specify the structural and semantic HTML elements required to develop the navigation component. If a component doesn't meet these foundational requirements, it's not worth my time looking any further. And while the component could be achieved with &amp;lt; div role="" /&amp;gt;, native components have inherent functionality that isn't usually available when a role is simply applied to a div.&lt;/p&gt;

&lt;p&gt;These three requirements are the easiest to look for and will allow me to identify any non-conforming components fairly easily. I'll just have to look at the rendered source code. If it meets these three requirements, I can continue the evaluation using additional requirements as listed below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Perceivable&lt;/strong&gt; - (continued)

&lt;ul&gt;
&lt;li&gt;Buttons are associated with a sublist and indicate if the sublist is open or closed. (1.3.1 Info and Relationships)&lt;/li&gt;
&lt;li&gt;Any user should easily perceive the state of a list's visible or hidden state. (&lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#name-role-value" rel="noopener noreferrer"&gt;4.1.2 Name, Role, Value&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A link must indicate it represents the current page through aria-current. (1.3.1 Info and Relationships / 4.1.2 Name, Role, Value) &lt;/li&gt;
&lt;li&gt;Buttons are associated with a sublist and indicate if the sublist is open or closed.  (1.3.1 Info and Relationships)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The remaining perceivable requirements mandate that any information available to a screen user should also be identifiable through a screen reader.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Operable&lt;/strong&gt; - The component should be operable to every person who encounters it.

&lt;ul&gt;
&lt;li&gt;A sublist may be toggled to open or close when the button associated with it is pressed. (1.3.1 Info and Relationships) &lt;/li&gt;
&lt;li&gt;Any open dropdown closes when the entire component loses focus.  (&lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#content-on-hover-or-focus" rel="noopener noreferrer"&gt;1.4.13 - Content on Hover or Focus&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The component should allow keyboard navigation through the following keys: Enter, Escape, Space, Tab, Home, End and the arrow keys. (&lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#keyboard" rel="noopener noreferrer"&gt;2.1.1 - Keyboard&lt;/a&gt;) (As extrapolated from &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/#kbd_label" rel="noopener noreferrer"&gt;APG Disclosure Navigation Keyboard Support&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The first two operable requirements don't specify how something is done; they only state that it must be done. But it's helpful to know that any interaction available through a pointing device should also be available when a keyboard is used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assessing Third-Party Components
&lt;/h2&gt;

&lt;p&gt;When assessing third-party components, it's always a good idea to evaluate the libraries already in use for your site before adding another. In this case, the third-party component library I'm using is Adobe's &lt;a href="https://react-aria.adobe.com/" rel="noopener noreferrer"&gt;react-aria-components&lt;/a&gt;, a primitives library containing unstyled UI components. &lt;/p&gt;

&lt;p&gt;While there's always room for improvement, Adobe pays close attention to accessibility requirements. I've worked with several styled-component libraries before, and I like the freedom from having to fight opinionated CSS. You can read the principles Adobe used to create this library on the &lt;a href="https://react-aria.adobe.com/quality" rel="noopener noreferrer"&gt;React Aria Quality&lt;/a&gt; page in their documentation.&lt;/p&gt;

&lt;p&gt;React Aria doesn't have a specifically named navigation component, but it does have a &lt;a href="https://react-aria.adobe.com/Menu" rel="noopener noreferrer"&gt;menu component&lt;/a&gt;. Since "menu" and "navigation" are often used interchangeably, I'll evaluate this before moving forward.&lt;/p&gt;

&lt;p&gt;The easiest way to begin the evaluation is to inspect the rendered HTML for an example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsnj5oxusxj6lpdzh7bj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsnj5oxusxj6lpdzh7bj.png" alt="A screenshot of the React-Aria component showing the dropdown menu of an ellipse button. The display shows options open, rename, duplicate, delete, share, show files and show folders. The Dev tools view on the right shows a series of divs, each holding roles of menuitem." width="800" height="545"&gt;&lt;/a&gt;&lt;br&gt;
Screenshot - React Aria Menu with Dev Tools open&lt;/p&gt;

&lt;p&gt;The example menu doesn't look promising on the screen as it shows items associated with an application rather than navigation. And a peek at the source confirms that it does not conform to the HTML structure required by my evaluation. The output lacks the &amp;lt; nav&amp;gt; role and does not expose nested lists; further, the menuitem role on each div does not match my requirements for a listitem role.&lt;/p&gt;

&lt;p&gt;When rejecting a component from a library already in use, there's bound to be pushback; someone in a standup meeting will point out that just because the example shows applications like menus, surely the code can be tweaked to display navigation. And why is it so important for the code to meet those unnecessary structural HTML requirements? After all, it does everything necessary, right?&lt;/p&gt;

&lt;p&gt;To explain why this component is not appropriate, there needs to be an understanding of the differences between the menu/menuitem and list/listitem roles. &lt;/p&gt;

&lt;p&gt;A menu pattern is typically used in desktop applications and their browser-based cousins (those with the role "application"). Think browser-based Google Sheets, or the online version of Microsoft Word or even Figma Design. Those require menus. A navigation component that only displays links and sublists that open when triggered by buttons doesn't need the complexity required of a menu. In fact, digging into the documentation further reveals much more complexity than is required for a navigation component; typeahead and multi-item selection are not indicated for one.&lt;/p&gt;

&lt;p&gt;Well, my third-party component library isn't going to give me what I need, so I searched npm and GitHub for anything I could fork and came up short. I remember thinking that somewhere there must be a navigation component that does what I want, so I checked out other third-party libraries.&lt;/p&gt;

&lt;p&gt;A library I use for common hooks, Mantine, also provides components, so I headed over to its site to take a look. &lt;/p&gt;

&lt;p&gt;Their website does show a &lt;a href="https://ui.mantine.dev/category/navbars/" rel="noopener noreferrer"&gt;navbar component&lt;/a&gt;. The screen example doesn't meet my needs, and the rendered HTML doesn't meet my requirements.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F800zf2n243funcu0s6am.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F800zf2n243funcu0s6am.png" alt="Screen shot of Mantine's navbar on Chrome with Devtools open" width="800" height="602"&gt;&lt;/a&gt;&lt;br&gt;
Screenshot of the Mantine Navbar example.&lt;/p&gt;

&lt;p&gt;Mantine actually does surround the code with a  &amp;lt; nav / &amp;gt; element, but the rest of once again examining the HTML shows me their component doesn't nest buttons or links in lists or list items. &lt;/p&gt;

&lt;p&gt;I began looking further afield, moving onto some of the better-known component libraries with a preference towards primitives:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mui.com/material-ui/react-menu/" rel="noopener noreferrer"&gt;&lt;strong&gt;Material-UI&lt;/strong&gt;&lt;/a&gt; has attempted and abandoned several projects to create a primitives library, which makes me wary of consuming its current primitives library, Base-UI. It also lacks a navigation component, but does include a menu component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmu0sm0qsbn3ubvlo4p3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmu0sm0qsbn3ubvlo4p3t.png" alt="Screenshot of Material UI Menu component on Chrome with DevTools open" width="800" height="527"&gt;&lt;/a&gt;&lt;br&gt;
Screenshot of Material UI Menu component example.&lt;/p&gt;

&lt;p&gt;Examining the HTML showed many of the same issues as the Adobe React Aria component. Lack of a &amp;lt; nav / &amp;gt; surrounding the code, and while it does use an unordered list and list items, the roles are specifically set to menu and menu-item.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://react-bootstrap.netlify.app/docs/components/navbar/" rel="noopener noreferrer"&gt;&lt;strong&gt;React Bootstrap&lt;/strong&gt;&lt;/a&gt; includes a navbar component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7n96ztxs3jxud75resh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7n96ztxs3jxud75resh.png" alt="Screenshot of React Bootstrap navbar on Chrome with Dev Tools open" width="800" height="453"&gt;&lt;/a&gt;&lt;br&gt;
Screenshot of React Bootstrap NavBar detailing the lack of proper HTML structure.&lt;/p&gt;

&lt;p&gt;The HTML structure is lacking: multiple links are wrapped in divs rather than being individually nested within list items in an unordered list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.radix-ui.com/primitives/docs/components/navigation-menu" rel="noopener noreferrer"&gt;&lt;strong&gt;Radix UI&lt;/strong&gt;&lt;/a&gt; shows some initial promise, but the rendered HTML still doesn't conform to my structured HTML requirements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3ta4joesi8aj4920fhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3ta4joesi8aj4920fhw.png" alt="Screen shot of Radix navigation menu on Chrome with Dev tools open" width="800" height="530"&gt;&lt;/a&gt;&lt;br&gt;
Screenshot of Radix navigation menu. &lt;/p&gt;

&lt;p&gt;Within the example, buttons are contained in an unordered list, which is contained in a nav element. But the failure comes when a button is activated, and the dropdown is not nested within the same list item as its parent button. &lt;/p&gt;

&lt;p&gt;No component library I reviewed provides a navigation component that meets the first three perceivability requirements. &lt;/p&gt;

&lt;p&gt;I have no choice but to create an accessible React navigation component that meets the criteria I've already identified. Are the requirements I've gathered enough? Probably not.&lt;/p&gt;

&lt;p&gt;Join me next time as I begin assembling the initial requirements for creating a universally accessible main navigation component.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>a11y</category>
    </item>
    <item>
      <title>The Modalities of Accessibility</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Wed, 29 Apr 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/the-modalities-of-accessibility-500m</link>
      <guid>https://dev.to/shaynaproductions/the-modalities-of-accessibility-500m</guid>
      <description>&lt;p&gt;There are nights when I have dreamt of a perfect world where, among other wishes, equitable access is a concern for everyone involved in developing a website. Unfortunately, the world I dream of is not the world we live in.&lt;/p&gt;

&lt;p&gt;I remember a contract where a graphic designer took it upon themselves to develop a help module in React since no team had the capacity to take it on. During peer review, I discovered issues with the module in screen readers and a keyboard trap. When I raised them, the designer flat-out refused to fix them, telling me during a meeting called to address the situation, "I don't care about blind people."  &lt;/p&gt;

&lt;p&gt;I was shocked but not surprised. In the world we live in today, caring about accessibility often only happens when someone personally knows someone affected by a specific disability. In Agile development, a world of sprints, tickets, and the pressure to "move fast and break things," teams tend to push out incomplete components designed to work along the "happy path" and, when confronted with the fact that their work isn't available to those with disabilities, offer to come up with the plan to fix accessibility later. &lt;/p&gt;

&lt;p&gt;The work of identifying specific disabilities and explaining how to address issues related to essential needs is often overlooked. The reality is that these issues rarely get resolved in a way that genuinely helps those who need it most. When accessibility is addressed at the end rather than built into the process from the start, the users who need it most end up suffering. &lt;/p&gt;

&lt;p&gt;Let's face it, as developers and designers, we love the new, shiny aspects of our craft, and many of us, it seems, aren't conversant with the foundational structures that support accessibility. Making sure our content is available to everyone seems to be a feature everyone is content to let languish in the backlog.&lt;/p&gt;

&lt;p&gt;Over the years, I've had the most success educating developers about accessibility when I've stopped leaning into guilt and compassion and focused on the nuts-and-bolts of what is necessary. And this means conceptualizing the Web Content Accessibility Guidelines differently.&lt;/p&gt;

&lt;p&gt;Commonly referred to as WCAG, the guidelines are an international standard adopted by many countries. Within the United States, it has been adopted under Section 508 of the Rehabilitation Act, which requires federal websites operated by the Executive Branch to be accessible, and Section 504 of the same act, which requires organizations receiving federal funding or assistance to ensure their websites are accessible.  This includes state agencies and publicly funded education systems, as well as public companies that receive federal financial assistance. Additionally, although not explicitly written into the law, U.S. courts have consistently upheld that websites run by private companies should also be subject to the same accessibility standards, through a variety of cases and appeals. &lt;/p&gt;

&lt;p&gt;The WCAG guidelines and success criteria are deliberately vague to remain relevant in a rapidly changing environment. The same standards apply whether the medium is a PDF, a page, or an application. The guidelines can be intimidating, and given their organization, they don't always make much sense to a developer who's been given a ticket that simply lists "must meet WCAG 2.x" as an acceptance criterion. Where to start? How to implement?  &lt;/p&gt;

&lt;p&gt;WCAG seems to be a dark hole into which developers and designers fear to fall. I want to propose another way of looking at the requirements through the lens of modalities and our physical abilities.&lt;/p&gt;

&lt;p&gt;The WCAG guidelines are grouped into four principles: Perceivable, Operable, Understandable, and Robust, collectively referred to as POUR. For the moment, I want to focus on the first two principles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perceivable
&lt;/h2&gt;

&lt;p&gt;All the information we receive comes through our physical senses. Of the senses available to us, three —vision, hearing and touch— are used to consume digital information. We read text, look at images and videos on a screen, and hear music and speech through speakers. We can even experience the digital world through touch: the vibrations of a game controller or the raised dots from a braille printer. While many of us have access to all three senses, some have access to only two, and still others to only one. &lt;/p&gt;

&lt;p&gt;The common denominator is that each of the three senses we use to perceive content on a computer is mediated by a peripheral device.  We use screens, external or wired in to view, speakers, separate or integrated to hear, and still other devices such as a game controller or braille printer to feel. &lt;/p&gt;

&lt;p&gt;So, perceivability can be achieved through peripherals, and to make content perceivable, we have to ensure it is available via a specific peripheral that accommodates one of the three senses. &lt;/p&gt;

&lt;p&gt;WCAG's first principle is Perceivability. All information and user interface components must be presentable to users in ways they can perceive. We can accomplish this by making sure all content is seen and heard. Audio content should include transcripts for screens; video content should include descriptions and captions, along with transcriptions for those who cannot hear. &lt;/p&gt;

&lt;p&gt;Screen readers are software programs that read the underlying content that ultimately displays on a screen. When coded structurally and semantically, the content on a screen can be perceived through different peripherals, such as audio from a speaker, or reduced to raised dots on a bar for reading through a braille printer. &lt;/p&gt;

&lt;p&gt;When considered through this filter, it becomes obvious that our code needs to target two peripherals: screens and screen readers. &lt;/p&gt;

&lt;p&gt;Most of the guidelines under the perceivability principle are mainly the responsibility of groups outside of front-end development.  Media accessibility, be it text alternatives, transcriptions, audio descriptions and captioning, typically would be the responsibility of content producers and creators. It's not a developer's responsibility to oversee those requirements; it's just to write code that makes them available.  &lt;/p&gt;

&lt;p&gt;How something is perceived on the screen, from theming, colors, layout and displays is in the purview of the design team. It's their responsibility to ensure that those with vision impairments can perceive the same information as those with perfect vision. &lt;/p&gt;

&lt;p&gt;Front-end developers do have some responsibility for perceivability. The underlying HTML, for example, should be semantic and well-structured. They are responsible for ensuring that metadata, such as state changes and relationships, is available to screen readers through HTML and ARIA attributes. &lt;/p&gt;

&lt;h2&gt;
  
  
  Operable
&lt;/h2&gt;

&lt;p&gt;Just as we use peripherals associated with our physical senses to perceive, we use other peripherals associated with movement to operate and interact. Sites can be interacted with through peripherals, such as a mouse or trackpad (known as pointers); we also interact through keyboards, and increasingly we use our voice. &lt;/p&gt;

&lt;p&gt;We can then specify that our sites must be operable via peripherals that support pointing devices, keyboards, and voice.&lt;/p&gt;

&lt;p&gt;Front-end developers bear the greatest responsibility for operability, though designers have some considerations as well, particularly regarding resizing, image flashing, headings and labels.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voice
&lt;/h3&gt;

&lt;p&gt;Using our voice to control how we interact with websites is becoming increasingly common. Windows 11 and Macs have built-in programs, and some browsers offer plugins and settings for voice interaction. Not everyone using their voice to control a site has a disability; situational and convenience also rank high. &lt;/p&gt;

&lt;p&gt;The most important aspect of operating a site via voice is ensuring that the words displayed on the screen are also programmatically associated with the component or element.  This means the visual label and programmatic name must include the same words. It doesn't mean the words need to be exact; the preference is to append any differences rather than prepend them. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.w3.org/WAI/WCAG22/quickref/#label-in-name" rel="noopener noreferrer"&gt;WCAG 2.5.3 Label in Name (A)&lt;/a&gt; requires that the visual label for a control be a trigger for speech activation.&lt;/p&gt;

&lt;p&gt;Consider the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;First Name: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"firstname /&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wrong (contrived, but still bad)&lt;/p&gt;

&lt;p&gt;In this case, the "First  Name" field has no association with the input, so any voice-operating user will become frustrated when they cannot trigger the input to fill out the form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"firstName&amp;gt;First Name&amp;lt;/label&amp;gt;&amp;lt;input name="&lt;/span&gt;&lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"firstName /&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better&lt;/p&gt;

&lt;p&gt;A user could enter their first name through their voice because the label is correctly hooked up to the input. &lt;/p&gt;

&lt;p&gt;Since labels and displayed text are outside a developer's control, the responsibility for ensuring the component name matches the displayed label lies with whoever is responsible for text enhancements. A developer's responsibilities here are mainly to notice when something doesn't meet the requirement and to request an enhancement from the responsible parties, whether the design team or the content owner.&lt;/p&gt;

&lt;p&gt;Any component where an aria label changes the wording shown must still include the visual wording for voice control to work, and whoever is responsible for the underlying wording and labeling must be aware of the issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pointers
&lt;/h2&gt;

&lt;p&gt;Pointers can include mice, trackpads, joysticks, and basically anything you can do with a finger or two or three. Many assistive technology devices mimic a simplified single-pointing device, usually a mouse event.&lt;/p&gt;

&lt;p&gt;When implementing handlers, it's important to understand that some devices require mouse events, while others require pointer events, and to ensure your handler works in all cases.  React supports a synthetic event handler onPointerDown that fires when a pointer is clicked on a tag or element. &lt;/p&gt;

&lt;h2&gt;
  
  
  Keyboard
&lt;/h2&gt;

&lt;p&gt;When it comes to keyboard usage, there are really two distinct sets of considerations. Screen readers on desktop computers require keyboard use, which presents different considerations than those for users who rely on a screen and keyboard for navigation. &lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboard with Screen Readers
&lt;/h3&gt;

&lt;p&gt;Every screen reader uses specific keyboard keys for all of its operations. There are keyboard commands that allow users to bring up lists of interactive elements, move through tables, skip to the next heading or link, and move through forms. &lt;/p&gt;

&lt;p&gt;Every screen reader uses different keys and key combinations for their users to navigate and interact with content, so care must be taken not to interfere with these keys when implementing your own. Reference guides for the most popular screen readers can be found at &lt;a href="https://dequeuniversity.com/screenreaders/" rel="noopener noreferrer"&gt;Deque University Screenreaders&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;For the most part, navigation outside the screen reader's key commands is handled by the Tab and Shift+Tab keys. Some screen readers limit the arrow keys to specific component types, such as select elements and radio groups, while others expose and allow their use in other custom components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboard with Screen
&lt;/h3&gt;

&lt;p&gt;With all the focus on accessibility for people who are blind, those who use a keyboard and screen combination can sometimes feel left out. Several assistive technologies mimic a keyboard, including on-screen keyboards activated by a switch, head and eye tracking, and sip-and-puff devices.&lt;/p&gt;

&lt;p&gt;Anyone using a screen should be able to navigate solely through the keyboard. Except for text inputs (single or multi-line), the most commonly used keys are Tab, Enter, Space, Escape and the arrow keys.&lt;/p&gt;

&lt;p&gt;Both screen/pointer and screenreader/keyboard users have a variety of ways of navigating to the content they are interested in. Screen-using keyboard users are the only users forced to navigate a web page linearly. They can benefit from bypassing common elements, such as header elements or long lists of interactive elements. &lt;/p&gt;

&lt;p&gt;When considering operability for these users, it's the interactive, focusable elements that deserve our attention.&lt;/p&gt;

&lt;p&gt;The basic interactive elements within HTML are &amp;lt;a  /&amp;gt;, &amp;lt; button /&amp;gt;, &amp;lt;input /&amp;gt;, &amp;lt;select /&amp;gt;, and &amp;lt; textarea /&amp;gt;. HTML elements are coded to be accessible and should be used rather than rolling your own.&lt;/p&gt;

&lt;p&gt;&amp;lt;div  role="button" onClick={handleClick &amp;gt;Click Me &amp;lt; /button &amp;gt; does not in fact equal &amp;lt;button onClick={handleClick}&amp;gt;Hello&amp;lt;/button&amp;gt; &lt;/p&gt;

&lt;p&gt;Without a tabIndex=0, the div cannot retain focus. None of the basic accessibility and functionality of a native button is present in a div that calls itself a button, which makes it even more frustrating for a user. A div with a role of button that only uses the onClick event will not respond when a user presses the Space or Enter keys. Each event type must be handled when creating your own custom component from divs.&lt;/p&gt;

&lt;p&gt;It is far better to use native HTML elements rather than cobbling together your own.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Understandable and Robust
&lt;/h2&gt;

&lt;p&gt;POUR's last two principles, Understandable and Robust, must be understood within the modalities of perceivability and operability. For instance, when allowing a user to switch to a different language, the lang attribute in the &amp;lt; html/&amp;gt; tag must be updated. A screen reader must know which language to use to speak with the language's natural inflections and pronunciation, rather than sounding like someone just learning the language. &lt;/p&gt;

&lt;p&gt;Similarly, if an error is identified and described to a user, it must be created in a way that is perceivable on the screen and through the screen reader. &lt;/p&gt;

&lt;p&gt;Consider tying accessibility to peripherals rather than to user disabilities. A ticket clearly defining acceptance criteria based on a peripheral is much clearer to a front-end developer than having them memorize which disabilities require which interactions. &lt;/p&gt;

&lt;p&gt;As professionals, it's our responsibility to ensure a website is fully perceivable on screen and with screen readers, and operable with pointing devices and keyboards. It shouldn't matter which devices a user chooses, or why they choose them, whether it's convenience or a disability. Our sites should just work.&lt;/p&gt;

&lt;p&gt;This article sets the stage for what comes next. Applying responsibility and the modalities of accessibility when building an accessible component. &lt;/p&gt;

&lt;p&gt;Join me as I start working on a universally accessible main navigation component for my site. I'll be building out a GitHub repository and discussing what it takes to build this component over a series I call "Guide to creating an accessible navigation component".&lt;/p&gt;

&lt;p&gt;Are you ready? Buckle up.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>wcag</category>
      <category>css</category>
    </item>
    <item>
      <title>Who is actually responsible for Web Accessibility?</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Tue, 28 Apr 2026 12:15:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/who-is-actually-responsible-for-web-accessibility-779</link>
      <guid>https://dev.to/shaynaproductions/who-is-actually-responsible-for-web-accessibility-779</guid>
      <description>&lt;p&gt;Who is responsible for making sure software is accessible? If your short answer is the front-end development team, I'm sorry to say that your software will never be universally accessible, because many accessibility decisions are made long before a developer begins working on a component. Architecture, design, and, yes, requirements all play a part in ensuring that whatever software is developed is perceivable and operable by people with differing characteristics. &lt;/p&gt;

&lt;p&gt;In all the agile teams I've been a part of, the process of creating a feature or component typically involves the project owner assessing needs, which (if deemed necessary) are then handed off to the software architect, and then to the data and design team/member(s), which (with or without front-end developer input) provide a visual design. Tickets are dispatched to different teams, and development commences.&lt;/p&gt;

&lt;p&gt;As a front-end developer, I am usually assigned stories with a design document or a Figma link, along with acceptance criteria. Rarely does any of this include accessibility information, and I haven't yet encountered someone well-versed in accessibility being included in the decisions made before tickets are written or handed off. &lt;/p&gt;

&lt;p&gt;Even if accessibility is considered before tickets are written, suggestions about it are usually met with swift and sometimes fierce pushback because the changes necessary to implement them affect a delivery date that was committed to without considering what it takes to create an accessible feature. When tickets mention accessibility in the acceptance criteria, it's typically a generic bullet point: "must meet WCAG 2.x." &lt;/p&gt;

&lt;p&gt;Front-end requirements tend to focus primarily on the physical sense of sight, with little input on how to make something perceivable to someone who lacks that sense. It's easier to demonstrate screen and mouse interactions during sprint demos and other agile ceremonies, since keyboard navigation doesn't translate well in either virtual or physical meetings, and screen reader demonstrations tend to be ineffective and leave stakeholders without a clear understanding of what has been achieved.&lt;/p&gt;

&lt;p&gt;True accessibility cannot be achieved if the first reference to it appears in a front-end development ticket. &lt;/p&gt;

&lt;p&gt;Trying to implement accessibility into a component when neither the design nor the back-end architecture has considered it will result in one of two outcomes: giving up after multiple test failures, or kludging the code to address impossible-to-fix issues aimed at passing an accessibility audit rather than helping actual users. A common example would be a requirement to describe user-uploaded images with an alt attribute when no database field is available to store the information. At best, a front-end developer can add generic alt text to pass an automated audit, but the actual requirement to describe an image so that someone who cannot see it has the same understanding as someone who can is never addressed.&lt;/p&gt;

&lt;p&gt;Requiring a developer to navigate between an inaccessible Figma design and the requirements to pass an accessibility audit places an undue burden on the party least able to rectify the situation.&lt;/p&gt;

&lt;p&gt;Implementing accessibility requires the knowledge and cooperation of everyone involved in the creation. From the project owners who define the business features to the back-end engineers who handle the data, as well as the designers, software architects, tech leads, content creators, developers, and testers. And while not everyone needs to be an expert in overall accessibility, they do need to know their responsibilities and gain expertise in those areas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real accessibility&lt;/strong&gt; requires those who assess the needs and gather the requirements to include requirements mapped to the appropriate WCAG success criteria when determining how a particular feature should be perceived and operated. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real accessibility&lt;/strong&gt;  requires the work of back-end engineers to ensure that dynamic images, charts, and graphs derived from database data also store and send the information necessary to describe those items. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real accessibility&lt;/strong&gt;  requires reasonable time limits and budgets to account for accessibility requirements when determining roadmaps. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real accessibility&lt;/strong&gt;  requires content owners to ensure that, if textual, the content they provide conforms to proper HTML semantic structure. If the content medium is audio/visual, it is accompanied by proper captioning, descriptions, transcriptions, and other related requirements for audio, images, and video.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real accessibility&lt;/strong&gt;  requires those writing tickets to write user stories and acceptance criteria in a way that both developers and testers can follow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real accessibility&lt;/strong&gt; requires those involved in design to truly understand the perceivable guidelines in the Web Content Accessibility Guidelines (WCAG) and apply them in their designs. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real accessibility&lt;/strong&gt; requires someone to be responsible for determining the phrasing of labels and text, including errors, descriptions, and headings that may or may not be visible on the screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real accessibility&lt;/strong&gt;  requires developers who understand the importance of accessibility and their role in ensuring components are semantically structured. They should be able to implement WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) properties and states correctly, and be responsible for supporting proper keyboard handling within complex components. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real accessibility&lt;/strong&gt; requires testers who know how to test across different accessibility scenarios, who can use a screen reader and the accessibility tree to ensure a user who lacks the physical sense of sight has an equitable experience as one who can see a screen.&lt;/p&gt;

&lt;p&gt;Real accessibility takes a company and community-wide effort. Whether it's a team-wide push or one person wearing all the hats, accessibility needs to be at the forefront of everyone's mind from the beginning of development to the very end.&lt;/p&gt;

&lt;p&gt;Right now, I'm like many of you, trying to survive the fallout happening in IT. I'm currently partnering with a friend on a website that hosts a constantly expanding universe of short stories. My friend is the content owner and has implemented their requirements, and I'm responsible for everything else. As the sole requirements gatherer/software architect/developer/designer/tester, it's my responsibility to ensure accessibility is considered at every step of the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hat Order
&lt;/h2&gt;

&lt;p&gt;Hat order is important. A tester's hat does me no good if there's nothing to test yet, and I can't develop a component until I know what I'm supposed to be building. So, really, the first hat I have to put on after deciding what I'm going to build is that of a product owner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Business Analyst/Requirements Gatherer 🖊
&lt;/h3&gt;

&lt;p&gt;Whether it's a standalone component or a feature, accessibility needs to be quantified. Requirements should be linked to Acceptance Criteria, and, ideally, those related to accessibility should also be linked to WCAG success criteria and best practices.&lt;br&gt;
Depending on company culture, requirements may be gathered in one place before any work begins, or gathered incrementally; however, all acceptance criteria for a particular user story should be in place a few sprints before design or development work begins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Architect 👷🏼
&lt;/h3&gt;

&lt;p&gt;A software architect is responsible for ensuring consistency throughout the website and for considering the architecture of a component and its relationship within the entire project. A software architect would be the first to review any requirements/acceptance criteria and add any necessary information. They would participate in design reviews to ensure the design itself is accessible and review pull requests for adherence to accessibility norms. &lt;/p&gt;

&lt;h3&gt;
  
  
  Content Creators/Producers 🎙️
&lt;/h3&gt;

&lt;p&gt;Content creators are responsible for ensuring that all audio, video, and textual content available through the website or application is accessible to everyone through proper semantic structure, captioning, audio description, and transcription. Proper labeling of interactive content is necessary to enable operability via voice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Designers 🎨
&lt;/h3&gt;

&lt;p&gt;Designers are responsible for what is shown on the screen. There is no amount of development in the world that can overcome an inaccessible design. The design team is responsible for the color contrast ratio between the foreground and background, and for state changes that occur when focus or hover actions interact with an interactive object. &lt;/p&gt;

&lt;p&gt;Depending on the team structure, they may or may not be responsible for the visual text labels and icon descriptions shown. If they are, they should also be responsible for labeling any text aimed toward screen readers. &lt;br&gt;
The design can be created in a prototyping environment such as Figma and sent back to the developer for application. If it is feasible and the CSS can be decoupled from the scripting code, designers could apply the CSS themselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend Engineers ⌨️
&lt;/h3&gt;

&lt;p&gt;Backend engineers are responsible for guaranteeing that the information necessary to describe an object whose data or location is stored in a database also includes fields to hold the descriptions. When raw data is used to generate a chart or other visually oriented component, textual descriptions based on the data are also generated and sent to the front end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend Developers 👩🏻‍💻
&lt;/h3&gt;

&lt;p&gt;A frontend developer implements the actual component or feature, using their knowledge of Semantic HTML structure and WAI-ARIA to create a semantically structured component that is operable across keyboard and touch peripherals.&lt;/p&gt;

&lt;p&gt;Developers are responsible for adhering to the acceptance criteria and ensuring the required WCAG guidelines are implemented. Developers should understand how browsers implement the accessibility tree and, ideally, test their code with screen readers and accessibility testing tools such as Accessibility Insights for Web.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testers 👩🏻‍💻
&lt;/h3&gt;

&lt;p&gt;Whether programmatic or human, a tester is responsible for making sure the tested item complies with the stated acceptance criteria. Screen readers and other accessibility testing tools, such as ZoomText or Accessibility Insights, may be used to test overall accessibility and specific acceptance criteria.&lt;/p&gt;

&lt;p&gt;When everyone is responsible for accessibility, the burden is shared. Not everyone needs to be an expert in everything that makes up accessibility, but each role needs to be an expert in their particular area.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessibility as a Layered Process
&lt;/h2&gt;

&lt;p&gt;While it's important to keep accessibility in mind from requirements gathering through testing, for the actual implementation, I've found it helps to build everything in layers over a series of sprints.&lt;/p&gt;

&lt;p&gt;Conversations over architecture, accessibility and design need to happen early in the process. Once a base structure is agreed upon, a front-end developer can create a clickable, semantically structured prototype that includes the basic requirements for screen reader perceivability and deliver it, along with minimal CSS, to the design team, who will work on screen perceivability. This prototype should be clear enough visually to help the developer implement the remaining features.&lt;/p&gt;

&lt;p&gt;When visual considerations take precedence, developers are more concerned with delivering something that matches the design than with how it operates. Minimal styling, even if it's ugly, helps developers focus on how the component operates, knowing the true design can be applied later in the process.&lt;/p&gt;

&lt;p&gt;Depending on the complexity of the component or feature, multiple tickets may be created, each with acceptance criteria mapped to the requirements, creating a contract between what a developer creates and what testing accomplishes. Toward the end of the process, the design can be implemented and tested against the WCAG perceivability and operable navigability guidelines.&lt;/p&gt;

&lt;p&gt;I'm going to demonstrate this process in a series of articles in which I implement a main navigation component that can be used for both desktop and mobile presentations. &lt;/p&gt;

&lt;p&gt;Are you ready to follow me on this journey?  Buckle Up.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
