Development-time validators and runtime checks for @a13y (tree-shakeable)
npm install @a13y/devtoolsDevelopment-time validators and runtime checks for @a13y
Helpful warnings and error messages during development, automatically stripped in production.


---
- Development-only - Zero overhead in production (tree-shakeable)
- WCAG references - Every warning includes WCAG 2.2 criterion
- Fix suggestions - Actionable fixes with code examples
- Runtime validation - Catches accessibility issues during development
- Type-safe - Full TypeScript support
``bash`
npm install -D @a13y/devtools
Devtools are automatically integrated when you use @a13y/react or @a13y/core. Simply install the package and warnings will appear in development.
`typescript
import { useAccessibleButton } from '@a13y/react';
function Button() {
const { buttonProps } = useAccessibleButton({ onPress: () => {} });
// ⚠️ Warning in console if devtools installed:
// "Element is missing accessible label (WCAG 4.1.2)"
return ;
}
`
You can also use validators directly:
`typescript
import { validateFocus, validateAria } from '@a13y/devtools/runtime/validators';
const button = document.querySelector('button');
// Validate focus management
validateFocus(button, {
hasFocusableElements: true,
isVisible: true,
});
// Validate ARIA attributes
validateAria(button, {
role: 'button',
requiredAttrs: ['aria-label'],
});
`
`typescript
import { validateFocus } from '@a13y/devtools/runtime/validators';
validateFocus(element, {
hasFocusableElements: true,
isVisible: true,
isInert: false,
});
`
Checks:
- Element has focusable children
- Focus trap contains interactive elements
- Elements are visible
- No inert ancestors
`typescript
import { validateAria } from '@a13y/devtools/runtime/validators';
validateAria(element, {
role: 'dialog',
requiredAttrs: ['aria-labelledby', 'aria-describedby'],
allowedRoles: ['dialog', 'alertdialog'],
});
`
Checks:
- Valid ARIA roles
- Required ARIA attributes present
- Attribute values are valid
- No conflicting attributes
`typescript
import { validateKeyboard } from '@a13y/devtools/runtime/validators';
validateKeyboard(element, {
supportsKeys: ['Enter', ' ', 'Escape'],
hasKeyboardHandler: true,
});
`
Checks:
- Keyboard event handlers present
- Required keys supported
- Focus visible on keyboard navigation
`typescript
import { warn, error } from '@a13y/devtools/runtime/warnings';
// Polite warning (logged to console)
warn('accessibility-issue', {
message: 'Missing accessible label',
wcagCriterion: '4.1.2',
fixes: [
'Add aria-label attribute',
'Add aria-labelledby reference',
'Add visible text content',
],
});
// Error (thrown in dev, silent in prod)
error('critical-accessibility-issue', {
message: 'Dialog missing required title',
wcagCriterion: '2.4.6',
});
`
- focus - Focus management issueskeyboard
- - Keyboard navigation problemsaria
- - ARIA attribute errorsstructure
- - DOM structure issuessemantics
- - Semantic HTML problems
Runtime checks that throw errors in development:
`typescript
import { invariant } from '@a13y/devtools/runtime/invariants';
invariant(
element.hasAttribute('aria-label'),
'Button must have accessible label',
'WCAG 4.1.2'
);
`
All devtools code is automatically removed in production:
`typescript
// Development build
if (process.env.NODE_ENV !== 'production') {
validateFocus(element);
}
// Production build - entire block removed by bundler
// No runtime overhead!
`
Configure warning behavior:
`typescript
import { configureWarnings } from '@a13y/devtools';
configureWarnings({
// Disable specific warnings
ignore: ['focus-trap-no-elements'],
// Throw errors instead of warnings
strict: true,
// Custom warning handler
onWarn: (warning) => {
console.log([A13Y] ${warning.message});`
// Send to error tracking service
},
});
Full TypeScript support with type definitions:
`typescript`
import type {
WarningType,
ValidationOptions,
WCAGCriterion,
} from '@a13y/devtools';
`
⚠️ A13Y Warning: Missing accessible label
Element:
WCAG: 4.1.2 Name, Role, Value
Suggested fixes:
1. Add aria-label:
` Issue: aria-expanded must be "true" or "false", not "yes" Fix: Issue: Focus trap activated but contains no focusable elements Suggested fixes: Import validators individually for optimal bundle size: // ❌ Avoid - imports all validators Created and maintained by Diego Aneli (@DiegoAneli) MIT © Diego Aneli and contributors
⚠️ A13Y Warning: Invalid ARIA attribute value
Element:
WCAG: 4.1.2 Name, Role, Value
``$3
`
⚠️ A13Y Warning: Focus trap has no focusable elements
Element: ...
WCAG: 2.1.1 Keyboard
1. Add focusable elements (button, input, a, etc.)
2. Add tabindex="0" to make element focusable
3. Check if elements are hidden or disabled`Tree Shaking
typescript``
// ✅ Good - imports only focus validator
import { validateFocus } from '@a13y/devtools/runtime/validators';
import { validateFocus } from '@a13y/devtools';Author
License