npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@afixt/apg-react

v1.2.0

Published

Accessible React components implementing every pattern in the WAI-ARIA Authoring Practices Guide (APG)

Downloads

384

Readme

apg-react

license: MIT npm Storybook

Accessible React components implementing every pattern in the W3C ARIA Authoring Practices Guide (APG).

Each component ships with the full APG keyboard-interaction model, correct ARIA roles and state, focus management, and a Bootstrap-flavored visual default you can restyle via CSS custom properties. Written in TypeScript with full type declarations. All user-facing strings are translatable via an optional labels prop.

Why

Most component libraries treat accessibility as a checklist. This library treats the APG as the specification. Every component is tested against the APG's keyboard model, ARIA contract, and focus-management requirements — with 295 unit tests, 37 dedicated accessibility-contract tests, and E2E tests driving a real browser. Every assertion is implemented from first principles against the DOM.

Install

npm install @afixt/apg-react

Peer dependencies:

  • react ≥ 18
  • react-dom ≥ 18
  • react-router-dom ≥ 6 (optional — only required if you use <Link> or <Breadcrumb>)

Quick start

import { Button, Accordion, ModalDialog } from '@afixt/apg-react';
import '@afixt/@afixt/apg-react/styles.css';         // full baseline styles
// or, to cherry-pick tokens only:
// import '@afixt/@afixt/apg-react/variables.css';

function App() {
  return (
    <Button label="Save" action={() => save()} />
  );
}

Components are tree-shakeable; only what you import will land in your bundle.

Components

Components are organized by the APG pattern they implement. Follow each link for the official APG documentation.

Widgets

| Component | APG pattern | | --- | --- | | Accordion | Accordion | | Alert | Alert | | AlertDialog | Alert Dialog | | Breadcrumb | Breadcrumb | | Button | Button | | Carousel | Carousel | | Checkbox | Checkbox (dual & tri-state) | | CheckboxGroup | Checkbox — parent/child mixed state | | Combobox | Combobox — supports none, list, both | | Disclosure | Disclosure | | Feed | Feed | | Grid | Grid | | Link | Link pattern (requires react-router-dom) | | Listbox | Listbox — single & multi-select | | MenuButton | Menu Button | | Menubar | Menu / Menubar | | Meter | role=meter | | ModalDialog | Dialog (Modal) | | Progressbar | role=progressbar | | RadioGroup | Radio Group | | Slider | Slider | | SliderMultiThumb | Slider (Multi-Thumb) | | Spinbutton | Spinbutton | | Switch | Switch | | Tabs | Tabs — automatic or manual activation, horizontal or vertical | | Textbox | role=textbox — single- and multi-line | | Toolbar | Toolbar | | Tooltip | Tooltip | | TreeGrid | Tree Grid | | TreeView | Tree View |

Structural

| Component | Purpose | | --- | --- | | Article | Semantic <article> with heading + posinset/setsize for use inside Feed. |

Keyboard reference

Every component implements the full keyboard model specified by its APG pattern. Highlights:

  • Roving tabindex where the pattern calls for it: RadioGroup, Toolbar, Tabs, Grid, TreeView, TreeGrid, Menubar, Listbox.
  • aria-activedescendant for virtual focus: Combobox.
  • Focus return on dialog dismiss: ModalDialog, AlertDialog, MenuButton, Menubar.
  • Escape closes popups: ModalDialog, AlertDialog, MenuButton, Menubar, Combobox, Tooltip.

Explore the live Storybook demo or run npm run storybook locally to see every keyboard path with step-by-step play interactions.

Styling

The package ships two CSS files:

  • @afixt/apg-react/styles.css — full baseline styles for every component.
  • @afixt/apg-react/variables.css — only the design tokens, if you want to write your own styles.

All visual choices are driven by CSS custom properties defined in variables.css. Override them at :root or at a container scope:

:root {
  --apg-color-primary: #7c3aed;
  --apg-radius-md: 0.25rem;
  --apg-font-family: "Inter", system-ui, sans-serif;
}

Key token groups: colors (--apg-color-*), spacing (--apg-space-*), radii (--apg-radius-*), typography (--apg-font-*), focus ring (--apg-focus-ring-*), shadows (--apg-shadow-*), z-index (--apg-z-*).

Internationalization (i18n)

Components that render hardcoded user-facing strings (aria-labels, button text) accept an optional labels prop — an object whose keys map to English defaults. Pass your own translations without forking:

<Alert message="Saved" type="info" labels={{ dismiss: "Fermer" }} />
<Carousel slides={slides} labels={{ previousSlide: "Anterior", nextSlide: "Siguiente" }} />
<ModalDialog isOpen onClose={close} labels={{ closeDialog: "Cerrar" }}>…</ModalDialog>
<Spinbutton min={0} max={10} labels={{ increaseValue: "Erhöhen", decreaseValue: "Verringern" }} />
<Breadcrumb items={items} navLabel="Fil d'Ariane" />

When labels is omitted, the English defaults are used. Only the keys you override are affected; the rest keep their defaults.

Implementer responsibilities

A handful of concerns must be satisfied by you — they cannot be handled at the library level:

  • Visible focus indicators. The default focus ring uses a soft box-shadow; ensure your brand palette preserves ≥3:1 contrast against the background.
  • Color contrast. If you override tokens, verify WCAG 1.4.3 (4.5:1 for text) and 1.4.11 (3:1 for UI).
  • External labels. Where a component exposes ariaLabelledby, make sure the referenced element exists and carries a meaningful name.
  • Focus restoration on unmount. Dialog components return focus to the invoking element when dismissed, but if you unmount them imperatively, re-establish focus yourself.
  • Live regions for dynamic content. Components that produce their own role=alert / role=status fire announcements; adjacent dynamic content you write still needs its own live region.

Testing

npm test               # unit + a11y contract suite (jsdom)
npm run test:e2e:build # builds Storybook, runs Puppeteer E2E tests
npm run test:all       # both
  • 295 unit tests across 32 suites; 92%+ statement coverage.
  • 37 accessibility-contract tests built on a hand-rolled ARIA-aware DOM assertion library — no external a11y libraries of any kind.
  • E2E tests drive a real Chromium against a built Storybook: accessible-name presence, aria-* id resolution, ARIA boolean grammar, Tab reachability.

Development

npm install
npm run storybook     # http://localhost:6006
npm test
npm run build         # produces dist/

Contributing

Issues and PRs are welcome. See CONTRIBUTING.md.

Versioning

This library follows Semantic Versioning. Breaking changes land in major releases; new components and opt-in features in minor; fixes in patch. See CHANGELOG.md.

License

MIT © AFixt, Inc. — see LICENSE.