Repository navigation
fix: recover uncontrolled selection when a tab becomes disabled - #10702
Shubham-Padkonde wants to merge 3 commits into
Conversation
|
One case I noticed while trying this out: when every tab becomes disabled after mount, the selection moves to the first tab and // uncontrolled, defaultSelectedKey="tests"
// rerender with disabledKeys={['logs', 'tests', 'artifacts']}
// main: Tests stays selected, onSelectionChange isn't called
// this branch: Logs is selected, onSelectionChange('logs')
// rerender with disabledKeys={[]}
// main: Tests
// this branch: LogsDisabling the whole list with
|
Related to #10633 (the uncontrolled-selection case).
When an uncontrolled Tabs selection becomes disabled, keep an enabled tab selected so keyboard users can still enter the tab list. The existing fallback already handles removed items and empty selection; this extends it to disabled items and tracks pending fallback transitions so collection re-renders do not notify twice before the new selection commits. Controlled selection remains the application's responsibility.
The regression tests exercise disabledKeys and per-item isDisabled, focus inside and outside the tab list, re-enabling an initially all-disabled list, repeated fallback changes, immediate disabling from onSelectionChange, and controlled selection. A Storybook example makes the dynamic disabling behavior reproducible. This change was prepared with Codex assistance.
✅ Pull Request Checklist:
📝 Test Instructions:
Run
yarn testandyarn test:ssr.In the React Aria Components Tabs
DisableSelectedTabstory, select Artifacts and press Re-run build. Logs should become selected. Pressing Tab from the button should focus Logs. The automated tests also cover disabling the focused tab, where focus should move to the enabled replacement.Full local validation on Windows / Node 24.15:
yarn test --maxWorkers=4: 379 suites passed, four failed; 8,080 tests passed, 16 failed, 16 skipped; all 262 snapshots passed. The same four failing suites and 16 failures reproduce with all three changed files restored to the base commit: NumberField, NumberParser, the S1-to-S2 CLI end-to-end tests, and LocalesResolver.yarn test:ssr: 57 suites passed, three failed (69 tests passed, five failed). Table, ListBox, and Calendar SSR tests timed out in the final local run. These SSR failures have not been isolated against the base commit; the previous published commit passed all SSR jobs in CircleCI.yarn lint: formatting, oxlint, workspace constraints, and package checks passed. Type checking reports Color.test.tsx:266 (TS2345), which also reproduces on unchanged source.The new regressions failed before the implementation change and pass afterward. The React 18 CI failure was reproduced locally as duplicate onSelectionChange events and addressed by tracking pending fallback transitions. The complete Tabs suite passes with both React 18 and React 19, including repeated transitions and immediate disabling of a newly selected tab. Automated mouse/keyboard and disabled/empty-state behavior is covered. Manual browser, touch, screen reader, RTL, theme, and zoom checks have not been performed.
🧢 Your Project:
Independent contribution addressing the existing issue; no production-project claim.