Skip to content

feat: migrate main menu to mui#912

Open
santipalenque wants to merge 4 commits intomasterfrom
feature/migrate-menu-to-mui
Open

feat: migrate main menu to mui#912
santipalenque wants to merge 4 commits intomasterfrom
feature/migrate-menu-to-mui

Conversation

@santipalenque
Copy link
Copy Markdown

@santipalenque santipalenque commented May 4, 2026

https://app.clickup.com/t/86b9n80f4

Summary by CodeRabbit

  • New Features

    • Reusable expandable menu sections with header styling and default-open behavior for active groups.
    • Centralized menu data builders for global and summit-scoped navigation.
  • UI/Design Changes

    • Menu panel widened with white background, refined spacing and stronger header typography.
    • Nested entries shown as collapsible sublists; summit area presented as its own collapsible section.
  • Behavior

    • Simplified interaction: overlay-based close, route-driven selection, and improved nested selection highlighting.
  • Tests

    • Added unit tests covering menu rendering and navigation behavior.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: de39f087-6c39-4baa-b2ba-6002f0aaf0b3

📥 Commits

Reviewing files that changed from the base of the PR and between 371fab2 and c3d0a00.

📒 Files selected for processing (7)
  • src/components/menu/__tests__/menu.test.js
  • src/components/menu/expandable-item.js
  • src/components/menu/index.js
  • src/components/menu/menu-definition.js
  • src/components/menu/menu-item.js
  • src/components/menu/menu.module.less
  • src/components/menu/sub-menu-item.js

📝 Walkthrough

Walkthrough

Menu components refactored to Material UI, menu data moved to menu-definition.js, and a new ExpandableItem component added. The Menu now uses a single menuOpen state, route-aware selection via history.location.pathname, and renders nested subItems with expanded/collapsible sections.

Changes

Menu System Modernization

Layer / File(s) Summary
Data Shape
src/components/menu/menu-definition.js
Adds getGlobalItems() and getSummitItems(summitId) returning arrays of menu entries with name, linkUrl, optional accessRoute/exclusive, and nested subItems.
Foundational Component
src/components/menu/expandable-item.js
Adds ExpandableItem (default export): MUI ListItemButton with internal open state (initialized from defaultOpen), expand/collapse icon, and Collapse wrapping children (unmountOnExit); supports isHeader styling.
Core Rendering
src/components/menu/menu-item.js, src/components/menu/sub-menu-item.js
MenuItem now renders MUI ListItemButton/Typography, accepts nested and selected props for padding/styling and preserves exclusive wrapper. SubMenuItem accepts subItems and currentPath, filters by accessRoute, computes isChildActive, and renders nested MenuItems inside ExpandableItem with defaultOpen={isChildActive}.
Integration / Wiring
src/components/menu/index.js
Main Menu imports getGlobalItems/getSummitItems, consolidates to a single menuOpen boolean (removed per-submenu state and document click listeners), derives currentPath from history.location.pathname, closes via overlay/onItem click, and navigates with history.push('/app/' + url).
Styling
src/components/menu/menu.module.less
Open menu width changed to 260px; panel background switched to white with right border; legacy nested/submenu CSS simplified/removed to rely on MUI for presentation.
Tests
src/components/menu/__tests__/menu.test.js
Adds tests that mock i18n, routing, member model, and menu-definition; assert rendering of general/summit sections and navigation behavior on item click.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Menu as Menu (index.js)
    participant Exp as ExpandableItem
    participant Sub as SubMenuItem
    participant MI as MenuItem
    participant Router as history

    User->>Menu: open menu / click section
    Menu->>Exp: render section header with defaultOpen
    User->>Exp: click header
    Exp->>Exp: toggle open state / show Collapse
    Exp->>Sub: render children list
    User->>MI: click nested item
    MI->>Menu: onMenuItemClick(url)
    Menu->>Router: history.push('/app/' + url)
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇
I nudged the lists and fluffed each line,
I tucked old classes out of sight to shine,
I open, close, a tiny tidy art,
New menus bloom — a hop, a happy start.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat: migrate main menu to mui' directly and accurately describes the main change: migrating the menu component to Material UI.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/migrate-menu-to-mui

Comment @coderabbitai help to get the list of available commands and usage tips.

@santipalenque santipalenque changed the title chore: migrate menu to mui feat: migrate main menu to mui May 4, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/menu/expandable-item.js`:
- Line 14: The ExpandableItem component currently initializes state with
useState(defaultOpen) but never updates when the prop changes, so add an effect
to sync the local open state when the defaultOpen prop updates: in the
ExpandableItem component (where useState(defaultOpen) is used) import and use
useEffect to call setOpen(defaultOpen) whenever defaultOpen changes; apply the
same fix for the similar instance around lines 25-29 (the other
useState(defaultOpen) usage) so route-driven changes to defaultOpen
re-open/collapse the item as expected.

In `@src/components/menu/index.js`:
- Around line 33-35: Guard access to currentSummit before calling
getSummitItems: change the eager call const summitItems =
getSummitItems(currentSummit.id) to a safe conditional such as const summitItems
= currentSummit ? getSummitItems(currentSummit.id) : [] (or use
currentSummit?.id inside a conditional) so the function is not invoked when
currentSummit is null/undefined; apply the same guard to the other occurrence
that builds summit-related items (the block referenced around lines 96-103) to
prevent runtime errors before summit data is loaded.
- Around line 36-40: The menu currently only closes via navigation
(onMenuItemClick) or onMouseLeave, which leaves touch users stuck; create a
single closeMenu handler (e.g., function closeMenu() { setMenuOpen(false); })
and use it everywhere: replace direct setMenuOpen(false) in onMenuItemClick with
closeMenu, attach closeMenu to the burger toggle's close action, add a backdrop
element with onClick/onTouchStart={closeMenu} to detect taps outside, and add
onTouchStart/onClick={closeMenu} to the explicit close button or drawer header;
also keep onMouseLeave as-is. Update references: onMenuItemClick, setMenuOpen,
history.push, and the burger toggle/button and any backdrop/drawer components
shown around lines 36 and 77-89.
- Around line 17-24: The project is using MUI v6 imports (e.g., Box, Divider,
IconButton from "@mui/material" in src/components/menu/index.js) while your
React version is 16.13.1 and thus incompatible; fix by either upgrading React
and ReactDOM in package.json to ^17.0.0 (or ^18/^19) and running npm/yarn
install and rebuilding, or pinning `@mui/material` to a v5 compatible release
(downgrade MUI in package.json) and reinstalling; after changing, verify
peerDependencies, run the app/tests, and update any MUI v6-specific APIs in
components like SubMenuItem, MenuItem, ExpandableItem if you upgrade/downgrade.

In `@src/components/menu/sub-menu-item.js`:
- Around line 20-24: The submenu component is creating an accordion even when
all children are filtered out; after computing const _subItems =
subItems.filter(...) in sub-menu-item.js, guard against an empty list by not
rendering the parent group when _subItems.length === 0 (i.e., return null / skip
render for the SubMenuItem/RenderSubMenu function). Apply the same empty-check
in the other related block (the alternative rendering branch around lines 30-45)
so parent menu groups with no visible children are not shown.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 82f333a7-3997-405f-9e7e-bd2a32e8abae

📥 Commits

Reviewing files that changed from the base of the PR and between 08e2650 and 67ca2ea.

📒 Files selected for processing (6)
  • src/components/menu/expandable-item.js
  • src/components/menu/index.js
  • src/components/menu/menu-definition.js
  • src/components/menu/menu-item.js
  • src/components/menu/menu.module.less
  • src/components/menu/sub-menu-item.js

* limitations under the License.
* */

import React, { useState } from "react";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Sync open when defaultOpen changes.

defaultOpen is route-derived in src/components/menu/sub-menu-item.js:26-33, but useState(defaultOpen) only applies on the first mount. After navigation, the active section can stay collapsed because this component never re-reads the updated prop.

Suggested fix
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
@@
   const [open, setOpen] = useState(defaultOpen);
+
+  useEffect(() => {
+    setOpen(defaultOpen);
+  }, [defaultOpen]);

Also applies to: 25-29

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/menu/expandable-item.js` at line 14, The ExpandableItem
component currently initializes state with useState(defaultOpen) but never
updates when the prop changes, so add an effect to sync the local open state
when the defaultOpen prop updates: in the ExpandableItem component (where
useState(defaultOpen) is used) import and use useEffect to call
setOpen(defaultOpen) whenever defaultOpen changes; apply the same fix for the
similar instance around lines 25-29 (the other useState(defaultOpen) usage) so
route-driven changes to defaultOpen re-open/collapse the item as expected.

Comment on lines +17 to +24
import Box from "@mui/material/Box";
import Divider from "@mui/material/Divider";
import IconButton from "@mui/material/IconButton";
import MenuIcon from "@mui/icons-material/Menu";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import SubMenuItem from "./sub-menu-item";
import MenuItem from "./menu-item";
import ExpandableItem from "./expandable-item";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

🧩 Analysis chain

🌐 Web query:

What are the peer dependency requirements for @mui/material6.4.3 and@mui/icons-material 6.4.3, and do they support React 16.13.1?

💡 Result:

The peer dependency requirements for @mui/material 6.4.3 and @mui/icons-material 6.4.3 are react (^17.0.0 || ^18.0.0 || ^19.0.0) and react-dom (^17.0.0 || ^18.0.0 || ^19.0.0). @mui/icons-material also has a peer dependency on @mui/material ^6.0.0 (matching the version series). They do not support React 16.13.1, as MUI v6 requires React ^17.0.0 or higher. React 16 support was dropped starting with v6; previous versions (v5) supported React >=16.8.0.

Citations:


Upgrade React to ^17.0.0 or higher before using MUI v6.

@mui/material 6.4.3 requires React ^17.0.0, ^18.0.0, or ^19.0.0 and does not support React 16.13.1. MUI v6 dropped React 16 support entirely. Either downgrade MUI to v5 (which supports React >=16.8.0) or upgrade your React version to at least 17.0.0. This is a blocking dependency incompatibility.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/menu/index.js` around lines 17 - 24, The project is using MUI
v6 imports (e.g., Box, Divider, IconButton from "@mui/material" in
src/components/menu/index.js) while your React version is 16.13.1 and thus
incompatible; fix by either upgrading React and ReactDOM in package.json to
^17.0.0 (or ^18/^19) and running npm/yarn install and rebuilding, or pinning
`@mui/material` to a v5 compatible release (downgrade MUI in package.json) and
reinstalling; after changing, verify peerDependencies, run the app/tests, and
update any MUI v6-specific APIs in components like SubMenuItem, MenuItem,
ExpandableItem if you upgrade/downgrade.

Comment thread src/components/menu/index.js
Comment thread src/components/menu/index.js
Comment thread src/components/menu/sub-menu-item.js
@santipalenque santipalenque force-pushed the feature/migrate-menu-to-mui branch from fb14a4f to 371fab2 Compare May 4, 2026 19:00
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/components/menu/index.js (1)

90-94: ⚡ Quick win

Add aria-label to the menu toggle button for accessibility.

The burger button lacks an accessible label for screen readers. Users relying on assistive technology won't understand the button's purpose.

♿ Suggested fix
         <IconButton
           onClick={() => (menuOpen ? closeMenu() : setMenuOpen(true))}
+          aria-label={menuOpen ? "Close menu" : "Open menu"}
         >
           <MenuIcon sx={{ fontSize: "2.5rem", color: "#555555" }} />
         </IconButton>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/menu/index.js` around lines 90 - 94, The IconButton used as
the menu toggle lacks an accessible label; update the IconButton element (the
one rendering MenuIcon and using menuOpen / closeMenu / setMenuOpen) to include
an aria-label that reflects state, e.g. aria-label={menuOpen ? 'Close menu' :
'Open menu'} so screen readers convey the button purpose (optionally also add
aria-expanded={menuOpen} for state announcement).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/components/menu/index.js`:
- Around line 90-94: The IconButton used as the menu toggle lacks an accessible
label; update the IconButton element (the one rendering MenuIcon and using
menuOpen / closeMenu / setMenuOpen) to include an aria-label that reflects
state, e.g. aria-label={menuOpen ? 'Close menu' : 'Open menu'} so screen readers
convey the button purpose (optionally also add aria-expanded={menuOpen} for
state announcement).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e5d05f8-1f06-4b46-8d0b-0366d1cc14da

📥 Commits

Reviewing files that changed from the base of the PR and between d49db3b and fb14a4f.

📒 Files selected for processing (2)
  • src/components/menu/index.js
  • src/components/menu/sub-menu-item.js

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/menu/menu-definition.js`:
- Around line 140-144: The menu entry uses kebab-case ("attendee-list") while
all other menu.name values use snake_case, which breaks i18n lookups via
T.translate(`menu.${name}`); update the menu item's name property to use
snake_case (e.g., change the "name" value to "attendee_list") in the
menu-definition.js entry for the attendees route and verify any references to
that name (translation keys and tests) are updated to match the new key.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: aba29a2a-2583-4c93-b092-32f0938e7825

📥 Commits

Reviewing files that changed from the base of the PR and between fb14a4f and 371fab2.

📒 Files selected for processing (6)
  • src/components/menu/expandable-item.js
  • src/components/menu/index.js
  • src/components/menu/menu-definition.js
  • src/components/menu/menu-item.js
  • src/components/menu/menu.module.less
  • src/components/menu/sub-menu-item.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/menu/expandable-item.js
  • src/components/menu/sub-menu-item.js
  • src/components/menu/index.js

Comment on lines +140 to +144
{
name: "attendee-list",
linkUrl: `summits/${summitId}/attendees`,
accessRoute: "attendees"
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent naming convention: attendee-list uses kebab-case.

All other name values use snake_case (e.g., speaker_list, badge_checkin, ticket_list), but this one uses kebab-case. Since name is used for i18n translation lookups via T.translate(\menu.${name}`)`, this inconsistency may require a separate translation key or could indicate a typo.

Proposed fix
      {
-       name: "attendee-list",
+       name: "attendee_list",
        linkUrl: `summits/${summitId}/attendees`,
        accessRoute: "attendees"
      },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
name: "attendee-list",
linkUrl: `summits/${summitId}/attendees`,
accessRoute: "attendees"
},
{
name: "attendee_list",
linkUrl: `summits/${summitId}/attendees`,
accessRoute: "attendees"
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/menu/menu-definition.js` around lines 140 - 144, The menu
entry uses kebab-case ("attendee-list") while all other menu.name values use
snake_case, which breaks i18n lookups via T.translate(`menu.${name}`); update
the menu item's name property to use snake_case (e.g., change the "name" value
to "attendee_list") in the menu-definition.js entry for the attendees route and
verify any references to that name (translation keys and tests) are updated to
match the new key.

@santipalenque santipalenque force-pushed the feature/migrate-menu-to-mui branch from 371fab2 to c3d0a00 Compare May 6, 2026 18:53
@santipalenque santipalenque requested a review from smarcet May 6, 2026 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant