A website's top navigation with dropdown and mega-menu panels, a floating glass variant, and a matching mobile sheet — all from one nav array. Admin panels use Sidebar instead.
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { NavigationMenu, MobileNav, type SiteNavItem } from "@vamos-ui/react";
const nav: SiteNavItem[] = [
{ label: "Products", children: [{ label: "vTag", href: "/vtag", description: "NFC business cards" }] },
{ label: "Pricing", href: "/pricing" },
];
<NavigationMenu items={nav} className="max-md:hidden" />
<MobileNav items={nav} className="md:hidden" />Keyboard: Tab between items, Enter / Space / ↓ open a panel, Tab moves into it, Escape closes and returns focus to the trigger.
Examples
Mega menu (company site)
Compose the parts: layout="featured" puts a highlight card beside the links, "grid-2" lays links in two columns. Panels slide inside one shared, animated viewport.
Floating glass pill
variant="floating" is the site's one permanent blur; its panel turns opaque to keep the glass budget.
Mobile menu
MobileNav opens a side sheet with groups as an accordion. Following a link closes it. Narrow the preview to see the switch.
API
NavigationMenu
| Prop | Type | Default |
|---|---|---|
itemsData-driven menu. Or compose NavigationMenuList children. | SiteNavItem[] | — |
variantIn a header, or a floating glass pill. | "bar" | "floating" | "bar" |
viewportOne shared animated panel; false drops each panel under its trigger. | boolean | true |
value · defaultValue · onValueChangeThe open item (controlled / uncontrolled). | string | — |
delayDurationHover-intent delay before a panel opens (ms). | number | 200 |
aria-labelName of the nav landmark (labels.label). | string | "Main" |
SiteNavItem
| Prop | Type | Default |
|---|---|---|
label · hrefText and target (no href when it has children). | string | — |
description · iconShown on panel links. | string · ReactNode | — |
childrenMakes the item a dropdown. | SiteNavItem[] | — |
layoutPanel layout. | "list" | "grid-2" | "featured" | "list" |
featuredlayout="featured": the highlight card. | { title; description?; href; eyebrow? } | — |
NavigationMenuContent
| Prop | Type | Default |
|---|---|---|
layoutPanel layout. | "list" | "grid-2" | "featured" | "list" |
inlineWithout the viewport: render as its own popover. | boolean | false |
NavigationMenuLink
| Prop | Type | Default |
|---|---|---|
hrefRequired. Rendered with the app's router Link. | string | — |
variantRich panel link or a top-level link in the bar. | "panel" | "top" | "panel" |
title · description · iconPanel link content (title falls back to children). | ReactNode | — |
activeCurrent page; default derived from VamosProvider currentPath. | boolean | — |
Parts
| Prop | Type | Default |
|---|---|---|
NavigationMenuList · NavigationMenuItem · NavigationMenuTriggerThe bar, an item, the panel toggle (chevron included). | Radix parts | — |
NavigationMenuGroupA ul of links; heading is visual text, not a heading element. | { heading? } | — |
NavigationMenuFeaturedHighlight card for featured panels. | { title; description?; href; eyebrow? } | — |
NavigationMenuViewport · NavigationMenuIndicatorShared panel container (rendered for you) and an optional arrow. | Radix parts | — |
MobileNav
| Prop | Type | Default |
|---|---|---|
itemsRequired. The same array as the desktop menu. | SiteNavItem[] | — |
titleSheet heading (brand). | ReactNode | "Menu" |
footerBottom of the sheet: CTA, language switch. | ReactNode | — |
open · defaultOpen · onOpenChangeSheet state. | boolean | — |
classNameTrigger button classes; hide it on desktop (md:hidden). | string | — |
labels"Main", "Open menu", "Close menu", "Menu". | { label?; open?; close?; title? } | — |