<?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: Matjaž Korošec</title>
    <description>The latest articles on DEV Community by Matjaž Korošec (@makeup).</description>
    <link>https://dev.to/makeup</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1698641%2Fa5e3903d-15eb-40e4-aa41-3a69048f4b79.png</url>
      <title>DEV Community: Matjaž Korošec</title>
      <link>https://dev.to/makeup</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/makeup"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Matjaž Korošec</dc:creator>
      <pubDate>Fri, 30 Oct 2026 16:39:02 +0000</pubDate>
      <link>https://dev.to/makeup/-1gh5</link>
      <guid>https://dev.to/makeup/-1gh5</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/makeup/i-built-a-bookmarklet-that-shows-where-the-tab-key-goes-and-what-it-never-reaches-26o1" class="crayons-story__hidden-navigation-link"&gt;I built a bookmarklet that shows where the Tab key goes, and what it never reaches&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/makeup" class="crayons-avatar  crayons-avatar--l  "&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1698641%2Fa5e3903d-15eb-40e4-aa41-3a69048f4b79.png" alt="makeup profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/makeup" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Matjaž Korošec
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Matjaž Korošec
                
                
              
              &lt;div id="story-author-preview-content-4948485" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/makeup" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1698641%2Fa5e3903d-15eb-40e4-aa41-3a69048f4b79.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Matjaž Korošec&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/makeup/i-built-a-bookmarklet-that-shows-where-the-tab-key-goes-and-what-it-never-reaches-26o1" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 30&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/makeup/i-built-a-bookmarklet-that-shows-where-the-tab-key-goes-and-what-it-never-reaches-26o1" id="article-link-4948485"&gt;
          I built a bookmarklet that shows where the Tab key goes, and what it never reaches
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/a11y"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;a11y&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/testing"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;testing&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/makeup/i-built-a-bookmarklet-that-shows-where-the-tab-key-goes-and-what-it-never-reaches-26o1#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>I built a bookmarklet that shows where the Tab key goes, and what it never reaches</title>
      <dc:creator>Matjaž Korošec</dc:creator>
      <pubDate>Fri, 30 Oct 2026 16:15:10 +0000</pubDate>
      <link>https://dev.to/makeup/i-built-a-bookmarklet-that-shows-where-the-tab-key-goes-and-what-it-never-reaches-26o1</link>
      <guid>https://dev.to/makeup/i-built-a-bookmarklet-that-shows-where-the-tab-key-goes-and-what-it-never-reaches-26o1</guid>
      <description>&lt;p&gt;Run Lighthouse on any page and scroll to the bottom of the Accessibility section. There is a list called "Additional items to manually check". Two of them are about the keyboard: "Interactive controls are keyboard focusable" and "The page has a logical tab order".&lt;/p&gt;

&lt;p&gt;Manually. I wanted to check every page of my own site with the keyboard, so I built a tool for it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51o1j12rm2xnvb6gxe3u.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51o1j12rm2xnvb6gxe3u.gif" alt="Tab trail running on its own page. The panel counts 20 stops, 2 spots Tab skips and 1 menu that opens only on mouse hover, then the orange ring follows 5 Tab presses along numbered dots." width="600" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;Tab trail is a bookmarklet. Click it on any page and it draws a numbered dot on every Tab stop, joined by a line in the order the keyboard visits them. The stop you are on turns orange. Press Tab and follow the numbers, or press Play and it walks every stop for you.&lt;/p&gt;

&lt;p&gt;Then it marks in red what fails WCAG 2.2 AA.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://matjazkorosec.com/tools/tab-trail" rel="noopener noreferrer"&gt;Try it on the live page&lt;/a&gt;&lt;/strong&gt;. It has 3 things broken on purpose, so the first click shows red.&lt;/p&gt;

&lt;h2&gt;
  
  
  What turns red
&lt;/h2&gt;

&lt;p&gt;7 checks, each with its WCAG rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Missed spots&lt;/strong&gt; (2.1.1 A). Something looks clickable (a pointer cursor, a button role, an onclick) but Tab never gets there. The classic &lt;code&gt;&amp;lt;div onClick&amp;gt;&lt;/code&gt; "Add to cart".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hover menus&lt;/strong&gt; (2.1.1 A, 2.4.7 AA). A menu that opens on &lt;code&gt;:hover&lt;/code&gt; but never when Tab reaches it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forced order&lt;/strong&gt; (2.4.3 A). A &lt;code&gt;tabindex="5"&lt;/code&gt; that pulls an element ahead of the rest of the page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden focus&lt;/strong&gt; (2.4.11 AA). Tab lands on something a sticky header, cookie bar or chat button covers completely. This one is new in WCAG 2.2.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keyboard trap&lt;/strong&gt; (2.1.2 A). Tab and Shift+Tab both leave focus on the same spot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lost focus&lt;/strong&gt; (2.4.3 A). A popup closes and focus drops to the top of the page instead of going back to the button that opened it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Out of order&lt;/strong&gt; (2.4.3 A). Tab jumps somewhere it shouldn't, or a popup that blocks the page doesn't get Tab first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The parts that were harder than they look
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hover menus come from CSS, so it reads your CSS.&lt;/strong&gt; It goes through every style sheet it can read for &lt;code&gt;:hover&lt;/code&gt; rules that show something (display, visibility, opacity, max-height) that is hidden right now and holds a link or button. Then it looks for a &lt;code&gt;:focus&lt;/code&gt;, &lt;code&gt;:focus-within&lt;/code&gt; or &lt;code&gt;:focus-visible&lt;/code&gt; rule that shows the same element. No match and no &lt;code&gt;aria-expanded&lt;/code&gt; toggle means red. Nested CSS and Tailwind v4 output had to work too: &lt;code&gt;&amp;amp;&lt;/code&gt; rules resolved against their parent, &lt;code&gt;@media&lt;/code&gt; inside rules, &lt;code&gt;:hover&lt;/code&gt; inside &lt;code&gt;:is()&lt;/code&gt; and &lt;code&gt;:where()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hidden focus needs the page to stop moving.&lt;/strong&gt; After each Tab press it waits until scrolling is done, then tests 5 points on the focused element (the center and 4 corners). Only when all 5 land on something fixed or sticky is it flagged. Partly covered passes AA, so it is not red.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safari and Firefox on a Mac skip links on Tab by default.&lt;/strong&gt; Safari skips links and buttons until you turn on "Press Tab to highlight each item", Firefox skips links until you turn on Keyboard navigation in System Settings. A naive checker would flag every one of those presses as a jump. Tab trail marks them SKIPPED and tells you which setting to flip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It has to survive any site.&lt;/strong&gt; It draws inside its own shadow root, so the page's CSS can't touch it. It runs under a strict Content Security Policy and Trusted Types. When the page opens a modal &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;, everything outside it goes inert, so the tool moves itself into the dialog to stay clickable and moves back out when it closes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Firefox can't store it.&lt;/strong&gt; A bookmark there can be at most 65,536 characters, and Tab trail is 223,286. In Firefox you paste the script in the console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hand it to your AI
&lt;/h2&gt;

&lt;p&gt;"Copy for AI" copies only the problems, each with its WCAG rule, what should happen, a unique CSS selector, a trimmed HTML snippet, the React, Vue or Angular component that drew it (on a dev build), a fix hint and how to check the fix. Paste it into your coding agent and it knows where to look.&lt;/p&gt;

&lt;p&gt;Long numbers, emails and things that look like tokens are masked before they reach your clipboard. Read it once anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put it in your tests
&lt;/h2&gt;

&lt;p&gt;While it is open, the page has &lt;code&gt;window.__tabTrail&lt;/code&gt;, so a test can run it with no clicks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt; tab-trail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readFileSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@playwright/test&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;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node_modules/tab-trail/dist/tab-trail.js&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;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tab reaches everything&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="nx"&gt;page&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;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5173/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__tabTrail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&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;problems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__tabTrail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;check&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&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;code&gt;play()&lt;/code&gt; moves focus through every stop, so it covers Missed spots, Hover menus, Forced order and Hidden focus. Out of order and Keyboard trap need real Tab and Shift+Tab presses, and &lt;code&gt;state().untested&lt;/code&gt; tells you which checks never ran, so a green test can tell a clean page from a skipped check. The full example, with the TypeScript types, is in the &lt;a href="https://github.com/matjazkorosec/tab-trail#playwright-example" rel="noopener noreferrer"&gt;README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Already run axe? Keep it. axe reads the HTML, Tab trail walks the Tab key.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it doesn't do
&lt;/h2&gt;

&lt;p&gt;It's the keyboard part, not a full audit. It checks that Tab gets there, not that Enter or Space then works. It doesn't compare Tab order with the visual order when CSS moves things around, doesn't judge your focus ring's contrast, and doesn't tell you what a screen reader says. Style sheets from other domains without CORS can't be read. The whole list is in &lt;a href="https://github.com/matjazkorosec/tab-trail/blob/main/docs/limits.md" rel="noopener noreferrer"&gt;docs/limits.md&lt;/a&gt;, and how it sits next to Accessibility Insights, WAVE and the rest is in &lt;a href="https://github.com/matjazkorosec/tab-trail/blob/main/docs/compared.md" rel="noopener noreferrer"&gt;docs/compared.md&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It reads the page and sends nothing: no network requests, no cookies, no storage. Close it and it's gone.&lt;/p&gt;
&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/matjazkorosec" rel="noopener noreferrer"&gt;
        matjazkorosec
      &lt;/a&gt; / &lt;a href="https://github.com/matjazkorosec/tab-trail" rel="noopener noreferrer"&gt;
        tab-trail
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Tab order and focus order checker. A bookmarklet that draws every Tab stop and marks what Tab never reaches. WCAG 2.2 AA check helper.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/matjazkorosec/tab-trail/.github/assets/trail.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmatjazkorosec%2Ftab-trail%2FHEAD%2F.github%2Fassets%2Ftrail.gif" width="960" alt="Tab trail running on its own page, matjazkorosec.com/tools/tab-trail. The panel opens and counts 20 stops for the Tab key, 2 spots that look clickable but Tab skips (Add to cart, Send) and 1 menu that opens only on mouse hover. Then the orange ring follows 5 Tab presses along numbered dots joined by lines."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Tab trail&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;One click shows the path the Tab key takes through any page, and marks in red what fails WCAG 2.2 AA.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/tab-trail" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/471c2e576212337c7127af2efbb31415ff702f8d64c02021506b5536866e1017/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f7461622d747261696c" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://github.com/matjazkorosec/tab-trail/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/matjazkorosec/tab-trail/actions/workflows/ci.yml/badge.svg" alt="CI"&gt;&lt;/a&gt;
&lt;a href="https://github.com/matjazkorosec/tab-trail/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b8cadaa967891081f8f165695470689986c028821dd8a040132f6e661795dc0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c7565" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some people only use the keyboard. If Tab skips your "Add to cart" button, they can't buy from you. If it skips "Send" on your contact form, they can't write to you. Even Lighthouse tells you to check this by hand. Tab trail checks it for you.&lt;/p&gt;
&lt;p&gt;I built it to check every page of my own site with the keyboard. &lt;strong&gt;&lt;a href="https://matjazkorosec.com/tools/tab-trail" rel="nofollow noopener noreferrer"&gt;Try it on the live page&lt;/a&gt;&lt;/strong&gt;, it has 3 things broken on purpose.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Bookmark&lt;/h3&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;a href="https://matjazkorosec.com/tools/tab-trail" rel="nofollow noopener noreferrer"&gt;matjazkorosec.com/tools/tab-trail&lt;/a&gt; and drag the Tab trail button to your bookmarks bar. Don't see the bookmarks bar? Press Ctrl+Shift+B, or Cmd+Shift+B on a Mac.&lt;/li&gt;
&lt;li&gt;Open your site and click the bookmark.&lt;/li&gt;
&lt;li&gt;Press Tab and follow the numbers, or press Play and it walks every stop for you. Click the bookmark…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/matjazkorosec/tab-trail" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;1 file of plain JavaScript, MIT licensed. Drag the button from &lt;a href="https://matjazkorosec.com/tools/tab-trail" rel="noopener noreferrer"&gt;the page&lt;/a&gt; to your bookmarks bar, click it on your own site, and press Play.&lt;/p&gt;

&lt;p&gt;If it gets something wrong on your site, press Copy log in the panel and open an issue with it. I'd like to see the pages that break it.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
