Mega Menu
Group navigation links into columns with captions and a featured card.
import { MegaMenuContent, MegaMenuFeatured, MegaMenuGroup, MegaMenuLink } from '@youj/react'
Installation & usage
npm i @youj/reactFor an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.
Use a mega menu when a top-level section has more destinations than a plain dropdown holds well: a product with a dozen features, a resources hub, a developer portal. Each panel groups links into captioned columns, and a featured card at the end can carry a launch or a case study. For a handful of links, a Navigation Menu with plain panels is enough. Actions (sign out, delete, switch theme) belong in a Dropdown Menu, not in navigation.
The mega menu parts go inside a Navigation Menu: MegaMenuContent takes the place of NavigationMenuContent.
import {
MegaMenuContent,
MegaMenuFeatured,
MegaMenuGroup,
MegaMenuLink,
NavigationMenu,
NavigationMenuItem,
NavigationMenuList,
NavigationMenuTrigger,
} from '@youj/react'
import { RocketIcon, TerminalIcon } from '@youj/icons'
export function ProductMenu() {
return (
<NavigationMenu aria-label="Main">
<NavigationMenuList>
<NavigationMenuItem value="product">
<NavigationMenuTrigger>Product</NavigationMenuTrigger>
<MegaMenuContent featured={<MegaMenuFeatured href="/blog/2-0" eyebrow="New" title="Northwind 2.0" />}>
<MegaMenuGroup title="Build">
<MegaMenuLink href="/deployments" icon={<RocketIcon size={16} />} title="Deployments" description="Git-push to preview, promote to prod." />
<MegaMenuLink href="/functions" icon={<TerminalIcon size={16} />} title="Functions" description="Server code that scales to zero." />
</MegaMenuGroup>
</MegaMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
)
}Each MegaMenuGroup is a column, 15.5rem wide, under its caption. MegaMenuLink is a destination: an icon tile, a title and one line of description. It closes the menu when it's followed. A Youj icon in the tile plays while the link is hovered or focused, with no wiring.
In a header
A mega menu usually lives in an App Header, inside AppHeaderNav, which hides it below md. Phones get the same destinations as a flat list in AppHeaderMenu.
Description
A header navigation whose Product panel arranges grouped links in columns beside a featured card.
A Resources panel with a featured card on one side and grouped links on the other.
featured puts one card at the inline end of the panel. MegaMenuFeatured is a single link with art on top and copy below: an eyebrow ("New", "Changelog"), a title and a description. The art is decorative, so any background piece works as media. The first preview uses a Mesh Gradient. Without media, the card gets a soft wash of the accent.
Keep a panel to two or three columns. Past that the popup gets wider than most windows, and the reader has too many choices to scan.
Code
mega-menu-demo.tsx, the Demo story. The component itself comes from the package.
Reference
Propsfeatured, title, title… (9)
Props
MegaMenuContent
| Prop | Type | |
|---|---|---|
featured | ReactNodeA card at the inline end: a launch, a case study, a changelog entry. | – |
Other props pass through: extends ComponentProps<typeof NavigationMenuContent>. | ||
It takes NavigationMenuContent's props as well.
MegaMenuGroup
| Prop | Type | |
|---|---|---|
title | ReactNodeThe column's caption. It labels the group for assistive tech. | – |
Other props pass through: extends ComponentProps<'div'>. | ||
MegaMenuLink
| Prop | Type | |
|---|---|---|
icon | ReactNodeA 16px glyph for the tile; a youj icon plays while the link is hovered or focused. | – |
titleRequired | ReactNode | – |
description | ReactNode | – |
Other props pass through: extends ComponentProps<typeof NavigationMenuLink>. | ||
MegaMenuFeatured
| Prop | Type | |
|---|---|---|
media | ReactNodeArt for the top of the card: an image, a motion background piece. Decorative. | – |
eyebrow | ReactNodeA small line above the title, e.g. "New". | – |
titleRequired | ReactNode | – |
description | ReactNode | – |
Other props pass through: extends ComponentProps<typeof NavigationMenuLink>. | ||
MegaMenuLink and MegaMenuFeatured are NavigationMenuLinks, so href, render (for a router link), active and closeOnClick pass through.
MotionHover pill, popup in, popup out… · reduced motion
Motion
The motion is the Navigation Menu's: the panels only add layout.
| Moment | Tokens | ||
|---|---|---|---|
| Hover pillglides between triggers with the pointer and keyboard focus | spring.smooth0.36s, bounce 0 | 0.36s, bounce 0 | |
| Popup ingrows out of the trigger: scale from 0.96 and fade | duration.fastease.enter140ms · cubic-bezier(0.16, 1, 0.3, 1) | 140mscubic-bezier(0.16, 1, 0.3, 1) | |
| Popup out | duration.instantease.exit80ms · cubic-bezier(0.4, 0, 1, 1) | 80mscubic-bezier(0.4, 0, 1, 1) | |
| Popup between triggersslides to the next trigger and morphs to its panel size | duration.slowease.standard340ms · cubic-bezier(0.2, 0, 0, 1) | 340mscubic-bezier(0.2, 0, 0, 1) | |
| Panels trade places24px drift and fade, away from the way you moved | duration.slowease.standard340ms · cubic-bezier(0.2, 0, 0, 1) | 340mscubic-bezier(0.2, 0, 0, 1) | |
| Link tilethe icon turns to ink, and a Youj icon plays its own motion | duration.fastease.standard140ms · cubic-bezier(0.2, 0, 0, 1) | 140mscubic-bezier(0.2, 0, 0, 1) | |
| Featured card borderstrengthens on hover | duration.fastease.standard140ms · cubic-bezier(0.2, 0, 0, 1) | 140mscubic-bezier(0.2, 0, 0, 1) |
Reduced motion
The popup and its panels appear, resize and swap at once, the pill jumps, and link icons don't play.
Reduced motion
The panel appears, resizes and swaps with the next one at once, and the hover pill jumps between triggers. Link icons stay still. The menu opens, closes and moves focus exactly as it does with motion.
AccessibilityKeyboard, ARIA, focus
Accessibility
- Each column is a
grouplabeled by its caption. - A link is named by its title, and its description is read after it (
aria-describedby). The featured card is named by its eyebrow and title. Icons and art are hidden from assistive technology. - Triggers are buttons with
aria-expanded. The whole menu is anavlandmark, named by theNavigationMenu'saria-label.
| Key | Action |
|---|---|
| Enter / Space / ↓ | Open the focused trigger's panel. |
| Tab | Move through the panel's links, then on to the next trigger. |
| Escape | Close the panel and return focus to its trigger. |