-
Notifications
You must be signed in to change notification settings - Fork 655
feat(navigation): add pinning for sidebar menu items #4729
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: next
Are you sure you want to change the base?
feat(navigation): add pinning for sidebar menu items #4729
Conversation
Introduced ability to pin/unpin sidebar menu items in admin UI navigation. Added PinnableMenuItem and PinnedMenuItems components. Updated MenuConfig and related components to support the `pinnable` property. Enabled pinning for CMS content models and groups. Updated Properties to handle `pinnable` attribute. Refs: WEB-5364
Renamed the variable pinnableItems to pinnableStates for clarity and consistency in the PinnedMenuItems component. This improves code readability by better reflecting the data structure's purpose.
Pin icon in menu items is now visible on hover or when the item is pinned. Pinned menu items are rendered with PinnableMenuItem for consistent UX. Refs: WEB-5364
Remove unused PinOffIcon and always display PinIcon for pinnable menu items. Add detailed JSDoc to PinnableMenuItem for improved developer clarity. The pin/unpin action now uses a single icon, streamlining UI consistency. Refs: WEB-5364
Refactored PinnedMenuItems to optimize filtering and rendering of pinned menu items. Now uses useMemo for pinnable menus and keys, and only renders the "Pinned" group if there are pinned items. Enhanced documentation and clarified prop usage. This improves performance and code readability. Refs: WEB-5364
Added the `pinnable={true}` prop to various settings-related `Menu` components across multiple modules. This enables users to pin these menu items for easier access and improved navigation within the admin interface. Refs: WEB-5364
Refactored pinnable menu item logic to store both pinned state and order in localStorage. Added hooks and utility functions for managing pinned menu items and their order. Updated PinnedMenuItems to display pinned items in user-defined order. Improved documentation and code clarity. Refs: WEB-5364
Added a new Menu.Group labeled "Webiny" to the PinnedMenuItems component. This provides a dedicated section for Webiny-related menu items in the admin UI navigation, improving organization and clarity for users. Refs: WEB-5364
Added with fca3d7b |
Based on the last video, you're missing the icon on the pinned entries. Every entry that's pinned should have an icon. The icon you need to use it the icon from the parent group where that entry is placed. |
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.
Just a tiny change on exported function name, and we're good to go 👍
* @param name - The unique name of the menu item. | ||
* @returns The localStorage key string for the pinned state. | ||
*/ | ||
export const PINNED_KEY = (name: string) => `navigation/${name}/pinned`; |
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.
This type of case is reserved for constants, like you have PINNED_ORDER_KEY
later in the code. If it's a function, export it as createPinnedKey
or getPinnedKey
. You could even go as far as calling it usePinnedKey
, name it as a hook, which will make the code very easy to read later where you use this.
* <PinnedMenuItems menuItems={menus} /> | ||
*/ | ||
export const PinnedMenuItems = ({ menuItems }: PinnedMenuItemsProps) => { | ||
const pinnableMenus = useMemo(() => getPinnableMenus(menuItems), [menuItems]); |
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.
I would say that most of these useMemo are not necessary. You can just get everything you need inside last useMemo
(pinnedItems
).
What you cant get inside of that useMemo (local storage), fetch outside.
Pinned menu items now display the icon of their parent menu, improving visual consistency and navigation clarity. Added logic to extract and render parent icons in the pinned section.
Removes the `icon` prop from `PinnableMenuItem` and instead passes the icon directly to the menu element via `React.cloneElement`. This simplifies the component API and ensures icons are handled consistently within menu items.
Ensure that the menu item's element is always defined before cloning it. This prevents runtime errors when rendering pinned menu items with missing elements. The non-null assertion improves type safety and UI stability.
Pinned menu items and their groups are now hidden when the sidebar is not pinned. The pin icon's visibility also depends on both the menu item's and sidebar's pinned state, improving UI consistency.
Renamed the PINNED_KEY function to pinnedKey in PinnableMenuItem and updated all references in related files for consistency. This improves naming conventions and code readability in the navigation components.
Pinned menu items now sort with missing items placed at the end, preventing incorrect ordering when items are not found in the pinned order array. Removed unnecessary useMemo for pinnableMenus and pinnableKeys to simplify component logic.
* @returns The localStorage key string for the pinned state. | ||
*/ | ||
export const PINNED_KEY = (name: string) => `navigation/${name}/pinned`; | ||
export const pinnedKey = (name: string) => `navigation/${name}/pinned`; |
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.
const key = createPinnedKey(whatever)
Refactored PinnedMenuItems to memoize pinnableMenus, pinnableKeys, and pinnedOrder together, reducing redundant computations and improving performance. This change ensures dependencies are managed efficiently and state updates are more predictable.
Refactored sidebar state variable from `pinned` to `expanded` in navigation components for improved clarity. Updated related conditional rendering and class logic to use the new naming convention.
Renamed the `pinnedKey` function to `createPinnedKey` in navigation components for improved clarity and consistency. Updated all references in related files. No functional changes were made.
Feature: Pinned Navigation Items
Related JIRA Story: WEB-5364
Summary
This PR introduces the ability for users to pin and unpin navigation menu items to a personalized "Pinned" section at the top of the sidebar.
The feature improves navigation efficiency, supports persistent user preferences, and provides clear visual feedback for pin and unpin actions.
SCREENSHOTS
Changes
Pin / Unpin functionality
Pinned Section
Persistence
UI & Feedback
Implementation Details
How to Test
The item should appear in the pinned section at the top.
Pinned items should remain visible.
The item should be removed from the pinned section but remain in its original location.
Out of Scope
Checklist