Out of Order

GitHub
Getting started

From install to overlay in a minute

Install one package, call one function. This page walks the three ways to run Out of Order: the trace() overlay on your own page, audit() in a test or CI, and the CLI against any URL. What the rules catch, and how to re-grade or disable one, is on the rules page.

See it before you install

The playground is every focus and keyboard bug the analyzer catches, each one wired to break then get fixed live, with the overlay tracing the real tab path.

See it: @out-of-order/trace

The framework-agnostic overlay. Import it and call trace(), and you have numbered tab stops, the path between them, and every finding ringed in place.

import { trace } from "@out-of-order/trace";

const overlay = trace();

// Later, tear it down. This removes the layer, observers, and listeners.
overlay.destroy();

The overlay re-analyzes itself on every DOM mutation, so most pages need nothing beyond the mount. You can scope it to a subtree, hide and show it, or feed it rule overrides through trace(options). See the trace API.

Check it: @out-of-order/core

The analyzer on its own, no overlay. It gives you the verdict as plain data, which is what you assert in a test or CI, or feed into your own UI. Its own install, with no framework or test-runner deps.

import { audit, formatViolations } from "@out-of-order/core";

const result = audit();

result.valid; // boolean, true when there are no error-severity violations
result.sequence; // elements in tab order, each with tabIndex + rect
result.violations; // one entry per element: { element, selector, orderIndex, issues }

if (!result.valid) {
  // formatViolations renders a ready-to-print string from the structured result.
  console.log(formatViolations(result, "text"));
}

valid only goes false on an error. Warnings are advisory and never flip it, so they will not fail a build gate unless you promote them. See the core API for every field.

Scan it: @out-of-order/cli

The same audit against any URL, without touching the page's code. It launches headless Chromium, runs the analyzer on the live page, and prints the findings, with an exit code that fails on errors so it can gate CI. Use it on a deployed site, a staging URL, or someone else's page.

npx playwright install chromium # once per machine

npx @out-of-order/cli https://example.com                  # prints findings, fails on errors
npx @out-of-order/cli https://example.com --format json    # the full result as JSON
npx @out-of-order/cli https://example.com --wait "[role=dialog]" # let a JS-heavy page settle
npx @out-of-order/cli https://example.com --overlay        # opens a browser with the overlay

For a page behind a login, run npx @out-of-order/cli login <url> once and sign in by hand. The session is saved, and every later audit of that host picks it up. The full option list is in the CLI README.