Skip to content

API Reference ​

Core (a11y-hud) ​

mount(options?) ​

Mounts the <a11y-hud> Custom Element and returns an instance for runtime control. If a <a11y-hud> element already exists in the document, it is reused.

Importing a11y-hud is safe in non-browser environments (SSR, Node test runners): the Custom Element is registered only when customElements exists. Nothing touches the DOM until you call mount() in the browser.

ts
function mount(options?: MountOptions): A11yHudInstance

MountOptions

OptionTypeDefaultDescription
themeTheme"auto"Visual theme. "auto" respects prefers-color-scheme and promotes to "high-contrast" when prefers-contrast: more is set.
scopestring | Elementdocument.bodyCSS selector or Element to restrict axe scans to a subtree.
autoScanbooleantrueAttach a MutationObserver that rescans when the DOM changes.
debouncenumber500Milliseconds to debounce auto-scan triggers.
runOnlystring[][]Restrict axe to specific rule-set tags (e.g. ["wcag2a", "wcag2aa"]). Empty array runs all rules.

A11yHudInstance ​

Returned by mount(). Framework adapters return the closely related UseA11yHudReturn shape.

ts
interface A11yHudInstance {
  unmount(): void;
  setTheme(theme: Theme): void;
  setRunOnly(tags: string[]): void;
  runScan(): Promise<AxeResults>;
  exportResults(): string | null;
  ignores: {
    add(ruleId: string, selector?: string): void;
    remove(ruleId: string, selector?: string): void;
    clear(): void;
    list(): IgnoreEntry[];
    exportJson(): string;
    importJson(json: string): void;
  };
}
MethodDescription
unmount()Removes the <a11y-hud> element from the DOM.
setTheme(theme)Switches the active theme at runtime.
setRunOnly(tags)Changes which axe rule-set tags are active.
runScan()Triggers a manual scan and resolves with the axe results (ignored violations already filtered out). If a scan is already in flight, the same pending promise is returned instead of starting a new one. If axe.run throws, the panel shows a "Scan failed" state and the promise rejects with the original error.
exportResults()Returns the most recent scan as a JSON string (or null if no scan has run yet). Ignored violations are filtered before results are stored, so the export reflects the ignore list.
ignores.add(ruleId, selector?)Adds a rule (or rule + selector) to the ignore list and triggers a rescan. Persisted to localStorage.
ignores.remove(ruleId, selector?)Removes a specific ignore entry and triggers a rescan.
ignores.clear()Clears all ignores and triggers a rescan.
ignores.list()Returns the current IgnoreEntry[].
ignores.exportJson()Returns the ignore list as a JSON string.
ignores.importJson(json)Replaces the ignore list with the parsed JSON and triggers a rescan.

runScan(target?, runOnly?) ​

Runs an axe-core scan without rendering any UI. Concurrent calls are serialized — a second call waits for the first to finish. Violations matching the current ignore list are filtered out of the returned results. The promise rejects if axe.run fails.

This requires a real browser DOM (axe-core relies on layout and computed styles); it is not supported under Node/jsdom. For CI, run it inside a browser via Playwright — see the CI integration cookbook.

ts
function runScan(
  target?: Element,       // default: document.body
  runOnly?: string[]      // axe rule tags
): Promise<AxeResults>

generateBookmarklet(version?) ​

Returns a javascript: URL that loads the UMD bundle from jsDelivr and calls window.A11yHud.mount().

ts
function generateBookmarklet(version?: string): string
// version defaults to "latest"

Ignore-rules headless API ​

These functions read/write the same localStorage key (a11y-hud:ignores) as the HUD panel, so headless scripts and the UI share a single ignore list.

ts
import {
  addIgnore,
  removeIgnore,
  clearIgnores,
  listIgnores,
  exportIgnores,
  importIgnores,
} from "a11y-hud";

addIgnore(ruleId: string, selector?: string): void
removeIgnore(ruleId: string, selector?: string): void
clearIgnores(): void
listIgnores(): IgnoreEntry[]
exportIgnores(): string      // JSON string
importIgnores(json: string): void

Keyboard mode helpers ​

ts
import {
  getFocusableElements,
  injectFocusOrderOverlay,
  detectKeyboardViolations,
} from "a11y-hud";

getFocusableElements(scope)

Returns all focusable elements in scope, sorted by tab order (positive tabindex values first, then natural document order).

ts
function getFocusableElements(scope: Element): FocusableElementInfo[]

interface FocusableElementInfo {
  element: Element;
  index: number;       // 1-based tab position
  selector: string;    // generated CSS selector
  tabIndex: number;    // resolved tabIndex value
}

injectFocusOrderOverlay(elements)

Injects numbered badge overlays onto the page showing each element's tab position. Badges use page-relative absolute positioning so they remain stable during scroll. Returns a cleanup function that removes the overlay.

ts
function injectFocusOrderOverlay(elements: FocusableElementInfo[]): () => void

detectKeyboardViolations(elements, scope?)

Checks a focusable element list for common keyboard navigation issues. elements is the output of getFocusableElements. scope defaults to document.body and is used to find interactive elements excluded from the tab order via tabindex="-1".

ts
function detectKeyboardViolations(
  elements: FocusableElementInfo[],
  scope?: Element
): KeyboardViolation[]

interface KeyboardViolation {
  type: "positive-tabindex" | "interactive-excluded" | "no-focusable-elements";
  element?: Element;
  selector?: string;
  message: string;
}

Violation types:

  • positive-tabindex — element has tabindex > 0, which breaks natural tab order.
  • interactive-excluded — an interactive element has tabindex="-1", removing it from keyboard navigation.
  • no-focusable-elements — the scope contains no focusable elements at all.

A11yHudElement ​

The underlying Custom Element class. Exported for advanced use (e.g., type narrowing after querySelector).

ts
import { A11yHudElement } from "a11y-hud";

const el = document.querySelector("a11y-hud") as A11yHudElement;
el.setTheme("github-dark");
el.runScan();
MemberSignatureDescription
static observedAttributesstring[]["theme", "scope", "auto-scan", "debounce", "run-only"]
scopeElementElement | undefined (getter/setter)Programmatic scan scope. Setting it clears the scope attribute and re-targets the MutationObserver. Adapters use this to pass element references.
setTheme(theme)(theme: Theme) => voidSwitches theme and updates the theme attribute.
setRunOnly(tags)(tags: string[]) => voidUpdates active rule-set tags and the run-only attribute.
runScan()() => Promise<AxeResults>Same semantics as A11yHudInstance.runScan() — returns the in-flight promise if a scan is already running.
exportResults()() => string | nullLast scan as a JSON string.

Observed attributes

AttributeTypeDefaultDescription
themeTheme"auto"Visual theme
scopeCSS selector—Restricts scans to a subtree; an invalid selector falls back to document.body. Changing it at runtime re-targets the MutationObserver.
auto-scanpresencepresentRemove to disable the MutationObserver
debounceinteger (ms)500Auto-scan debounce; runtime changes take effect immediately
run-onlyJSON string[][]Active axe rule-set tags

Types ​

ts
type Theme =
  | "auto"
  | "default"
  | "light"
  | "high-contrast"
  | "github-dark"
  | "github-light"
  | "tokyo-night"
  | "solarized-dark";

type ResolvedTheme = Exclude<Theme, "auto">;

type Severity = "minor" | "moderate" | "serious" | "critical";

interface IgnoreEntry {
  ruleId: string;
  selector?: string;
}

interface A11yHudExport {
  version: "1";
  timestamp: string;     // ISO 8601
  url: string;           // window.location.href at scan time
  scope: string;         // selector or "document.body"
  results: AxeResults;   // raw axe-core results object
}

@a11y-hud/react ​

<A11yHud> ​

Mounts the HUD inside a React tree. Props are A11yHudProps, a type alias for UseA11yHudOptions.

tsx
import { A11yHud } from "@a11y-hud/react";

<A11yHud theme="auto" scope={ref} autoScan debounce={300} />

useA11yHud(options) ​

ts
function useA11yHud(options?: UseA11yHudOptions): UseA11yHudReturn

UseA11yHudOptions

ts
interface UseA11yHudOptions {
  theme?: Theme;
  scope?: RefObject<Element | null>;
  autoScan?: boolean;
  debounce?: number;
  runOnly?: string[];
}

@a11y-hud/vue ​

<A11yHud> ​

Props are A11yHudProps (alias for UseA11yHudOptions): theme, scope, autoScan, debounce, runOnly.

vue
<A11yHud theme="auto" :scope="templateRef" />

useA11yHud(options) ​

ts
function useA11yHud(options?: UseA11yHudOptions): UseA11yHudReturn

UseA11yHudOptions

ts
interface UseA11yHudOptions {
  theme?: Theme;
  scope?: Element | null;
  autoScan?: boolean;
  debounce?: number;
  runOnly?: string[];
}

Template refs

When using the component, pass a Vue template ref directly (:scope="myRef"). Vue templates auto-unwrap refs in attribute bindings, so the component receives the underlying Element | null.

When calling useA11yHud() directly, pass the element value or use a getter for reactivity:

ts
// Reactive getter pattern (recommended for composable usage with template refs)
const container = ref<HTMLElement | null>(null)
useA11yHud({ get scope() { return container.value } })

@a11y-hud/angular ​

A11yHudComponent ​

Selector: a11y-hud-angular. Standalone component. Inputs are theme, scope, autoScan, debounce, runOnly (A11yHudProps). The component provides its own A11yHudService, mounts the HUD in ngAfterViewInit, and rescans after every render commit via afterEveryRender.

html
<a11y-hud-angular [theme]="'auto'" [scope]="viewChildRef" />

The component also exposes the UseA11yHudReturn methods for use via @ViewChild:

ts
@ViewChild(A11yHudComponent) hud!: A11yHudComponent;

await this.hud.runScan();     // Promise<AxeResults | null>
this.hud.setTheme("tokyo-night");
this.hud.setRunOnly(["wcag2aa"]);
this.hud.exportResults();     // string | null
this.hud.ignores.add("color-contrast");

A11yHudService ​

Injectable service for imperative use without the component. It is declared with @Injectable() and no providedIn, so list it in a component's providers array (A11yHudComponent does this for you). Call init(options?) in ngOnInit / ngAfterViewInit; the service unmounts the HUD in ngOnDestroy.

ts
type ScopeInput = ElementRef<Element> | Element | null | undefined;

interface UseA11yHudOptions {
  theme?: Theme;
  scope?: ScopeInput;
  autoScan?: boolean;
  debounce?: number;
  runOnly?: string[];
}
MethodDescription
init(options?)Mounts the HUD with the given options. Call once.
initializedGetter — true once init() has run.
syncScope(scope)Updates the scan scope (ScopeInput) on the mounted element.
syncTheme(theme)Applies theme if it is defined.
syncAutoScan(autoScan)Adds or removes the auto-scan attribute.
syncDebounce(debounce)Updates the debounce attribute.
runScan()Runs a scan outside NgZone. Resolves null if init() has not been called.
setTheme / setRunOnly / exportResults / ignoresSame as UseA11yHudReturn.

@a11y-hud/svelte ​

<A11yHud> ​

Props are A11yHudProps (alias for UseA11yHudOptions): theme, scope, autoScan, debounce, runOnly.

svelte
<A11yHud theme="auto" scope={element} />

useA11yHud(getOptions) ​

Accepts a getter function — required for Svelte 5 $effect reactivity.

ts
function useA11yHud(getOptions: () => UseA11yHudOptions): UseA11yHudReturn

UseA11yHudOptions

ts
interface UseA11yHudOptions {
  theme?: Theme;
  scope?: Element | null;
  autoScan?: boolean;
  debounce?: number;
  runOnly?: string[];
}

@a11y-hud/solid ​

<A11yHud> ​

Props are A11yHudProps (alias for CreateA11yHudOptions): theme, scope, autoScan, debounce, runOnly.

tsx
<A11yHud theme="auto" scope={element} />

createA11yHud(options) ​

ts
function createA11yHud(options?: CreateA11yHudOptions): CreateA11yHudReturn

For reactive options, use getter properties so Solid's createEffect tracks them:

ts
const hud = createA11yHud({
  get theme() { return themeSignal(); },
});

CreateA11yHudOptions

ts
interface CreateA11yHudOptions {
  theme?: Theme;
  scope?: Element | null;
  autoScan?: boolean;
  debounce?: number;
  runOnly?: string[];
}

UseA11yHudReturn ​

All framework adapters (React, Vue, Angular, Svelte, Solid) return this shape from their hook / composable / service (Solid names it CreateA11yHudReturn):

ts
interface UseA11yHudReturn {
  runScan(): Promise<AxeResults | null>;
  setTheme(theme: Theme): void;
  setRunOnly(tags: string[]): void;
  exportResults(): string | null;
  ignores: {
    add(ruleId: string, selector?: string): void;
    remove(ruleId: string, selector?: string): void;
    clear(): void;
    list(): IgnoreEntry[];
    exportJson(): string;
    importJson(json: string): void;
  };
}

runScan() resolves null when the HUD has not mounted yet — for example, when called synchronously during the first render before the framework's mount hook has run. Once mounted it resolves with the same AxeResults as the core runScan().

Note: unmount() is intentionally omitted from adapters — the adapter lifecycle handles cleanup when the component unmounts.