Skip to main content
Vuetify0 is now in alpha!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

Accessibility

v0 provides ARIA attributes out-of-the-box through the attrs pattern. You provide styling and visual feedback.

The attrs Pattern

Every v0 component exposes an attrs object containing all accessibility attributes. Spread it onto your elements:

vue
<script setup>
  import { Selection } from '@vuetify/v0'

  const items = ['Apple', 'Banana', 'Cherry']
</script>

<template>
  <Selection.Root v-slot="{ attrs }">
    <div v-bind="attrs">
      <Selection.Item v-for="item in items" :key="item" v-slot="{ attrs }">
        <button v-bind="attrs">{{ item }}</button>
      </Selection.Item>
    </div>
  </Selection.Root>
</template>

What’s Included in attrs

ComponentARIA Attributes Provided
Selection.Itemaria-selected, aria-disabled, data-selected, data-disabled
Group.Itemrole="checkbox", aria-checked, aria-disabled, data-selected, data-disabled, data-mixed
ExpansionPanel.Activatorid, role, tabindex, aria-expanded, aria-controls, aria-disabled
Pagination.Rootaria-label, role="navigation"[1]
Popover.Activatorpopovertarget, data-open[2]
Tip

Always spread the attrs object from slot props onto your interactive elements. Missing ARIA attributes break screen reader support.

Developer Responsibilities

v0 provides the ARIA plumbing. You must provide:

ResponsibilityExample
Visual focus indicators:focus-visible { outline: 2px solid blue }
Color contrastEnsure 4.5:1 ratio minimum
Visible labelsAdd <label> or aria-label for inputs
Skip linksNavigation landmarks for keyboard users

Focus Trapping

v0 does not provide focus trapping. Use external solutions:

Roving Tabindex

v0 does not provide roving tabindex. This keeps the library headless - implement in your design system layer if needed for arrow key navigation between items.

Keyboard Navigation

What v0 Handles

  • tabindex management (-1 when disabled, 0 when enabled)

  • ARIA state synchronization (aria-expanded, aria-selected)

  • Data attributes for styling (data-selected, data-disabled)

What You Implement

PatternKeys to Handle
List selectionArrow keys, Home/End
MenusArrow keys, Escape, Enter
DialogsEscape to close, focus trap
TabsArrow keys, Home/End
ts
// You implement navigation logic - v0 provides selection state
function onKeydown (e: KeyboardEvent, ids: string[], currentIndex: number) {
  switch (e.key) {
    case 'ArrowDown': selection.select(ids[currentIndex + 1]); break
    case 'ArrowUp': selection.select(ids[currentIndex - 1]); break
    case 'Home': selection.select(ids[0]); break
    case 'End': selection.select(ids[ids.length - 1]); break
  }
}

Testing Strategies

Automated Testing

MyComponent.test.ts
import { axe } from 'vitest-axe'

it('passes accessibility audit', async () => {
  const { container } = render(MyComponent)
  expect(await axe(container)).toHaveNoViolations()
})

Manual Testing Checklist

Use this checklist during manual QA:

markdown
- [ ] Tab through all interactive elements
- [ ] Verify focus visibility
- [ ] Test with keyboard only (no mouse)
- [ ] Check color contrast with DevTools
- [ ] Validate with browser accessibility tree
ToolPurpose
axe DevToolsBrowser extension for WCAG scanning
LighthouseBuilt-in Chrome audit
NVDA/VoiceOverScreen reader verification

Internationalization

v0’s useLocale handles translated labels. See useLocale for accessibility label translations.

For RTL (right-to-left) support, see useRtl. Direction is managed independently from locale — useRtl provides a reactive isRtl boolean and sets the dir attribute on the target element.


  1. role="navigation" is only added when the root element isn’t already a <nav>. If you render Pagination.Root as="nav", the role is omitted to avoid redundant landmark roles. ↩︎

  2. Popover.Activator wires the native Popover API↗︎ via the popovertarget attribute. See the Browser Support page for fallback behavior in older browsers. ↩︎

Was this page helpful?

Ctrl+/