feat(ui-tabs,ui-view): add roving tabindex and manual activation mode - #2723
Open
git-nandor wants to merge 1 commit into
Open
git-nandor wants to merge 1 commit into
git-nandor wants to merge 1 commit into
Conversation
Unselected tabs had no tabindex, so keyboard focus relied on the Focusable wrapper. This also made arrow navigation depend on an unstable render prop. Use a proper roving tabindex: one tab gets tabindex="0", the rest -1. Track focus per tab, move it explicitly, and keep the roving tabindex in sync, falling back to the selected tab when focus leaves the tablist. Add activationMode="manual": arrow keys, Home, and End move focus; Enter or Space selects. This also provides a reliable way to select tabs in VoiceOver, which reserves arrow keys for its cursor. Add Home/End support, RTL-aware arrow navigation, and aria-selected="false" for unselected tabs. Add isTabbable and onFocus to Tabs.Tab, plus shouldUseFocusVisible to View to prevent focus rings on mouse clicks. The DOM output changes: unselected tabs now render tabindex="-1" instead of no attribute, and aria-selected="false" instead of no attribute. Selectors that test for the absence of those attributes need updating. INSTUI-5181 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Contributor
|
Contributor
Visual regression reportCypress suite: ✅ Passing Visual diff:
Accessibility (axe): ✅ No violations. 📊 View full report — click a screenshot's ⚠ badge to see each violation boxed on the image, with the offending element named and contrast failures shown as color swatches. Baselines come from the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
tabindex="0"at a time, tracked per tab node instead of via aFocusablewrapper.activationMode="manual", so arrow keys move focus without changing selection until Enter or Space is pressed (for screen readers that reserve arrow keys for their own cursor).aria-orientationandaria-selected="false"on unselected tabs to match the WAI-ARIA tabs pattern.shouldUseFocusVisibleonView(passes:focus-visiblethrough to the already-existingcustomCSSSelector), so the roving tabindex doesn't make a mouse click paint a focus ring. No-op for every existingViewconsumer.DOM output changes: unselected tabs render
tabindex="-1"andaria-selected="false"instead of omitting both attributes. Selectors asserting their absence need updating.Test Plan
activationMode="manual"— the acceptance criterion for the ticket and not coverable by CI: arrow through the strip, confirm Enter and Space select.tabOverflow="scroll"in manual mode — arrow to an off-screen tab and confirm it scrolls out from under the fade overlay.Fixes INSTUI-5181
🤖 Generated with Claude Code