-
Notifications
You must be signed in to change notification settings - Fork 2
✨ Add exact matching prop to sidebar menu items #1191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for exact URL matching in sidebar menu items to address issues where parent menu items become incorrectly active when viewing nested pages. The feature allows developers to configure whether each menu item should match URLs exactly or partially (the default behavior for backward compatibility).
Key changes:
- Added optional
exactboolean property to sidebar menu item types with documentation - Exported
isExactUrlutility function for use in menu item components - Updated
BasicMenuItemandCollapsableMenuItemto conditionally use exact or partial URL matching based on theexactprop
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/atoms/types/SideBar.ts |
Added optional exact property to SideBarMenuItemBase interface with JSDoc documentation |
src/organisms/SideBar/MenuItem/MenuItem.utils.ts |
Exported existing isExactUrl function to make it available for component use |
src/organisms/SideBar/MenuItem/BasicMenuItem.tsx |
Implemented conditional logic to use exact or partial URL matching based on the exact prop |
src/organisms/SideBar/MenuItem/CollapsableMenuItem.tsx |
Updated parent active state determination to respect child items' exact property |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| const isExactUrl = ({ currentUrl, link }: IsUrlArgs) => { | ||
| export const isExactUrl = ({ currentUrl, link }: IsUrlArgs) => { | ||
| const currentWithoutParams = currentUrl.split('?')[0]; |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The isExactUrl function doesn't decode the URL like isCurrentUrl does (line 7), which could lead to inconsistent behavior when comparing encoded vs. non-encoded URLs.
Consider applying the same decoding:
export const isExactUrl = ({ currentUrl, link }: IsUrlArgs) => {
const decodedCurrentUrl = decodeURIComponent(currentUrl);
const currentWithoutParams = decodedCurrentUrl.split('?')[0];
return currentWithoutParams === link;
};| const currentWithoutParams = currentUrl.split('?')[0]; | |
| const decodedCurrentUrl = decodeURIComponent(currentUrl); | |
| const currentWithoutParams = decodedCurrentUrl.split('?')[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this is correct, i wasn't sure if reusing the internal isExactUrl was the proper way to do this functionality, unsure if i do this suggestion I might break something. What do you think @mariush2 @aslakihle?
Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export const isExactUrl = ({ currentUrl, link }: IsUrlArgs) => { | ||
| const currentWithoutParams = currentUrl.split('?')[0]; | ||
| return currentWithoutParams === link; |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The newly exported isExactUrl function lacks test coverage. Since there are existing tests in MenuItem.utils.test.ts for similar utility functions, consider adding tests for isExactUrl to cover scenarios like:
- Exact URL match
- URL with query parameters (should match when params are stripped)
- URL mismatch
- Edge cases with trailing slashes
| const isActive = exact | ||
| ? isExactUrl({ | ||
| currentUrl: pathname, | ||
| link, | ||
| }) | ||
| : isCurrentUrl({ | ||
| currentUrl: pathname, | ||
| link, | ||
| }); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new exact prop behavior in BasicMenuItem lacks test coverage. Since there are comprehensive tests for MenuItem in MenuItem.test.tsx, consider adding tests to verify:
- Menu item is active only when URL exactly matches (when
exact=true) - Menu item is active with partial match (when
exact=falseorundefined) - Navigation behavior with
exactprop in different URL scenarios
| const isActive = items.some((item) => | ||
| isCurrentUrl({ currentUrl: pathname, link: item.link }) | ||
| item.exact | ||
| ? isExactUrl({ currentUrl: pathname, link: item.link }) | ||
| : isCurrentUrl({ currentUrl: pathname, link: item.link }) | ||
| ); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new exact prop behavior in CollapsableMenuItem lacks test coverage. Since there are comprehensive tests for menu items in the test files, consider adding tests to verify:
- Parent item's active state respects child items'
exactproperty - Multiple child items with different
exactsettings are handled correctly
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export const isExactUrl = ({ currentUrl, link }: IsUrlArgs) => { | ||
| const currentWithoutParams = currentUrl.split('?')[0]; | ||
| return currentWithoutParams === link; | ||
| }; |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new exact property functionality lacks test coverage. While tests exist for other functionality in this file (e.g., isCurrentUrl, canNavigate), there are no tests for the newly exported isExactUrl function.
Consider adding tests to verify:
- Exact URL matching works correctly
- Query parameters are properly stripped before comparison
- The function handles edge cases (e.g., trailing slashes, encoded characters)
|
@mariush2 @aslakihle The menu item already includes a
For the following two interpretations, it depends on how we want menu items to behave:
Given that, perhaps this PR should change and explicitly address this decision point by allowing applications to configure which interpretation they want. At the same time, we may want to clarify and document the intention of the existing |
|
@yunarch |
Description
This PR adds support for configuring sidebar menu items to match their links either exactly or partially (the current behavior).
Problem
Currently, a menu item is considered active if its link is included anywhere in the current URL. This results in overly broad matches. For example, consider the following menu item links:
With the existing behavior and:
All menu items above would be marked as active because each item's link is a substring of the current URL. This leads to multiple items being highlighted when only the most specific one (
menuItem4) should be active, at least for this case.Why this matters
When a menu item is active, clicking it does not trigger navigation (which is correct). However, being “inside” a menu item's path does not always mean that the item itself should be marked active.
For example, imagine a sidebar with a single
Projectsmenu item that leads to a list of all projects. A user might navigate deep into a specific project’s pages and then want to return to the mainProjectspage by clicking the sidebar item. With the current behavior, because all deeper project pages share the/projectsprefix, theProjectsitem becomes active even while viewing a specific project. This makes it impossible for the user to navigate back using the sidebar, since clicking an already-active item does nothing.To work around this today, the only option would be to change the URL structure so each section uses different prefixes, such as:
But this forces URLs into unnatural or inconsistent patterns solely to avoid the matching issue, and breaks the idea of meaningful, hierarchical deep linking.
What This PR Changes
This PR introduces a configuration option that allows each menu item to define how it should be matched against the current URL:
This gives developers fine-grained control over how active states are determined and prevents sidebar items from being incorrectly highlighted or becoming unusable due to prefix-based collisions.