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.