Skip to content

Accessibility Guide ​

Vue Custom Tooltip is built with accessibility in mind, following WAI-ARIA guidelines for tooltips and ensuring keyboard navigation and screen reader support.

ARIA Attributes ​

The tooltip component automatically applies the appropriate ARIA attributes for accessibility.

Tooltip Content:

  • id matches the aria-describedby attribute on the trigger element
  • role="tooltip"
  • aria-live="polite" for polite announcements by screen readers

Trigger Element:

  • aria-describedby referencing the tooltip's id
  • aria-expanded toggles on click to indicate tooltip visibility
vue
<template>
  <Tooltip content="Helper text">
    <!-- Results in: -->
    <button
      aria-describedby="tooltip-1"
      role="button"
      tabindex="0"
    >
      Hover me
    </button>
  </Tooltip>
</template>

Keyboard Navigation ​

Tooltips are keyboard-accessible by default:

  • Tab: Move focus between tooltip triggers
  • Enter/Space: Toggle click-triggered tooltips
  • Escape: Close active tooltip
  • Focus: Show tooltip on focusable elements
  • Blur: Hide tooltip when focus is lost

Screen Reader Support ​

Screen readers announce tooltip content appropriately:

vue
<template>
  <!-- Basic screen reader support -->
  <Tooltip content="Delete this item">
    <button>
      <IconTrash aria-hidden="true" />
    </button>
  </Tooltip>

  <!-- With additional context -->
  <Tooltip content="Press Enter to save changes">
    <button aria-label="Save">
      <IconSave aria-hidden="true" />
    </button>
  </Tooltip>
</template>

Focus Management ​

Focusable Elements ​

Ensure tooltip triggers are focusable:

vue
<template>
  <!-- Good - naturally focusable -->
  <Tooltip content="Submit form">
    <button>Submit</button>
  </Tooltip>

  <!-- Good - made focusable -->
  <Tooltip content="More information">
    <div
      role="button"
      tabindex="0"
    >
      Info
    </div>
  </Tooltip>

  <!-- Avoid - not focusable -->
  <Tooltip content="Helper">
    <div>❌ Not accessible</div>
  </Tooltip>
</template>

Focus Indicators ​

Maintain visible focus indicators:

vue
<template>
  <Tooltip content="Action button">
    <button class="focus-visible:ring-2">
      Visible Focus
    </button>
  </Tooltip>
</template>

<style>
/* Ensure focus is visible */
:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}
</style>

Reduced motion support ​

The tooltip respects users 'prefers-reduced-motion' system settings by disabling animations for a more comfortable experience. This ensures tooltips appear instantly without animation when reduced motion is preferred:

css
@media (prefers-reduced-motion: reduce) {
  .tooltip-fade-enter-active,
  .tooltip-fade-leave-active {
    transition: none;
  }

  .tooltip-fade-enter-from,
  .tooltip-fade-leave-to {
    transform: scale(1);
  }
}

High contrast mode support ​

The tooltip adapts to users' high contrast preference by enhancing visibility with thicker borders and bolder text. This ensures better readability and accessibility for users who require increased contrast:

css
/* High contrast mode support */
@media (prefers-contrast: high) {
  .tooltip-content {
    border-width: 2px;
    font-weight: 600;
  }
}

Best Practices ​

1. Clear and Concise Content ​

vue
<template>
  <!-- Good - clear and concise -->
  <Tooltip content="Delete item">
    <button>
      <IconTrash />
    </button>
  </Tooltip>

  <!-- Avoid - too verbose -->
  <Tooltip content="Click this button to permanently delete the selected item from your list">
    <button>
      <IconTrash />
    </button>
  </Tooltip>
</template>

2. Appropriate Timing ​

vue
<template>
  <!-- Good - enough time to read -->
  <Tooltip
    content="Important information"
    :show-delay="200"
    :hide-delay="150"
  >
    <button>Action</button>
  </Tooltip>

  <!-- Avoid - too quick -->
  <Tooltip
    content="Important information"
    :show-delay="50"
    :hide-delay="50"
  >
    <button>Action</button>
  </Tooltip>
</template>

3. Color Contrast ​

Ensure sufficient color contrast:

css
:root {
  /* Good - high contrast */
  --tooltip-background: rgba(0, 0, 0, 0.9);
  --tooltip-color: #ffffff;

  /* Avoid - low contrast */
  --tooltip-bad-background: rgba(0, 0, 0, 0.3);
  --tooltip-bad-color: #666666;
}

Form Input Tooltips ​

vue
<template>
  <form>
    <Tooltip content="Must be at least 8 characters">
      <input
        type="password"
        aria-required="true"
        placeholder="Password"
      >
    </Tooltip>

    <Tooltip content="Enter a valid email address">
      <input
        type="email"
        aria-required="true"
        placeholder="Email"
      >
    </Tooltip>
  </form>
</template>

Icon Button Tooltips ​

vue
<template>
  <div role="toolbar" aria-label="Document actions">
    <Tooltip content="Save document">
      <button aria-label="Save">
        <IconSave aria-hidden="true" />
      </button>
    </Tooltip>

    <Tooltip content="Print document">
      <button aria-label="Print">
        <IconPrint aria-hidden="true" />
      </button>
    </Tooltip>
  </div>
</template>

Interactive Content ​

For tooltips with interactive content, ensure proper focus management:

vue
<template>
  <Tooltip>
    <button aria-label="Settings">
      <IconSettings aria-hidden="true" />
    </button>

    <template #content>
      <div
        role="dialog"
        aria-label="Settings options"
      >
        <button
          tabindex="0"
          @click="saveSettings"
        >
          Save preferences
        </button>
      </div>
    </template>
  </Tooltip>
</template>

Testing Accessibility ​

Manual Testing Checklist ​

  1. Keyboard Navigation

    • [ ] All tooltips reachable via Tab
    • [ ] Enter/Space toggles click tooltips
    • [ ] Escape closes active tooltips
  2. Screen Reader Testing

    • [ ] Content is announced properly
    • [ ] Role and state are clear
    • [ ] Interactive elements are discoverable
  3. Focus Management

    • [ ] Focus indicators are visible
    • [ ] Focus order is logical
    • [ ] No keyboard traps
  4. Color and Contrast

    • [ ] Text meets WCAG contrast requirements
    • [ ] Works in high contrast mode
    • [ ] Visible in light/dark themes

Resources ​