Accessibility Guide for VueJS Tour
Current State
VueJS Tour now includes comprehensive WCAG 2.1 AA accessibility features, including keyboard navigation, ARIA attributes, focus management, and screen reader support.
⚠️ Note: Accessibility features are disabled by default (as of v2.5.0) pending further testing and validation. Enable them by setting enableA11y: true on the component.
Implemented Accessibility Features
1. ARIA Attributes ✅
Implemented:
- ✅
aria-labelon tooltip (configurable viaariaLabelprop or per-stepariaLabel) - ✅
aria-describedbyfor step content - ✅
aria-live="polite"region for step announcements - ✅
aria-modal="true"whenenableA11yis enabled - ✅
role="dialog"for proper semantic structure - ✅ Enhanced
aria-labelattributes on all buttons
2. Keyboard Navigation ✅
Implemented:
- ✅
Escapekey to close tour - ✅
ArrowRightorEnterto go to next step - ✅
ArrowLeftto go to previous step - ✅ Keyboard navigation can be disabled via
keyboardNav: false - ⚠️ Focus trap not yet implemented (planned for future release)
3. Focus Management ✅
Implemented:
- ✅ Tooltip receives focus when opened (when
enableA11yis true) - ✅ Previous focus restored when tour ends
- ✅
tabindex="0"on tooltip for keyboard accessibility
4. Screen Reader Support ✅
Implemented:
- ✅ Step progress announced ("Step 2 of 5")
- ✅ Descriptive button labels with step context
- ✅ Content changes announced via aria-live region
- ✅ Screen reader only content via
.vjt-sr-onlyCSS class
5. Semantic Structure ✅
Implemented:
- ✅
role="dialog"on tooltip (changed fromrole="tooltip"for better modal semantics) - ✅ Step counter announced to screen readers
- ✅ Proper ARIA attributes on all interactive elements
Usage
Enabling Accessibility Features
Accessibility features are disabled by default. To enable them:
<VTour
:steps="steps"
:enableA11y="true"
:keyboardNav="true"
ariaLabel="Product tour"
/>Available Props
interface VTourProps {
// ... other props
/** Enable accessibility features (default: false) */
readonly enableA11y?: boolean;
/** Enable keyboard navigation (default: true, only active when enableA11y is true) */
readonly keyboardNav?: boolean;
/** Custom aria-label for the tour (default: "Guided tour") */
readonly ariaLabel?: string;
}
interface ITourStep {
// ... other props
/** Descriptive label for screen readers */
readonly ariaLabel?: string;
}Example: Per-Step Accessibility Labels
<script setup>
const steps = [
{
target: '#welcome',
content: 'Welcome to our app!',
ariaLabel: 'Welcome step: Introduction to the application',
},
{
target: '#profile',
content: 'View your profile here',
ariaLabel: 'Profile step: Learn about your user profile',
},
];
</script>
<template>
<VTour :steps="steps" :enableA11y="true" />
</template>Implementation Details
Features Already Implemented ✅
ARIA Live Region - Announces step changes to screen readers
vue<div v-if="enableA11y" role="status" aria-live="polite" aria-atomic="true" class="vjt-sr-only" > Step {{ currentStepIndex + 1 }} of {{ props.steps.length }} </div>Enhanced Tooltip Semantics - Proper dialog role and ARIA attributes
vue<div :id="tooltipId" role="dialog" :aria-modal="enableA11y ? 'true' : undefined" :aria-label="getCurrentStep?.ariaLabel || ariaLabel" :aria-describedby="`${tooltipId}-content`" :tabindex="enableA11y ? '0' : undefined" />Keyboard Navigation - Arrow keys, Enter, and Escape support
typescriptconst onKeydown = (event: KeyboardEvent): void => { if (!tourVisible.value || !props.enableA11y || !props.keyboardNav) return; switch (event.key) { case 'Escape': endTour(); event.preventDefault(); break; case 'ArrowRight': case 'Enter': nextStep(); event.preventDefault(); break; case 'ArrowLeft': if (currentStepIndex.value > 0) { lastStep(); event.preventDefault(); } break; } };Focus Management - Stores and restores focus
typescriptlet previousFocus: HTMLElement | null = null; const startTour = async () => { if (props.enableA11y && typeof document !== 'undefined') { previousFocus = document.activeElement as HTMLElement; } // ... tour starts if (props.enableA11y) { await nextTick(); _Tooltip.value?.focus(); } }; const stopTour = () => { if (props.enableA11y && previousFocus) { previousFocus.focus(); previousFocus = null; } };Enhanced Button Labels - Descriptive aria-labels for all actions
vue<button type="button" @click.prevent="nextStep" :aria-label=" enableA11y ? isLastStep ? 'Finish tour' : `Go to next step, step ${nextStepIndex + 1} of ${props.steps.length}` : undefined " > {{ getNextLabel }} </button>
Future Enhancements ⚠️
These features are planned for future releases:
- Focus Trap - Trap focus within modal when backdrop is active
- Customizable Keyboard Shortcuts - Allow users to configure key bindings
- Visual Progress Indicators - Show step progress visually
- Skip to Content - Quick navigation option
Backward Compatibility
All accessibility features:
- ⚠️ Default to disabled (
enableA11y: false) as of v2.4.3 pending further testing - Are opt-in via
enableA11y: trueprop - Do not break existing implementations when disabled
- Add ~3KB to bundle size (minimal impact)
Testing Requirements
Keyboard-only navigation
- Can navigate all steps without mouse
- Can dismiss tour with Escape
- Focus visible at all times
Screen reader testing
- NVDA (Windows)
- JAWS (Windows)
- VoiceOver (macOS/iOS)
- TalkBack (Android)
Automated testing
- axe-core integration
- ARIA validity checks
- Keyboard interaction tests
Resources
- WAI-ARIA Authoring Practices Guide - Dialog
- WCAG 2.1 Guidelines
- focus-trap library
- Vue A11y Best Practices
Testing Status
Implemented (v2.4.3): ✅
- ✅ Keyboard navigation tests (28 test cases)
- ✅ ARIA attributes validation
- ✅ Focus management tests
- ✅ Screen reader announcement tests
Pending:
Manual testing with screen readers
- NVDA (Windows)
- JAWS (Windows)
- VoiceOver (macOS/iOS)
- TalkBack (Android)
Real-world validation
- User testing with keyboard-only users
- Screen reader user feedback
- Production environment testing
Automated accessibility testing
- axe-core integration
- Lighthouse accessibility audits
- pa11y or similar tools
Status
✅ Phase 1 (Critical) features implemented - All essential WCAG AA compliance features are in place and tested. Features are disabled by default pending further validation.
Next steps:
- Community testing and feedback
- Screen reader validation
- Enable by default once vetted
- Implement Phase 2 features (focus trap, custom shortcuts)
