fix(tabs): honor hash-linked nav tabs#12303
fix(tabs): honor hash-linked nav tabs#12303tarunvashishth wants to merge 2 commits intopatternfly:mainfrom
Conversation
WalkthroughDerives an initial active tab from the URL hash for nav-style Tabs by parsing each tab's Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
Preview: https://pf-react-pr-12303.surge.sh A11y report: https://pf-react-pr-12303-a11y.surge.sh |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/react-core/src/components/Tabs/Tabs.tsx`:
- Around line 194-198: Seed the uncontrolledActiveKey state using the
hash-derived key so initial selection matches shownKeys: set
uncontrolledActiveKey to hashActiveKey ?? this.props.defaultActiveKey (mirroring
shownKeys logic that uses hashActiveKey ?? ...). Update the initializer that
defines uncontrolledActiveKey in the Tabs component so it references
hashActiveKey, and ensure any later render-time hash derivation logic is removed
or not used to override user interactions after mount (preserve user changes to
uncontrolledActiveKey afterwards).
- Around line 145-156: Tests are missing for getTabHashActiveKey to verify
hash-based selection; add unit tests in the Tabs spec that set
window.location.hash (use a beforeEach to assign a hash and afterEach to clear
it) and assert getTabHashActiveKey (via rendering Tabs or importing the function
if exported) returns the expected eventKey when a child TabElement has matching
href, and does not return keys for hidden/disabled tabs or when component/isNav
conditions are unmet; target the getTabHashActiveKey logic and exercise
Tabs/TabsProps behavior with TabElement props (href, isHidden, isDisabled,
isAriaDisabled) so hash-based navigation is covered.
- Around line 559-560: The code currently recalculates hashActiveKey each render
(getTabHashActiveKey) and then uses it to set localActiveKey, which causes the
URL hash to override user clicks; instead, remove the per-render usage of
getTabHashActiveKey and seed uncontrolledActiveKey from the hash only on initial
mount/constructor (where you already compute it around line ~186), or use the
existing initial shownKeys/uncontrolledActiveKey initialization to incorporate
the hash-derived key; update Tabs constructor/initialization to set
uncontrolledActiveKey from getTabHashActiveKey once and ensure handleTabClick
updates uncontrolledActiveKey (not the URL hash) so subsequent renders respect
the user's selection rather than recomputing hashActiveKey each render.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3544653a-d87d-4a92-8b53-8011dd08fcc6
📒 Files selected for processing (1)
packages/react-core/src/components/Tabs/Tabs.tsx
| const getTabHashActiveKey = ({ children, component, isNav }: Pick<TabsProps, 'children' | 'component' | 'isNav'>) => { | ||
| if (!canUseDOM || !(component === TabsComponent.nav || isNav) || !window.location.hash) { | ||
| return undefined; | ||
| } | ||
|
|
||
| return Children.toArray(children) | ||
| .filter((child): child is TabElement => isValidElement(child)) | ||
| .filter(({ props }) => !props.isHidden) | ||
| .find( | ||
| ({ props }) => !props.isDisabled && !props.isAriaDisabled && getHashFromHref(props.href) === window.location.hash | ||
| )?.props.eventKey; | ||
| }; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if Tabs tests have any hash-related setup
rg -n "location.hash|window.location" packages/react-core/src/components/Tabs/__tests__/Repository: patternfly/patternfly-react
Length of output: 53
Add test coverage for the getTabHashActiveKey function with hash-based navigation.
The new getTabHashActiveKey function accesses window.location.hash and should be tested to ensure the hash-based tab selection works correctly and prevent regressions. Currently, no hash-related test setup exists in the Tabs tests, while the Nav component tests demonstrate the pattern with window.location.hash setup in a beforeEach block.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/react-core/src/components/Tabs/Tabs.tsx` around lines 145 - 156,
Tests are missing for getTabHashActiveKey to verify hash-based selection; add
unit tests in the Tabs spec that set window.location.hash (use a beforeEach to
assign a hash and afterEach to clear it) and assert getTabHashActiveKey (via
rendering Tabs or importing the function if exported) returns the expected
eventKey when a child TabElement has matching href, and does not return keys for
hidden/disabled tabs or when component/isNav conditions are unmet; target the
getTabHashActiveKey logic and exercise Tabs/TabsProps behavior with TabElement
props (href, isHidden, isDisabled, isAriaDisabled) so hash-based navigation is
covered.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/react-core/src/components/Tabs/__tests__/Tabs.test.tsx (1)
122-129: Restore previous hash instead of forcing empty cleanup.Line 128 always sets
window.location.hash = ''. Prefer restoring the pre-test value for better isolation if surrounding tests ever rely on a non-empty hash.♻️ Suggested tweak
describe('hash-based nav selection', () => { + let previousHash = ''; + beforeEach(() => { + previousHash = window.location.hash; window.location.hash = '#/items/2'; }); afterEach(() => { - window.location.hash = ''; + window.location.hash = previousHash; });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/react-core/src/components/Tabs/__tests__/Tabs.test.tsx` around lines 122 - 129, The afterEach cleanup currently forces window.location.hash = '' which can break other tests; capture the original hash in the beforeEach (e.g., store it in a local variable like originalHash) and in afterEach restore window.location.hash = originalHash so the test suite returns the location state to what it was; update the beforeEach/afterEach surrounding the describe('hash-based nav selection') block to use that stored value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/react-core/src/components/Tabs/__tests__/Tabs.test.tsx`:
- Around line 122-129: The afterEach cleanup currently forces
window.location.hash = '' which can break other tests; capture the original hash
in the beforeEach (e.g., store it in a local variable like originalHash) and in
afterEach restore window.location.hash = originalHash so the test suite returns
the location state to what it was; update the beforeEach/afterEach surrounding
the describe('hash-based nav selection') block to use that stored value.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2c4b6d9f-e34c-4693-9b87-f4036d496206
📒 Files selected for processing (2)
packages/react-core/src/components/Tabs/Tabs.tsxpackages/react-core/src/components/Tabs/__tests__/Tabs.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/react-core/src/components/Tabs/Tabs.tsx
Closes #12094
Summary by CodeRabbit