@compa11y/core
v0.1.2
Published
Framework-agnostic accessibility primitives
Maintainers
Readme
@compa11y/core
Framework-agnostic accessibility primitives for building accessible UI components.
Installation
npm install @compa11y/coreFeatures
- Focus Management — Focus traps, focus scope, roving tabindex
- Keyboard Navigation — Pre-built patterns for menus, tabs, grids
- Screen Reader Support — Live region announcements
- ARIA Utilities — Helpers for managing ARIA attributes
- Dev Warnings — Catch accessibility issues during development
Usage
Focus Trap
import { createFocusTrap } from '@compa11y/core';
const dialog = document.getElementById('dialog');
const trap = createFocusTrap(dialog, {
escapeDeactivates: true,
returnFocus: true,
});
// Activate when dialog opens
trap.activate();
// Deactivate when dialog closes
trap.deactivate();Announcements
import { announce, announcePolite, announceAssertive } from '@compa11y/core';
// Polite announcement (doesn't interrupt)
announcePolite('Item added to cart');
// Assertive announcement (interrupts current speech)
announceAssertive('Error: Form submission failed');Keyboard Navigation
import { createKeyboardManager, KeyboardPatterns } from '@compa11y/core';
const manager = createKeyboardManager(
KeyboardPatterns.menu({
onUp: () => focusPreviousItem(),
onDown: () => focusNextItem(),
onEnter: () => selectItem(),
onEscape: () => closeMenu(),
})
);
manager.attach(menuElement);ARIA Utilities
import { aria, buildAriaProps, hasAccessibleName } from '@compa11y/core';
// Set individual ARIA attributes
aria.setExpanded(button, true);
aria.setControls(button, 'menu-id');
// Build props object for React/frameworks
const props = buildAriaProps({
expanded: true,
controls: 'menu-id',
hasPopup: 'menu',
});
// Check accessibility
if (!hasAccessibleName(element)) {
console.warn('Element needs an accessible name');
}Dev Warnings
import { checks, createComponentWarnings } from '@compa11y/core';
// Use pre-built checks
checks.accessibleLabel(element, 'MyComponent');
// Create component-scoped warnings
const warnings = createComponentWarnings('MyComponent');
warnings.error('Missing required prop', 'Add the "label" prop');API Reference
Focus
createFocusTrap(container, options)— Create a focus trapcreateFocusScope(container, options)— Manage focus within a scopecreateRovingTabindex(container, selector, options)— Roving tabindex patterninitFocusVisible()— Initialize focus-visible detection
Announcer
initAnnouncer()— Initialize live regionsannounce(message, options)— General announcementannouncePolite(message)— Non-interrupting announcementannounceAssertive(message)— Interrupting announcementcreateAnnouncer(defaults)— Create scoped announcer
Keyboard
createKeyboardManager(handlers, options)— Keyboard event handlingKeyboardPatterns.menu(handlers)— Menu navigation patternKeyboardPatterns.tabs(handlers)— Tabs navigation patternKeyboardPatterns.grid(handlers)— Grid navigation patterncreateTypeAhead(items, options)— Type-ahead search
ARIA
aria.*— ARIA attribute settersbuildAriaProps(props)— Build props objecthasAccessibleName(element)— Check for accessible namemergeAriaIds(...ids)— Merge ARIA ID lists
Dev
warn(warning)— Issue a warningchecks.*— Pre-built accessibility checkscreateComponentWarnings(name)— Create scoped warnings
DOM Utilities
isFocusable(element)— Check if focusableisTabbable(element)— Check if tabbablegetFocusableElements(container)— Get all focusable elementsgetTabbableElements(container)— Get all tabbable elementsgetFirstFocusable(container)— Get first focusablegetLastFocusable(container)— Get last focusable
Platform
isBrowser()— Check if in browserisMac()— Check if macOSprefersReducedMotion()— Check motion preferenceprefersHighContrast()— Check contrast preferenceprefersDarkMode()— Check color scheme preference
License
MIT
