Accessible tabs without libraries

The WAI-ARIA tabs pattern in forty lines of React, including roving focus and reduced motion.

  • 5 min read
  • Accessibility
Cover graphic for “Accessible tabs without libraries”

The pattern

A tab list owns a set of tabs; each tab controls one panel. Only the active tab is in the tab order, and arrow keys move between tabs.

  • role=tablist on the container
  • role=tab with aria-selected and aria-controls
  • role=tabpanel with aria-labelledby

Need a hand?

Let’s build it together

Keyboard support

Roving focus
function onKeyDown(e: React.KeyboardEvent) {
  if (e.key === "ArrowRight") select((index + 1) % count);
  if (e.key === "ArrowLeft") select((index - 1 + count) % count);
}

Home and End jump to the first and last tab. Selection follows focus, which suits panels that render instantly.

Let’s talk

Tell me about your project. I usually reply within two working days.