Skip to content

Conversation

@hasegawa-101
Copy link
Contributor

@hasegawa-101 hasegawa-101 commented Nov 21, 2025

Closes #5810

📝 Description

Fix vertical tabs to use correct aria-orientation="vertical" and support Up/Down arrow key navigation.

⛳️ Current behavior (updates)

Vertical tabs incorrectly have aria-orientation="horizontal" and only respond to Left/Right arrow keys.

2025-11-21.22.18.00.mov

🚀 New behavior

  • Vertical tabs now have aria-orientation="vertical"
  • Up/Down arrow keys work for vertical tab navigation

💣 Is this a breaking change (Yes/No):

No

📝 Additional Information

Based on #5811 and addresses review feedback from @wingkwong.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed vertical tabs to properly set ARIA orientation attributes for accessibility compliance.
    • Added support for Up/Down arrow key navigation in vertical tabs for enhanced keyboard usability.
  • Tests

    • Added test coverage for vertical tabs ARIA orientation attributes and arrow key navigation behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Nov 21, 2025

🦋 Changeset detected

Latest commit: d02b90c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@heroui/tabs Patch
@heroui/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Nov 21, 2025

@hasegawa-101 is attempting to deploy a commit to the HeroUI Inc Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

Walkthrough

Fixed vertical tabs accessibility by computing the correct aria-orientation attribute and enabling Up/Down arrow key navigation. Changes include updates to tab orientation handling, corresponding tests for vertical tab behavior, and a changelog entry documenting the fix.

Changes

Cohort / File(s) Summary
Changelog
​.changeset/ninety-hairs-heal.md
Added patch changelog entry documenting the fix for vertical tabs aria-orientation and arrow key navigation.
Tests
packages/components/tabs/__tests__/tabs.test.tsx
Added two new test cases: one verifying aria-orientation="vertical" is set on vertical Tabs instances, and another confirming ArrowUp/ArrowDown keyboard navigation updates aria-selected state correctly.
Core Implementation
packages/components/tabs/src/use-tabs.ts
Introduced placement and orientation computed values derived from variantProps and isVertical. Passes orientation to useTabList via tabListProps. Removed duplicate placement variable declaration and unified its usage across getWrapperProps and data-vertical determination.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Verify that orientation is correctly computed from both isVertical and placement props and properly passed to useTabList
  • Confirm the test cases adequately cover the expected behavior for both vertical orientation detection and arrow key navigation
  • Check for any edge cases where isVertical and placement values might conflict or produce unexpected results

Suggested reviewers

  • jrgarciadev
  • wingkwong

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly summarizes the main change: fixing vertical tabs to support proper aria-orientation and Up/Down arrow navigation.
Description check ✅ Passed The PR description follows the template with all required sections filled: issue reference (#5810), description, current behavior, new behavior, breaking change status, and additional context.
Linked Issues check ✅ Passed Code changes address all requirements from #5810: vertical tabs now set aria-orientation to vertical via orientation prop in useTabList, and keyboard navigation supports Up/Down arrow keys.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing vertical tabs accessibility. The changeset, tests, and hook modifications all focus solely on the aria-orientation and arrow key navigation objectives.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc4c982 and d02b90c.

📒 Files selected for processing (3)
  • .changeset/ninety-hairs-heal.md (1 hunks)
  • packages/components/tabs/__tests__/tabs.test.tsx (1 hunks)
  • packages/components/tabs/src/use-tabs.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-10-25T17:08:46.283Z
Learnt from: adbjo
Repo: heroui-inc/heroui PR: 5846
File: packages/components/tabs/src/tabs.tsx:156-157
Timestamp: 2025-10-25T17:08:46.283Z
Learning: In packages/components/tabs/src/tabs.tsx, the renderTabs useMemo dependency array intentionally includes `variant` and `isVertical` to prevent potential side-effects, even though they might appear redundant based on static analysis.

Applied to files:

  • packages/components/tabs/__tests__/tabs.test.tsx
  • packages/components/tabs/src/use-tabs.ts
📚 Learning: 2025-10-25T17:11:59.338Z
Learnt from: adbjo
Repo: heroui-inc/heroui PR: 5846
File: packages/components/tabs/src/tabs.tsx:155-155
Timestamp: 2025-10-25T17:11:59.338Z
Learning: In packages/components/tabs/src/tabs.tsx, the renderTabs useMemo dependency array intentionally includes both `domRef` and `cursorRef` to maintain consistency in how ref objects are handled in dependency arrays, even though ref objects have stable identity across renders.

Applied to files:

  • packages/components/tabs/src/use-tabs.ts
📚 Learning: 2025-10-27T21:48:35.308Z
Learnt from: adbjo
Repo: heroui-inc/heroui PR: 5846
File: packages/components/tabs/src/tabs.tsx:76-101
Timestamp: 2025-10-27T21:48:35.308Z
Learning: In packages/components/tabs/src/tabs.tsx, the updateCursorPosition useCallback dependency array intentionally includes `cursorRef.current` to handle the case where the cursor span element is unmounted and remounted (e.g., when `disableAnimation` or `disableCursorAnimation` toggles). This ensures the callback is recreated when the ref points to a new element, triggering a dependency chain that re-establishes the ResizeObserver and initializes the new cursor element with the data-initialized attribute.
</learning]

Applied to files:

  • packages/components/tabs/src/use-tabs.ts
📚 Learning: 2025-10-27T21:52:33.324Z
Learnt from: adbjo
Repo: heroui-inc/heroui PR: 5846
File: packages/components/tabs/src/tabs.tsx:115-125
Timestamp: 2025-10-27T21:52:33.324Z
Learning: In packages/components/tabs/src/tabs.tsx, the useEffect dependency array at line 125 intentionally uses `domRef.current` rather than `domRef` because domRef.current can change between renders (when React sets it during the commit phase), whereas domRef itself has stable identity and won't change.

Applied to files:

  • packages/components/tabs/src/use-tabs.ts
🧬 Code graph analysis (1)
packages/components/tabs/__tests__/tabs.test.tsx (1)
packages/utilities/test-utils/src/focus.ts (1)
  • focus (6-12)
🔇 Additional comments (6)
.changeset/ninety-hairs-heal.md (1)

1-5: LGTM! Well-documented changelog entry.

The changelog accurately describes the accessibility fix for vertical tabs, including both the aria-orientation correction and the keyboard navigation enhancement.

packages/components/tabs/__tests__/tabs.test.tsx (2)

543-561: LGTM! Clean test for aria-orientation attribute.

The test correctly verifies that vertical tabs render with aria-orientation="vertical" on the tablist element, ensuring proper accessibility semantics.


563-600: LGTM! Comprehensive keyboard navigation test.

The test thoroughly validates that vertical tabs respond correctly to ArrowUp and ArrowDown keys, verifying aria-selected state changes at each navigation step. This ensures the accessibility fix works as intended.

packages/components/tabs/src/use-tabs.ts (3)

109-111: LGTM! Clean computation of placement and orientation.

The logic correctly derives:

  • placement: Defaults to "start" for vertical tabs, "top" otherwise, with user props taking precedence
  • orientation: Set to "vertical" when isVertical is true or placement is "start"/"end"

This establishes the foundation for proper accessibility attributes.


117-121: LGTM! Proper integration with React Aria.

Passing the computed orientation to useTabList ensures that:

  • The correct aria-orientation attribute is applied to the tablist
  • Keyboard navigation (ArrowUp/ArrowDown for vertical, ArrowLeft/ArrowRight for horizontal) is handled automatically by React Aria

This is the correct approach for implementing accessible tab navigation.


172-181: LGTM! Consistent orientation logic.

The data-vertical computation at lines 177-178 correctly mirrors the orientation logic, ensuring visual styling aligns with the accessibility semantics. The dependencies at line 180 properly include placement and isVertical.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 21, 2025

Open in StackBlitz

@heroui/accordion

npm i https://pkg.pr.new/@heroui/accordion@5924

@heroui/alert

npm i https://pkg.pr.new/@heroui/alert@5924

@heroui/autocomplete

npm i https://pkg.pr.new/@heroui/autocomplete@5924

@heroui/avatar

npm i https://pkg.pr.new/@heroui/avatar@5924

@heroui/badge

npm i https://pkg.pr.new/@heroui/badge@5924

@heroui/breadcrumbs

npm i https://pkg.pr.new/@heroui/breadcrumbs@5924

@heroui/button

npm i https://pkg.pr.new/@heroui/button@5924

@heroui/calendar

npm i https://pkg.pr.new/@heroui/calendar@5924

@heroui/card

npm i https://pkg.pr.new/@heroui/card@5924

@heroui/checkbox

npm i https://pkg.pr.new/@heroui/checkbox@5924

@heroui/chip

npm i https://pkg.pr.new/@heroui/chip@5924

@heroui/code

npm i https://pkg.pr.new/@heroui/code@5924

@heroui/date-input

npm i https://pkg.pr.new/@heroui/date-input@5924

@heroui/date-picker

npm i https://pkg.pr.new/@heroui/date-picker@5924

@heroui/divider

npm i https://pkg.pr.new/@heroui/divider@5924

@heroui/drawer

npm i https://pkg.pr.new/@heroui/drawer@5924

@heroui/dropdown

npm i https://pkg.pr.new/@heroui/dropdown@5924

@heroui/form

npm i https://pkg.pr.new/@heroui/form@5924

@heroui/image

npm i https://pkg.pr.new/@heroui/image@5924

@heroui/input

npm i https://pkg.pr.new/@heroui/input@5924

@heroui/input-otp

npm i https://pkg.pr.new/@heroui/input-otp@5924

@heroui/kbd

npm i https://pkg.pr.new/@heroui/kbd@5924

@heroui/link

npm i https://pkg.pr.new/@heroui/link@5924

@heroui/listbox

npm i https://pkg.pr.new/@heroui/listbox@5924

@heroui/menu

npm i https://pkg.pr.new/@heroui/menu@5924

@heroui/modal

npm i https://pkg.pr.new/@heroui/modal@5924

@heroui/navbar

npm i https://pkg.pr.new/@heroui/navbar@5924

@heroui/number-input

npm i https://pkg.pr.new/@heroui/number-input@5924

@heroui/pagination

npm i https://pkg.pr.new/@heroui/pagination@5924

@heroui/popover

npm i https://pkg.pr.new/@heroui/popover@5924

@heroui/progress

npm i https://pkg.pr.new/@heroui/progress@5924

@heroui/radio

npm i https://pkg.pr.new/@heroui/radio@5924

@heroui/ripple

npm i https://pkg.pr.new/@heroui/ripple@5924

@heroui/scroll-shadow

npm i https://pkg.pr.new/@heroui/scroll-shadow@5924

@heroui/select

npm i https://pkg.pr.new/@heroui/select@5924

@heroui/skeleton

npm i https://pkg.pr.new/@heroui/skeleton@5924

@heroui/slider

npm i https://pkg.pr.new/@heroui/slider@5924

@heroui/snippet

npm i https://pkg.pr.new/@heroui/snippet@5924

@heroui/spacer

npm i https://pkg.pr.new/@heroui/spacer@5924

@heroui/spinner

npm i https://pkg.pr.new/@heroui/spinner@5924

@heroui/switch

npm i https://pkg.pr.new/@heroui/switch@5924

@heroui/table

npm i https://pkg.pr.new/@heroui/table@5924

@heroui/tabs

npm i https://pkg.pr.new/@heroui/tabs@5924

@heroui/toast

npm i https://pkg.pr.new/@heroui/toast@5924

@heroui/tooltip

npm i https://pkg.pr.new/@heroui/tooltip@5924

@heroui/user

npm i https://pkg.pr.new/@heroui/user@5924

@heroui/react

npm i https://pkg.pr.new/@heroui/react@5924

@heroui/system

npm i https://pkg.pr.new/@heroui/system@5924

@heroui/system-rsc

npm i https://pkg.pr.new/@heroui/system-rsc@5924

@heroui/theme

npm i https://pkg.pr.new/@heroui/theme@5924

@heroui/use-aria-accordion

npm i https://pkg.pr.new/@heroui/use-aria-accordion@5924

@heroui/use-aria-accordion-item

npm i https://pkg.pr.new/@heroui/use-aria-accordion-item@5924

@heroui/use-aria-button

npm i https://pkg.pr.new/@heroui/use-aria-button@5924

@heroui/use-aria-link

npm i https://pkg.pr.new/@heroui/use-aria-link@5924

@heroui/use-aria-modal-overlay

npm i https://pkg.pr.new/@heroui/use-aria-modal-overlay@5924

@heroui/use-aria-multiselect

npm i https://pkg.pr.new/@heroui/use-aria-multiselect@5924

@heroui/use-aria-overlay

npm i https://pkg.pr.new/@heroui/use-aria-overlay@5924

@heroui/use-callback-ref

npm i https://pkg.pr.new/@heroui/use-callback-ref@5924

@heroui/use-clipboard

npm i https://pkg.pr.new/@heroui/use-clipboard@5924

@heroui/use-data-scroll-overflow

npm i https://pkg.pr.new/@heroui/use-data-scroll-overflow@5924

@heroui/use-disclosure

npm i https://pkg.pr.new/@heroui/use-disclosure@5924

@heroui/use-draggable

npm i https://pkg.pr.new/@heroui/use-draggable@5924

@heroui/use-form-reset

npm i https://pkg.pr.new/@heroui/use-form-reset@5924

@heroui/use-image

npm i https://pkg.pr.new/@heroui/use-image@5924

@heroui/use-infinite-scroll

npm i https://pkg.pr.new/@heroui/use-infinite-scroll@5924

@heroui/use-intersection-observer

npm i https://pkg.pr.new/@heroui/use-intersection-observer@5924

@heroui/use-is-mobile

npm i https://pkg.pr.new/@heroui/use-is-mobile@5924

@heroui/use-is-mounted

npm i https://pkg.pr.new/@heroui/use-is-mounted@5924

@heroui/use-measure

npm i https://pkg.pr.new/@heroui/use-measure@5924

@heroui/use-pagination

npm i https://pkg.pr.new/@heroui/use-pagination@5924

@heroui/use-real-shape

npm i https://pkg.pr.new/@heroui/use-real-shape@5924

@heroui/use-ref-state

npm i https://pkg.pr.new/@heroui/use-ref-state@5924

@heroui/use-resize

npm i https://pkg.pr.new/@heroui/use-resize@5924

@heroui/use-safe-layout-effect

npm i https://pkg.pr.new/@heroui/use-safe-layout-effect@5924

@heroui/use-scroll-position

npm i https://pkg.pr.new/@heroui/use-scroll-position@5924

@heroui/use-ssr

npm i https://pkg.pr.new/@heroui/use-ssr@5924

@heroui/use-theme

npm i https://pkg.pr.new/@heroui/use-theme@5924

@heroui/use-update-effect

npm i https://pkg.pr.new/@heroui/use-update-effect@5924

@heroui/use-viewport-size

npm i https://pkg.pr.new/@heroui/use-viewport-size@5924

@heroui/aria-utils

npm i https://pkg.pr.new/@heroui/aria-utils@5924

@heroui/dom-animation

npm i https://pkg.pr.new/@heroui/dom-animation@5924

@heroui/framer-utils

npm i https://pkg.pr.new/@heroui/framer-utils@5924

@heroui/react-rsc-utils

npm i https://pkg.pr.new/@heroui/react-rsc-utils@5924

@heroui/react-utils

npm i https://pkg.pr.new/@heroui/react-utils@5924

@heroui/shared-icons

npm i https://pkg.pr.new/@heroui/shared-icons@5924

@heroui/shared-utils

npm i https://pkg.pr.new/@heroui/shared-utils@5924

@heroui/stories-utils

npm i https://pkg.pr.new/@heroui/stories-utils@5924

@heroui/test-utils

npm i https://pkg.pr.new/@heroui/test-utils@5924

commit: d02b90c

@hasegawa-101 hasegawa-101 marked this pull request as ready for review November 21, 2025 14:10
@wingkwong wingkwong self-assigned this Nov 21, 2025
@wingkwong wingkwong added this to the v2.8.6 milestone Nov 21, 2025
@vercel
Copy link

vercel bot commented Nov 21, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
heroui Ready Ready Preview Comment Nov 21, 2025 2:30pm
heroui-sb Ready Ready Preview Comment Nov 21, 2025 2:30pm

@wingkwong wingkwong merged commit 5d9a05b into heroui-inc:canary Nov 22, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] - Vertical Tabs use incorrect aria-orientation and do not respond to Up/Down arrow keys

2 participants