Skip to content

Navigation Menu Component - Implementation Summary

Added shadcn/ui Navigation Menu component to the universal packages/ui-web/ package for use across all CloudAlt web applications.

October 13, 2025

packages/ui-web/
├── src/
│ ├── lib/
│ │ └── utils.ts # cn() utility for class merging
│ ├── navigation-menu/
│ │ ├── NavigationMenu.tsx # Main component
│ │ ├── NavigationMenu.stories.tsx # Storybook documentation
│ │ └── index.ts # Exports
│ └── index.ts # Updated to export navigation-menu
  • @radix-ui/react-navigation-menu - Accessible navigation primitive
  • class-variance-authority - Variant styling utility
  • clsx - Conditional class names
  • tailwind-merge - Tailwind class deduplication
import {
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuTrigger,
NavigationMenuContent,
NavigationMenuLink,
NavigationMenuIndicator,
NavigationMenuViewport,
navigationMenuTriggerStyle,
} from '@cloudalt/ui-web';
import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuLink } from '@cloudalt/ui-web';
function AppHeader() {
return (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuLink href="/">Home</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink href="/about">About</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
);
}
import {
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuTrigger,
NavigationMenuContent,
NavigationMenuLink,
} from '@cloudalt/ui-web';
function AppHeader() {
return (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Products</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-[400px] gap-3 p-4">
<li>
<NavigationMenuLink href="/products/homestay">
<div className="text-sm font-medium">Homestay</div>
<p className="text-sm text-muted-foreground">
Find welcoming hosts for your stay
</p>
</NavigationMenuLink>
</li>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
);
}

Three stories available at Components/NavigationMenu:

  1. Default - Full-featured navigation with multiple dropdowns
  2. Simple - Basic navigation with just links
  3. SingleDropdown - One dropdown with multiple simple links
  • ✅ Full keyboard navigation (Arrow keys, Tab, Enter, Escape)
  • ✅ ARIA attributes automatically managed
  • ✅ Focus management
  • ✅ Screen reader support
  • ✅ RTL support ready

To create a custom navigation for a division (e.g., Stay Match):

  1. Create wrapper component in packages/ui-stay-match/:
packages/ui-stay-match/src/navigation/StayMatchNav.tsx
import {
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuTrigger,
NavigationMenuContent,
NavigationMenuLink,
} from '@cloudalt/ui-web';
export function StayMatchNav() {
return (
<NavigationMenu className="stay-match-nav">
<NavigationMenuList>
{/* Stay Match specific navigation items */}
<NavigationMenuItem>
<NavigationMenuLink href="/find-stays">Find Stays</NavigationMenuLink>
</NavigationMenuItem>
{/* Add more Stay Match specific items */}
</NavigationMenuList>
</NavigationMenu>
);
}
  1. Apps in the division import the division-specific component:
apps/homestay/app/layout.tsx
import { StayMatchNav } from '@cloudalt/ui-stay-match';
export default function RootLayout({ children }) {
return (
<html>
<body>
<StayMatchNav />
{children}
</body>
</html>
);
}

The component uses Tailwind CSS design tokens:

  • bg-background - Background color
  • bg-accent - Accent/hover color
  • text-accent-foreground - Accent text color
  • bg-popover - Dropdown background
  • text-popover-foreground - Dropdown text

Configure these in your app’s Tailwind config:

apps/homestay/tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))',
},
},
},
},
};
  • Component installed in packages/ui-web/
  • Storybook stories created
  • Exports configured
  • Test in at least one app (e.g., apps/homestay)
  • Create StayMatchNav in packages/ui-stay-match/
  • Create BonjourServicesNav in packages/ui-bonjour-services/
  • Define navigation structure for each division
  • Add division-specific branding/styling
  • Add to Astro docs site at apps/docs/src/content/docs/design-system/navigation.mdx
  • Document theming approach
  • Add migration guide for existing navigation components
  • Component is fully typed with TypeScript
  • Uses Radix UI primitives for accessibility
  • Tailwind classes can be overridden via className prop
  • Designed to be brand-agnostic at universal level
  • Division packages should wrap/extend for their specific needs