Accessibility (A11y)
Directix provides comprehensive accessibility utilities to help you build inclusive directive experiences that work for everyone.
Overview
The accessibility module in v1.10.0 includes:
- ARIA attribute management - Apply and manage ARIA attributes
- Screen reader support - Announce messages to screen readers
- Keyboard navigation - Navigate directive elements with keyboard
- Focus management - Trap and manage focus within components
ARIA Attributes
applyAriaAttributes
Apply ARIA attributes to an element with automatic cleanup support.
import { applyAriaAttributes } from 'directix'
// Apply ARIA attributes
applyAriaAttributes(element, {
role: 'button',
ariaLabel: 'Submit form',
ariaDisabled: true,
tabIndex: 0,
})ARIA Configuration
The ARIAConfig interface supports all standard ARIA attributes:
interface ARIAConfig {
// Role
role?: ARIARole // 60+ ARIA roles supported
// State attributes
ariaExpanded?: boolean
ariaSelected?: boolean
ariaChecked?: boolean
ariaDisabled?: boolean
ariaHidden?: boolean
ariaBusy?: boolean
ariaPressed?: boolean
ariaCurrent?: 'page' | 'step' | 'location' | 'date' | 'time' | boolean
// Property attributes
ariaLabel?: string
ariaLabelledBy?: string
ariaDescribedBy?: string
ariaControls?: string
ariaOwns?: string
ariaHasPopup?: 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'tooltip' | boolean
// Live region attributes
ariaLive?: 'off' | 'polite' | 'assertive'
ariaAtomic?: boolean
ariaRelevant?: 'additions' | 'removals' | 'text' | 'all'
// Value attributes
ariaValueNow?: number
ariaValueMin?: number
ariaValueMax?: number
ariaValueText?: string
// Other attributes
ariaPlaceholder?: string
ariaRequired?: boolean
ariaReadonly?: boolean
ariaModal?: boolean
tabIndex?: number
}clearAriaAttributes
Remove all ARIA attributes from an element:
import { clearAriaAttributes } from 'directix'
clearAriaAttributes(element)Auto-generate ARIA Config
Generate default ARIA configuration for common directive types:
import { getAutoAriaConfig } from 'directix'
// For a tooltip
const tooltipConfig = getAutoAriaConfig({
type: 'tooltip',
expanded: false,
})
// For a dialog
const dialogConfig = getAutoAriaConfig({
type: 'dialog',
label: 'Confirmation Dialog',
})Supported types: tooltip, menu, dialog, popover, dropdown, modal, alert, region
Screen Reader Support
announce
Announce messages to screen reader users:
import { announce } from 'directix'
// Basic announcement
announce('Form submitted successfully')
// With priority (polite waits for user to pause, assertive interrupts)
announce('Error: Please fix the form', { priority: 'assertive' })
// With custom timeout
announce('Item added to cart', { timeout: 2000 })Announcement Options
| Option | Type | Default | Description |
|---|---|---|---|
priority | 'polite' | 'assertive' | 'polite' | Announcement priority |
timeout | number | 1000 | Time before clearing (ms) |
clear | boolean | true | Clear message after timeout |
Example: Announce Copy Success
import { announce } from 'directix'
async function copyToClipboard(text: string) {
await navigator.clipboard.writeText(text)
announce('Copied to clipboard')
}Keyboard Navigation
useKeyboardNavigation
Composable for keyboard navigation within directive elements:
<script setup>
import { ref, onMounted } from 'vue'
import { useKeyboardNavigation } from 'directix'
const containerRef = ref(null)
const items = ref([])
const { focusedIndex, bind, focusNext, focusPrev } = useKeyboardNavigation({
focusTrap: true,
loop: true,
rovingTabindex: true,
})
onMounted(() => {
if (containerRef.value) {
bind(containerRef.value, items.value)
}
})
</script>
<template>
<div ref="containerRef" role="listbox">
<div
v-for="(item, index) in items"
:key="item.id"
ref="items"
role="option"
@click="selectItem(index)"
>
{{ item.label }}
</div>
</div>
</template>Navigation Configuration
| Option | Type | Default | Description |
|---|---|---|---|
nextKeys | string[] | ['ArrowDown', 'ArrowRight'] | Keys for next item |
prevKeys | string[] | ['ArrowUp', 'ArrowLeft'] | Keys for previous item |
selectKeys | string[] | ['Enter', ' '] | Keys for selection |
closeKeys | string[] | ['Escape'] | Keys for closing |
focusTrap | boolean | false | Enable focus trap |
loop | boolean | true | Loop navigation |
rovingTabindex | boolean | false | Use roving tabindex |
returnFocus | boolean | true | Return focus on close |
Focus Management
useFocusTrap
Composable for trapping focus within a container:
<script setup>
import { ref } from 'vue'
import { useFocusTrap } from 'directix'
const modalRef = ref(null)
const isOpen = ref(false)
const { activate, deactivate, isActive } = useFocusTrap(modalRef, {
initialFocus: '[data-autofocus]',
returnFocus: true,
escapeDeactivates: true,
onActivate: () => console.log('Focus trap activated'),
onDeactivate: () => console.log('Focus trap deactivated'),
})
function openModal() {
isOpen.value = true
activate()
}
function closeModal() {
deactivate()
isOpen.value = false
}
</script>
<template>
<button @click="openModal">Open Modal</button>
<div v-if="isOpen" ref="modalRef" role="dialog" aria-modal="true">
<h2>Modal Title</h2>
<input data-autofocus placeholder="First input" />
<button @click="closeModal">Close</button>
</div>
</template>Focus Trap Options
| Option | Type | Default | Description |
|---|---|---|---|
initialFocus | HTMLElement | string | Function | - | Initial focus element |
allowOutsideClick | boolean | Function | false | Allow clicks outside |
escapeDeactivates | boolean | true | Deactivate on Escape |
onActivate | Function | - | Callback on activate |
onDeactivate | Function | - | Callback on deactivate |
Best Practices
1. Always Provide Labels
// Good
applyAriaAttributes(button, {
role: 'button',
ariaLabel: 'Submit form',
})
// Avoid - screen readers may read nothing
element.setAttribute('role', 'button')2. Use Live Regions Appropriately
// For status updates that can wait
announce('Saving...', { priority: 'polite' })
// For urgent errors
announce('Critical error occurred!', { priority: 'assertive' })3. Implement Keyboard Navigation
All interactive elements should be accessible via keyboard:
- Use
useKeyboardNavigationfor lists and menus - Use
useFocusTrapfor modals and dialogs - Provide visible focus indicators
4. Test with Screen Readers
Always test your directives with actual screen readers:
- macOS: VoiceOver
- Windows: NVDA or JAWS
- Linux: Orca
- Mobile: VoiceOver (iOS) or TalkBack (Android)
Utility Functions
| Function | Description |
|---|---|
applyAriaAttributes | Apply ARIA attributes to element |
clearAriaAttributes | Remove all ARIA attributes |
generateAriaId | Generate unique ARIA ID |
announce | Announce to screen readers |
clearAnnouncer | Clear screen reader announcer |
getAutoAriaConfig | Auto-generate ARIA config |
useKeyboardNavigation | Keyboard navigation composable |
useFocusTrap | Focus trap composable |