Skip to content

fix(carousel): add vertical keyboard nav and aria-live announcements#10226

Open
mahmoodhamdi wants to merge 1 commit intoshadcn-ui:mainfrom
mahmoodhamdi:fix/carousel-a11y-vertical-keys
Open

fix(carousel): add vertical keyboard nav and aria-live announcements#10226
mahmoodhamdi wants to merge 1 commit intoshadcn-ui:mainfrom
mahmoodhamdi:fix/carousel-a11y-vertical-keys

Conversation

@mahmoodhamdi
Copy link
Copy Markdown

What

Two accessibility improvements for the Carousel component:

  1. Vertical keyboard navigation — ArrowUp/ArrowDown now work when orientation="vertical"
  2. Screen reader announcements — Added aria-live region that announces current slide position

Why

Keyboard navigation (#10219)

The handleKeyDown handler only listened for ArrowLeft/ArrowRight, making vertical carousels inaccessible via keyboard. Per WAI-ARIA Carousel Pattern, directional keys should match the carousel orientation.

Screen reader support (#10220)

The carousel role="region" had no mechanism to announce slide changes. Screen reader users had no way to know which slide they were on or how many slides existed.

How

Keyboard fix

Replaced hardcoded arrow key strings with orientation-aware variables:

const prevKey = orientation === "vertical" ? "ArrowUp" : "ArrowLeft"
const nextKey = orientation === "vertical" ? "ArrowDown" : "ArrowRight"

Added orientation to the useCallback dependency array.

Aria-live region

  • Added currentSlide and slideCount state, updated in onSelect
  • Added a visually-hidden <span aria-live="polite" aria-atomic="true"> that announces "Slide X of Y"
  • Added optional aria-label prop forwarded to the role="region" container
  • Fixed missing api?.off("reInit", onSelect) in useEffect cleanup

Files changed (3)

All three carousel variants updated consistently:

  • apps/v4/registry/bases/base/ui/carousel.tsx
  • apps/v4/registry/bases/radix/ui/carousel.tsx
  • apps/v4/registry/new-york-v4/ui/carousel.tsx

Testing

  • Verified ArrowUp/ArrowDown navigates vertical carousels
  • Verified ArrowLeft/ArrowRight still works for horizontal (default)
  • Verified aria-live region updates on slide change
  • No breaking changes — aria-label is optional, keyboard behavior is backward-compatible

Closes #10219
Closes #10220

…lity

- Fix shadcn-ui#10219: handleKeyDown now uses ArrowUp/ArrowDown for vertical orientation
  and ArrowLeft/ArrowRight for horizontal; adds orientation to dep array
- Fix shadcn-ui#10220: accept aria-label prop on Carousel and forward it to the region
  div; add visually-hidden aria-live="polite" region that announces current
  slide index ("Slide X of Y") on every navigation event
- Fix missing api?.off("reInit", onSelect) in useEffect cleanup
- Applied to all three variants: bases/base, bases/radix, new-york-v4
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 29, 2026

@mahmoodhamdi is attempting to deploy a commit to the shadcn-pro Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant