<?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>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.0" rel="noopener noreferrer"&gt;release 0.2.0&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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) -&lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0) - &lt;a href="https://github.com/ShaynaProductions/accessible-react-navigation-demo/tree/v0.2.0/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.0/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>
    <item>
      <title>A Longer Introduction</title>
      <dc:creator>ShaynaProductions</dc:creator>
      <pubDate>Tue, 21 Apr 2026 12:10:00 +0000</pubDate>
      <link>https://dev.to/shaynaproductions/a-longer-introduction-4b6c</link>
      <guid>https://dev.to/shaynaproductions/a-longer-introduction-4b6c</guid>
      <description>&lt;p&gt;This introduction could perhaps be more aptly titled as "Who am I and why am I here?" While I posted a shorter intro in the introductory thread, I think it's easier to use my first article to give you some insight into myself and my motivations. &lt;/p&gt;

&lt;p&gt;My name is Sandra Clark, and through my company, Shayna Productions, I offer accessibility consulting services, including identifying, explaining, and resolving accessibility issues, as well as educating designers, developers, and testers on their accessibility responsibilities. My goal is to help teams work together to create actual accessible websites.&lt;/p&gt;

&lt;p&gt;I am also a front-end developer with a focus on React and TypeScript, and I strive to create truly accessible components and applications. That's been my focus throughout most of my career, first as a contractor developing dynamic applications for various local, state and federal government agencies as well as for small, medium, and large companies in the private sector. I've gone through it all, from working full-stack on solo and small-team projects to being one of many front-end developers on multiple teams working on larger projects. I've worked with both waterfall and agile methodologies, and I've experienced situations where each approach can be beneficial and where they fall short. &lt;/p&gt;

&lt;p&gt;My early years in programming were spent with the first web language to enable dynamic server-side sites, ColdFusion. It was groundbreaking in its time and was one of the few programming communities that were welcoming of women and actively recruited women speakers for its conferences. I was one, speaking at yearly conferences and to some user groups, focusing on accessibility and the foundations it's built upon—HTML, CSS and eventually WAI-ARIA. &lt;/p&gt;

&lt;p&gt;As fewer companies needed ColdFusion programming, I moved into front-end development, specifically with React, which reminded me of the first framework I used. React allows me to build larger components from smaller ones, and for the most part, makes it easy to add accessibility when the website/application architecture allows it, of course. &lt;/p&gt;

&lt;p&gt;I've been working in the React/TypeScript ecosystem for the past eight years. I appreciate structure and organization, and I'm comfortable with its paradigms, having wrapped my head around nested components in the first framework I ever used. &lt;/p&gt;

&lt;p&gt;I'll say straight out that I'm not a fan of AI, especially when it comes to crafting accessible solutions. There are no training materials that can push LLMs to have a visceral understanding of the human condition, nor is there any way for AI to have compassion; requirements when considering how to code something every human can perceive and interact with. While not every designer or developer exhibits these characteristics, the fact that we are all human means we have the capability, even when we don't have the desire, qualities that AI lacks.&lt;/p&gt;

&lt;p&gt;During my career, I've met a lot of people in the industry, and for the most part, whether they work as developers, designers, testers, program managers, scrum masters or even system architects, most of them are ignorant of accessibility and where the requirements for it lie in their area of expertise. &lt;/p&gt;

&lt;p&gt;Accessibility seems like a dark hole that few want to dive into. It's not that most people don't care about accessibility when building websites or apps. It's that they don't think about the fact that other people may use the web differently than they are used to, or they have no idea what the requirements are or how to implement them. The WCAG guidelines are deliberately vague, and well, there's always some new shiny tech that grabs people's attention instead of boring HTML and keyboard functionality. &lt;/p&gt;

&lt;p&gt;By the time a front-end developer is tasked with creating a new component, most of the architectural decisions that affect a site's accessibility have already been made. Those early decisions, whether it be routing to what comes from the back-end and even theming and design, have a huge impact on what a front-end developer can and can't do to create a truly accessible product. I've spent years working to improve a website whose original architects made decisions without considering accessibility, and even when I raised the specific issues, leadership was unwilling to change anything. &lt;/p&gt;

&lt;p&gt;Over the years, I've learned to serve as a translator between architecture, design, development, and accessibility.  And it's been necessary, especially when the only nod to accessibility is a ticket that serves as either a definition of done or acceptance criteria, which usually states something like "must meet WCAG 2.2".&lt;/p&gt;

&lt;p&gt;Almost every tech person on the teams I've been a part of has little to no idea what WCAG means, beyond asking, "This is about blind people, right?" Many people don't fully understand what it takes to implement accessibility in whatever app or component they're building. I've also found that very few testers I've encountered, other than those I've had the opportunity to mentor, have known how to test accessibility. &lt;/p&gt;

&lt;p&gt;"Must meet WCAG" places most of the responsibility for accessibility on developers and testers, without considering the other roles necessary to achieve it. Responsibility is placed without adequate training or guidance on how to meet the guidelines or determine whether they have been met. And even if the guidelines are met, many companies pay little to no attention to implementing accessibility in a meaningful, actually helpful way. &lt;/p&gt;

&lt;p&gt;I live and breathe accessibility; I've been tasked with interpreting audit results for management and developers, drafting remediation suggestions for tickets, and pair-programming with developers to explain the issue and how to fix it.&lt;/p&gt;

&lt;p&gt;I've been placed on special teams to find and fix accessibility issues right before major releases, a costly and unreachable goal. Especially when the requirement for the application to be accessible was part of the contract and known from the very beginning. &lt;/p&gt;

&lt;p&gt;And I've learned a few things along the way.&lt;/p&gt;

&lt;p&gt;Accessibility isn't achieved when a company pulls in every developer for a tech debt sprint and requires them to fix every vaguely worded accessibility-tagged ticket, only to ignore the issue once again until the next time tech debt is addressed. Tickets rerouted to the design team tend to stay in the backlog because it's "too hard" to actually fix the issues, for example, when it comes to a corporate primary color choice that will never meet contrast-ratio requirements. &lt;/p&gt;

&lt;p&gt;Accessibility is achieved when everyone involved in creating a component, page, or application treats it as a foundational core principle to be considered during every stage of the design and development process.&lt;/p&gt;

&lt;p&gt;Many of the decisions made early on, those that require concordance between the front and back end, need to keep accessibility in mind during the decision-making process. After all, allowing a user to upload an image without also providing the ability to store descriptive text actively impairs accessibility. Similarly, choices made by design, especially if they are at the forefront of the requirements a developer has to work with, may or may not improve accessibility, and non-visual perceivability may not even be considered.&lt;/p&gt;

&lt;p&gt;I'm currently between contracts, not under any NDA and heads deep in a collaboration with a friend on the second iteration of their website, &lt;a href="https://nudgestories.com" rel="noopener noreferrer"&gt;NudgeStories.com&lt;/a&gt;. The first version is a heavily customized WordPress site that pleases neither of us, but does gather the content for the second version: a headless WordPress back-end serving data to a React front-end. It's been a lot of fun settling back into being a full-stack developer as well as the architect and designer. &lt;/p&gt;

&lt;p&gt;I want to use this platform to explore what it means to create a truly accessible website, one available to as many people as possible, regardless of how they choose to consume the content, and share what I've learned over the years as I've emphasized accessible development. &lt;/p&gt;

&lt;p&gt;I'm currently working on a series on creating a universally accessible navigation component for React, and I hope the community finds it useful.&lt;/p&gt;

&lt;p&gt;I hope you follow me, and I look forward to interacting with you.&lt;/p&gt;

</description>
      <category>community</category>
      <category>webdev</category>
      <category>react</category>
      <category>a11y</category>
    </item>
  </channel>
</rss>
