Building UI components that follow the ARIA Authoring Practices Guide (APG) is a time-consuming and challenging task to capture all the many details. Here comes aria-voyager
the canoe vessel that navigates your components. You bring your own markup (BYOM) and aria-voyager layers navigation on top.
I built aria-voyager
to provide the full navigation sets for composite widget roles. Following the universal approach the core is written in plain TS to be framework agnostic and to be able to function on its own plus adapters per framework to integrate with their reactivity system.
Architecture
Two parts are relevant for its architecture: composition of its atomic navigation patterns and reading/writing the state back and forth to the DOM/framework adapter (much like its IO part).
Navigation Patterns
The heart of all navigation consists of many atomic patterns, each one doing one particular task and form a library to pull from. Each control expresses its navigation capabilities through a composition of these and a new control can be created from them. They range from primitive patterns next, previous, home, end keyboard and pointer navigation to more complex features, such as single and multi selection all while applying the appropriate focus strategy for the control.
These are battle tested with a huge test suite. And on a funny note: these patterns are recycled code that I’ve written 15 years ago.
Read/Write State
A control is keeping its state in memory. To keep it in sync with the “real world” state must be updated from its source. To do that each control uses emitters and updaters. By default a DOMObserver is used to update when changes are happening there. Emitters on the other hand let consumers know about changes happening, for example to react to a different selection.
Thats the link into the reactivity systems of a given framework. When creating a control pass it instances of updaters/emitters that interact with your framework.
PS: Internally everything is waiting to use the new signals feature to make internal state better reactive as well a better exchange with its consumers.
Framework Integration
Adapting a framework is a minimal layer intentionally kept very slim thanks to its core’s architecture.
Ember
Ember is my framework of choice so I built ember-aria-voyager
as a first adapter. For each supported control a helper is available. Beyond that, the ember package ships with test helpers to run your own testsuite for your own component.
Next: Svelte and Vue
As next step I’d like to support svelte through actions and vue through directives. The technical implementation seems straight forward… but I might be a bit too much indulged by ember’s fantastic test support. Neither official docs for svelte actions and vue directives mentions ways to test them. I’d prefer tests written in vitest browser mode (no virtual environment for sure) – if you know, please drop a comment in the linked issues here, then they are ready for development.
Hope you find great use in this library and I’m happy to adopt more frameworks.