Skip to content

[navigation menu] Add keepMounted prop to Content part#3794

Merged
atomiks merged 2 commits intomui:masterfrom
atomiks:fix/navigation-menu-ssr
Feb 3, 2026
Merged

[navigation menu] Add keepMounted prop to Content part#3794
atomiks merged 2 commits intomui:masterfrom
atomiks:fix/navigation-menu-ssr

Conversation

@atomiks
Copy link
Copy Markdown
Contributor

@atomiks atomiks commented Jan 20, 2026

Closes #3755

<NavigationMenu.Content keepMounted> will keep the content mounted in the DOM with a hidden attribute during SSR and after hydration - this ensures the content is crawlable. Whenever it should be inserted into the popup, the component moves in there permanently, and stays mounted inside. <NavigationMenu.Portal keepMounted> needs to be used for it to "stay" on the DOM after it gets moved.

@atomiks atomiks added the component: navigation menu Changes related to the navigation menu component. label Jan 20, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jan 20, 2026

commit: da85a35

@mui-bot
Copy link
Copy Markdown

mui-bot commented Jan 20, 2026

Bundle size report

Bundle Parsed size Gzip size
@base-ui/react 🔺+182B(+0.04%) 🔺+61B(+0.05%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@netlify
Copy link
Copy Markdown

netlify Bot commented Jan 20, 2026

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit da85a35
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/698164fdc08cd80009edd311
😎 Deploy Preview https://deploy-preview-3794--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@atomiks atomiks force-pushed the fix/navigation-menu-ssr branch from eb4920e to f87bf7e Compare January 20, 2026 01:14
@atomiks atomiks marked this pull request as ready for review January 20, 2026 01:17
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jan 20, 2026

Greptile Overview

Greptile Summary

Adds keepMounted prop to <NavigationMenu.Content> to keep content in the DOM with a hidden attribute during SSR and when closed, ensuring web crawler accessibility. When the popup opens, the content is reparented into the portal container.

  • Added keepMounted prop (default false) to NavigationMenuContent component
  • Content renders inline with hidden attribute when keepMounted=true and not mounted/no portal container
  • Content moves to portal when popup opens and portal container exists
  • Comprehensive test coverage for SSR and client-side hydration scenarios
  • Documentation updated in API reference and component pages

Confidence Score: 4/5

  • safe to merge after addressing the missing refs issue
  • implementation is solid with good test coverage, but the inline rendering path is missing forwardedRef which could break ref forwarding for parent components
  • packages/react/src/navigation-menu/content/NavigationMenuContent.tsx needs the refs fix

Important Files Changed

Filename Overview
packages/react/src/navigation-menu/content/NavigationMenuContent.tsx Added keepMounted prop to render content with hidden attribute during SSR and when closed, ensuring crawlability. Content is portaled when mounted and has a portal container.
packages/react/src/navigation-menu/content/NavigationMenuContent.test.tsx Added comprehensive tests for keepMounted prop covering SSR and client-side hydration scenarios.

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread packages/react/src/navigation-menu/content/NavigationMenuContent.tsx Outdated
@michaldudak
Copy link
Copy Markdown
Member

I'd make this opt-in to avoid potential performance hits. With it enabled by default, the initial payload received from the server is larger. The browser also adds these elements to the DOM just to remove them a split-second later. It doesn't have to lay out or paint, so it's not a huge issue, but memory will be allocated, increasing the GC pressure.

@atomiks
Copy link
Copy Markdown
Contributor Author

atomiks commented Jan 28, 2026

@michaldudak yeah good point, I figured navigation menus should always be mounted for SEO, but we can keep it opt-in with keepMounted specified on Root and possibly on Content as well to let them opt-out for specific menus if they're expensive and not critical for SEO

Alternatively (and this actually is probably necessary), we could keep the mounted content in the DOM at all times, since Google might re-evaluate contents after hydration finishes.

@atomiks atomiks force-pushed the fix/navigation-menu-ssr branch 4 times, most recently from a26220e to 2c25435 Compare January 28, 2026 22:34
Comment thread packages/react/src/navigation-menu/content/NavigationMenuContent.tsx Outdated
@atomiks atomiks changed the title [navigation menu] Mount content as hidden before hydration [navigation menu] Add keepMounted prop to Content part Jan 30, 2026
portalContainer,
);

if (keepMounted) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A comment explaining what's going on here could be useful for future readers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I removed the clone approach to be simpler

@atomiks atomiks force-pushed the fix/navigation-menu-ssr branch from 9caaf09 to 9d6a90b Compare February 3, 2026 02:00
@atomiks atomiks added the type: new feature Expand the scope of the product to solve a new problem. label Feb 3, 2026
@atomiks
Copy link
Copy Markdown
Contributor Author

atomiks commented Feb 3, 2026

@greptileai

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@atomiks atomiks force-pushed the fix/navigation-menu-ssr branch from 9d6a90b to 8dfc03e Compare February 3, 2026 02:43
@atomiks atomiks force-pushed the fix/navigation-menu-ssr branch from 8dfc03e to da85a35 Compare February 3, 2026 03:01
@atomiks atomiks merged commit 7643c54 into mui:master Feb 3, 2026
23 checks passed
@atomiks atomiks deleted the fix/navigation-menu-ssr branch February 3, 2026 03:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: navigation menu Changes related to the navigation menu component. type: new feature Expand the scope of the product to solve a new problem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[navigation menu] support for SSR / forceMount

3 participants