Skip to content

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-label on tooltip (configurable via ariaLabel prop or per-step ariaLabel)
  • ✅ aria-describedby for step content
  • ✅ aria-live="polite" region for step announcements
  • ✅ aria-modal="true" when enableA11y is enabled
  • ✅ role="dialog" for proper semantic structure
  • ✅ Enhanced aria-label attributes on all buttons

2. Keyboard Navigation ✅ ​

Implemented:

  • ✅ Escape key to close tour
  • ✅ ArrowRight or Enter to go to next step
  • ✅ ArrowLeft to 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 enableA11y is 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-only CSS class

5. Semantic Structure ✅ ​

Implemented:

  • ✅ role="dialog" on tooltip (changed from role="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:

vue
<VTour
  :steps="steps"
  :enableA11y="true"
  :keyboardNav="true"
  ariaLabel="Product tour"
/>

Available Props ​

typescript
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 ​

vue
<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 ✅ ​

  1. 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>
  2. 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"
    />
  3. Keyboard Navigation - Arrow keys, Enter, and Escape support

    typescript
    const 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;
      }
    };
  4. Focus Management - Stores and restores focus

    typescript
    let 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;
      }
    };
  5. 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:

  1. Focus Trap - Trap focus within modal when backdrop is active
  2. Customizable Keyboard Shortcuts - Allow users to configure key bindings
  3. Visual Progress Indicators - Show step progress visually
  4. 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: true prop
  • Do not break existing implementations when disabled
  • Add ~3KB to bundle size (minimal impact)

Testing Requirements ​

  1. Keyboard-only navigation

    • Can navigate all steps without mouse
    • Can dismiss tour with Escape
    • Focus visible at all times
  2. Screen reader testing

    • NVDA (Windows)
    • JAWS (Windows)
    • VoiceOver (macOS/iOS)
    • TalkBack (Android)
  3. Automated testing

    • axe-core integration
    • ARIA validity checks
    • Keyboard interaction tests

Resources ​

Testing Status ​

Implemented (v2.4.3): ✅

  • ✅ Keyboard navigation tests (28 test cases)
  • ✅ ARIA attributes validation
  • ✅ Focus management tests
  • ✅ Screen reader announcement tests

Pending:

  1. Manual testing with screen readers

    • NVDA (Windows)
    • JAWS (Windows)
    • VoiceOver (macOS/iOS)
    • TalkBack (Android)
  2. Real-world validation

    • User testing with keyboard-only users
    • Screen reader user feedback
    • Production environment testing
  3. 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:

  1. Community testing and feedback
  2. Screen reader validation
  3. Enable by default once vetted
  4. Implement Phase 2 features (focus trap, custom shortcuts)

Released under the MIT License.