Skip to content

Components / Sections

Mega Menu

A menu bar whose panels open as popovers anchored under their triggers, columns revealing with a stagger, closing on Escape or outside click. Zero JavaScript of its own: the popover attribute and anchor positioning do the menu; Reveal does the columns.

Live demo

Live, from the library itself, at full size: scroll, hover, navigate away and back. The demo is never gated.

Variants · each row writes the attribute the prop writes; the section's own CSS answers

tone
density

Measured

JavaScript of its own

0 B

Uses Reveal and the shared runtime (1.9 kB raw, once per site). With those included: 3.0 kB raw.

CSS 11.0 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.

Browser support

Baseline · newly available

Chrome 125 · Firefox 147 · Safari 26; needs popover, anchor, starting-style. Elsewhere: panels open as a sheet at the bottom of the viewport.

Install Pro

The demo above is never gated; the source is. With a key in components.json (see account), the registry serves it like any other item:

terminal
npx shadcn@latest add @moonarc-pro/mega-menu
src/pages/index.astro
---
import MegaMenu from '@/components/moonarc/pro/MegaMenu.astro';
---
<MegaMenu menus={[
  { id: 'product', label: 'Product', columns: [
    { title: 'Features', links: [{ href: '/features/', label: 'Overview', description: 'What it does' }] },
    { title: 'Resources', links: [{ href: '/docs/', label: 'Docs' }] },
  ] },
]} />

Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: popover, reveal.

Props

PropTypeDefaultDescription
menus{ id, label, columns: { title, links: { href, label, description? }[] }[] }[]noneOne popover per menu; ids must be unique on the page.
tone'surface' | 'muted' | 'ink' | 'brand'unset (paints nothing)The ground: the page surface, a muted band, an always-dark ink panel, or a deep brand panel. Each paints --background, --ma-tone-muted (over --muted, with a --border hairline), --ma-tone-ink or --ma-tone-brand (over --primary) with the matching text. With theme.css, a painted tone also re-declares --card, --border, --input and --ring inside the section, so cards and fields follow the ground. Decoration is strongest on brand.
density'compact' | 'cozy' | 'roomy''cozy'Trigger and panel padding ×0.8 / ×1 / ×1.25 through --ma-density.
labelstring'Site'Accessible name of the menu bar's nav. Make it unique per page.

Theming and overrides

The section reads the theme contract (shadcn's variable names with the base tokens as fallback), so a pasted theme or one --ma-brand recolours it. Its class names are the override surface and stay stable; a named slot replaces the matching prop with your own markup.

Classes

.ma-megamenu.ma-megamenu__actions.ma-megamenu__brand.ma-megamenu__column.ma-megamenu__columns.ma-megamenu__panel.ma-megamenu__title.ma-megamenu__trigger

Slots

slot="headline"slot="actions"

Reduced motion

Panels crossfade; columns appear without stagger.

With ClientRouter

Native; nothing to rebind.

Why it is built this way

Replaces: NavigationMenu (Radix / shadcn) · Flyout menus (Tailwind Plus). See the migration table.

Raw bytes of JavaScript, from a production build, measured again for every change that can move them.

A popover that opens beside its trigger, flips when there is no room, closes on outside click or Escape, and animates in and out.

newly · Chrome 125 · Firefox 147 · Safari 26click

Entrance on scroll that plays once and stays, staggers its children, scrubs with the scroll position when asked, honours reduced motion, and keeps working after every ClientRouter navigation.

every browserscroll

A sticky navigation bar that condenses over the first 120 px of scroll: the row tightens and a hairline appears, bound to the document's scroll timeline.

Chrome 115 · not Firefox · Safari 26scroll

Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown