Mega menu that supports multiple overlay types and animations.
prc-block/navigation-mega-menu
design
| Feature | Enabled |
|---|---|
| HTML | No |
| Interactivity | Yes |
| Renaming | Yes |
| Reusable | No |
| Typography (fontSize) | Yes |
| Typography (lineHeight) | Yes |
| Typography (fontFamily) | Yes |
| Typography (fontWeight) | Yes |
| Typography (fontStyle) | Yes |
| Typography (textTransform) | Yes |
| Typography (textDecoration) | Yes |
| Typography (letterSpacing) | Yes |
| Shadow | Yes |
| Border (color) | Yes |
| Border (width) | Yes |
| Slash Inserter | Yes |
| Attribute | Type | Default | Description |
|---|---|---|---|
label |
string |
-- | The visible text label for the menu item. |
description |
string |
-- | Description text for the menu item (displayed if theme supports it). |
title |
string |
-- | Additional title attribute for accessibility/clarification. |
url |
string |
-- | Fallback URL when the mega menu cannot be opened. |
menuSlug |
string |
-- | Slug of the template part to render as the mega menu content. |
menuItemBackgroundColor |
string |
-- | Preset color name for menu item background. |
customMenuItemBackgroundColor |
string |
-- | Custom hex color for menu item background. |
menuItemTextColor |
string |
-- | Preset color name for menu item text. |
customMenuItemTextColor |
string |
-- | Custom hex color for menu item text. |
menuItemActiveBackgroundColor |
string |
-- | Preset color name for active menu item background. |
customMenuItemActiveBackgroundColor |
string |
-- | Custom hex color for active menu item background. |
menuItemActiveTextColor |
string |
-- | Preset color name for active menu item text. |
customMenuItemActiveTextColor |
string |
-- | Custom hex color for active menu item text. |
menuOverlayBackgroundColor |
string |
-- | Preset color name for the mega menu overlay background. |
customMenuOverlayBackgroundColor |
string |
-- | Custom hex color for the mega menu overlay background. |
menuOverlayTextColor |
string |
-- | Preset color name for the mega menu overlay text. |
customMenuOverlayTextColor |
string |
-- | Custom hex color for the mega menu overlay text. |
menuActiveBorderColor |
string |
-- | Preset color name for active state border. |
customMenuActiveBorderColor |
string |
-- | Custom hex color for active state border. |
isMobile |
boolean |
false |
Whether this mega menu instance is designed for mobile layout. |
icon |
string |
"dropdown" |
Icon type for the toggle button. One of: dropdown, mobile, search. |
animation |
string |
-- | Animation type for the overlay. One of: fade, slide. |
No block style variations defined in block.json, but variations control layout behavior (see below).
| Variation | Name | Description | Default |
|---|---|---|---|
| Mega Menu (Desktop) | mega-menu-desktop |
Absolute positioning designed for desktop | Yes |
| Mega Menu (Mobile) | mega-menu-mobile |
Absolute positioning designed for mobile | No |
This block does not use inner blocks in the traditional sense. Instead, it references a template part (by menuSlug) that is rendered as the mega menu overlay content.
In the editor, overlay content is not stored on the mega menu block itself. The edit UI loads the template part’s blocks through InnerBlocksAsSyncedContent from @prc/components (PRC Platform Core):
postType:wp_template_partpostId: Resolved frommenuSlugvia the menu template part hook (same entity the site uses for that template part).- Sync: Edits to inner blocks in the overlay are persisted to the template part post, not to the navigation block’s serialized markup.
The editor preview is not a <dialog>: edit.jsx renders an in-flow panel (a <div> with wp-block-prc-block-navigation-mega-menu__editor-panel) directly under the nav item so editing the navigation block stays manageable. Styles for that panel live in edit.scss. The frontend still uses a native <dialog> and --prc-mega-menu-anchor-top (see Frontend markup and Frontend Interactivity below).
Parent: core/navigation
This block can only be inserted inside a core/navigation block. It is registered as a listable block so that the navigation block wraps it in an <li> element.
- Insert a Navigation Mega Menu block inside a
core/navigationblock. - Set the Label -- this is the visible text for the navigation item.
- Select a Menu Template Part -- this template part defines the content shown in the mega menu overlay.
- Optionally set a URL as a fallback link when the mega menu cannot open.
- Choose an Icon type:
Dropdown-- shows label with a caret iconMobile-- shows a hamburger (bars) icon instead of the labelSearch-- shows a magnifying glass icon instead of the label
- Customize colors for menu item states (default, active) and overlay appearance via the color controls in the inspector.
- Click the menu item in the editor to toggle the mega menu overlay preview.
<div
class="wp-block-prc-block-navigation-mega-menu wp-block-navigation-item has-label"
id="mega-menu-1"
style="--custom-menu-item-background-color: #fff; ..."
data-wp-interactive="prc-block/navigation-mega-menu"
data-wp-context='{"id":"mega-menu-1","dialogId":"mega-menu-1-dialog","animation":"fade"}'
data-wp-class--is-active="state.isActive"
data-wp-init="callbacks.onInit"
data-wp-watch="callbacks.syncDialogState"
>
<button
class="wp-block-navigation-item__content wp-block-prc-block-navigation-mega-menu__toggle"
data-wp-on--click="actions.toggleMenuOnClick"
data-wp-bind--aria-expanded="state.isActive"
aria-controls="mega-menu-1-dialog"
type="button"
>
Topics
<span
class="wp-block-prc-block-navigation-mega-menu__toggle-dropdown-icon"
><!-- caret icon --></span
>
</button>
<div class="wp-block-prc-block-navigation-mega-menu__tab-divider"></div>
<dialog
id="mega-menu-1-dialog"
class="wp-block-prc-block-navigation-mega-menu__container wp-block-prc-block-navigation-mega-menu__dialog"
data-wp-on--click="callbacks.onBackdropClick"
data-wp-on--close="callbacks.onDialogClose"
>
<button
class="wp-block-prc-block-navigation-mega-menu__container__close-button"
data-wp-on--click="actions.closeMenuOnClick"
type="button"
>
<!-- close icon -->
</button>
<!-- Template part content rendered here -->
</dialog>
</div>--prc-mega-menu-anchor-top is written at runtime on document.documentElement (see view.js); style.scss positions the dialog with top: var(--prc-mega-menu-anchor-top, 0px).
The block_render_callback method:
- Returns early if no
labelormenuSlugis set. - Renders the referenced template part via
block_template_part($menu_slug). - Generates a unique ID for the menu instance.
- Sets initial interactivity state with
wp_interactivity_state. - Renders an icon based on the
iconattribute (dropdown caret, mobile bars, or search magnifying glass) using\PRC\Platform\Icons\Render. - Generates inline CSS custom properties for all color settings.
- Outputs a toggle button, tab divider, and
<dialog>overlay with full Interactivity API bindings.
Additional PHP hooks:
mega_menu_template_part_areas-- Registers a custom "menu" template part area for mega menu sections.enable_mega_menu_list_wrapper-- Adds the block toblock_core_navigation_listable_blocksso it gets wrapped in<li>.
Uses the WordPress Interactivity API (@wordpress/interactivity).
Store namespace: prc-block/navigation-mega-menu
State (derived):
isActive-- Whether this menu instance is currently open
CSS (runtime):
--prc-mega-menu-anchor-top-- Set ondocument.documentElementto the parent.wp-block-navigationblock'sgetBoundingClientRect().bottom(px), so the top-layer dialog'stopsits flush under the nav (view.jsonly; the editor does not use this variable).
Actions:
toggleMenuOnClick()-- Toggles the menu open/closed (closes other instances first)closeMenuOnClick()-- Closes the menucloseAll()-- Closes all mega menu instancesopenMenu()/closeMenu()-- Explicit open/close
Callbacks:
onInit()--ResizeObserveron the parent nav updates--prc-mega-menu-anchor-top; captures active classnames from inner group blockssyncDialogState()-- Callsdialog.showModal()/dialog.close()whenisActiveflips; refreshes anchor top beforeshowModal()onDialogClose()-- SyncsisActivewhen the user presses Escape or the platform closes the dialogonBackdropClick()-- Closes when the user clicks the modal backdrop
Global: a single window resize listener (in view.js) re-computes the anchor for any wrapper with .is-active.
core/navigation-- Required parent blockcore/template-part-- Used to define mega menu content