# NavigationMenu Component

A horizontal navigation menu component that renders a top-level menu bar with dropdown submenus, keyboard navigation support, and a mobile drawer menu that slides in from the right.

## Import path
```tsx
import NavigationMenu from '@hubspot/cms-component-library/NavigationMenu';
```

## Purpose

The NavigationMenu component provides a horizontal navigation menu for HubSpot CMS projects. It automatically integrates with HubSpot's site menu system, supporting multi-level dropdown menus with keyboard navigation and flexible horizontal alignment options. On mobile viewports, it displays a hamburger button that opens a full-width drawer with a vertical list of top-level menu items. Colors inherit from the section's color scheme (`--hs-section-color` and `--hs-section-backgroundColor`).

## Component Structure

```
NavigationMenu/
├── index.tsx                      # Main component wrapper (Island integration)
├── ContentFields.tsx              # HubSpot field definitions for menu selection
├── islands/
│   ├── NavigationMenuIsland.tsx   # Island component with desktop nav and hamburger
│   ├── MobileMenu.tsx             # Mobile drawer with vertical menu items
│   ├── types.ts                   # TypeScript type definitions
│   └── index.module.scss          # CSS module styles
└── stories/
    ├── NavigationMenu.stories.tsx  # Storybook examples
    └── NavigationMenuDecorator.tsx # Storybook decorator
```

## Components

### NavigationMenu (Main Component)

**Purpose:** Renders a horizontal navigation menu from HubSpot site menu data with dropdown submenus on desktop and a slide-out drawer menu on mobile.

**Props:**
```tsx
{
  menuData: SiteMenu;                    // Menu data from useMenu hook (required)
  justifyMenu?: FlexJustifyContent;      // Horizontal alignment (default: 'flex-start')
  navAriaLabel?: string;                 // ARIA label for navigation (default: 'Navigation')
  hamburgerAriaLabel?: string;           // ARIA label for hamburger button (default: 'Open menu')
  className?: string;                    // Additional CSS classes
  style?: React.CSSProperties;           // Inline styles
}
```

### MobileMenu (Internal Component)

**Purpose:** Renders the mobile drawer with a recursive tree of navigation items and drilldown behavior. Items with children display a right-pointing chevron; clicking them slides in the submenu from the right. A "< Back" button at the top of the drilled-in view returns to the previous level.

**Props:**
```tsx
{
  isOpen: boolean;                       // Whether the drawer is open
  close: () => void;                     // Callback to close the drawer
  menuItems: EnrichedMenuDataItem[];     // Menu items to display
  drawerTop: number;                     // Top position in pixels (below header)
  navAriaLabel: string;                  // ARIA label for mobile nav
  portalTarget?: HTMLElement | null;     // Section element to portal into (set by NavigationMenuIsland)
}
```

## Consuming the Component with useMenu Hook

The NavigationMenu component requires menu data from HubSpot's `useMenu` hook. This hook fetches the site menu structure based on a menu ID defined in your module fields.

### Basic Module Implementation

```tsx
import { ModuleMeta } from '../types/modules.js';
import NavigationMenu from '@hubspot/cms-component-library/NavigationMenu';
import { useMenu, fieldPath } from '@hubspot/cms-components';

export const Component = () => {
  const menuData = useMenu(fieldPath('menu'));

  return (
    <NavigationMenu
      menuData={menuData}
      justifyMenu="flex-start"
      navAriaLabel="Main navigation"
    />
  );
};

export { fields } from './fields.js';

export const meta: ModuleMeta = {
  label: 'Main Navigation Menu',
  content_types: [],
  icon: '',
  categories: ['navigation'],
};
```

### Module Fields Definition

```tsx
import { ModuleFields } from '@hubspot/cms-components/fields';
import NavigationMenu from '@hubspot/cms-component-library/NavigationMenu';

export const fields = (
  <ModuleFields>
    <NavigationMenu.ContentFields />
  </ModuleFields>
);
```

**What this does:**
1. `NavigationMenu.ContentFields` creates a HubSpot MenuField in your module
2. This field allows content editors to select which site menu to display
3. The `useMenu(fieldPath('menu'))` hook fetches the selected menu's data
4. The menu data is passed to the NavigationMenu component via the `menuData` prop

## Usage Examples

### Basic Navigation Menu

```tsx
import NavigationMenu from '@hubspot/cms-component-library/NavigationMenu';
import { useMenu, fieldPath } from '@hubspot/cms-components';

export const Component = () => {
  const menuData = useMenu(fieldPath('menu'));

  return <NavigationMenu menuData={menuData} />;
};
```

## Mobile Behavior

On viewports below the `md` breakpoint (or when `data-hs-breakpoint-name="mobile"` is set):

- The desktop horizontal nav is hidden
- A hamburger button appears, centered in the nav area
- Clicking the hamburger opens a full-width drawer from the right, positioned below the header section
- The hamburger bars animate to an X while open
- The drawer contains a vertical list of menu items with drilldown navigation
- Items with children show a right-pointing chevron; clicking them slides in the submenu from the right (CSS `left` transition, 0.3s ease)
- A "< Back" button appears at the top of the menu when drilled into a submenu, returning to the previous level
- Clicking a leaf nav link closes the drawer
- Pressing ESC closes the drawer at any level (handled by the Drawer component)
- ArrowRight on an item with children drills in; ArrowLeft goes back
- ArrowDown/ArrowUp navigate between siblings
- Closing and reopening the drawer resets to the top-level menu
- Respects `prefers-reduced-motion` (transitions disabled)

## Styling

Colors inherit from the containing section's CSS variables:
- `--hs-section-color`: Text color for links and hamburger bars
- `--hs-section-backgroundColor`: Background color for menu items

The mobile drawer is portaled into the nearest `<section>` ancestor, so these variables cascade naturally without any JavaScript color bridging. The component renders `null` on first render (before mount), which is safe since the drawer starts closed.

Layout values like padding and max-width are defined in the CSS module. The mobile menu uses 10px block padding on the list, 8px block / 32px inline padding on each item, and 12px wide chevron icons.

## HubSpot CMS Integration

### Field Definitions

The NavigationMenu component provides field definitions for menu selection in HubSpot CMS modules.

#### ContentFields

Configurable props for customizing field labels, names, and defaults:

```tsx
<NavigationMenu.ContentFields
  menuLabel="Menu"
  menuName="menu"
  menuDefault="default"
/>
```

**Fields:**
- `menu`: MenuField for selecting which site menu to display (default: 'default')

#### StyleFields

Configurable props for customizing color field labels, names, and defaults. Opacity is not exposed on any of these color fields (`showOpacity={false}`).

```tsx
<NavigationMenu.StyleFields
  linkColorLabel="Text color (default)"
  linkColorName="linkColor"
  linkColorDefault={{ color: '#141414', opacity: 100 }}
  linkColorHoverLabel="Text color (hover)"
  linkColorHoverName="linkColorHover"
  linkColorHoverDefault={{ color: '#141414', opacity: 100 }}
  accentColorHoverLabel="Accent color (hover)"
  accentColorHoverName="accentColorHover"
  accentColorHoverDefault={{ color: '#F9F9F9', opacity: 100 }}
/>
```

**Fields:**
- `linkColor`: ColorField for the default text color of navigation links and the hamburger menu icon
- `linkColorHover`: ColorField for the text color of navigation links on hover
- `accentColorHover`: ColorField for menu item hover state backgrounds and flyout menu borders

## Accessibility

The NavigationMenu component follows accessibility best practices:

- **Semantic HTML**: Renders as a `<nav>` element with an unordered list (`<ul>`)
- **ARIA Labels**: Customizable `aria-label` via the `navAriaLabel` prop; mobile nav gets `Mobile ${navAriaLabel}`
- **ARIA Roles**: List items have `role="menuitem"` for proper screen reader support
- **Hamburger Button**: Uses `aria-expanded` to indicate drawer state, toggles `aria-label` between "Open menu" and "Close menu"
- **Keyboard Navigation**: Full keyboard support with arrow keys
  - `ArrowDown`: Opens submenu or moves to next item
  - `ArrowUp`: Closes submenu or moves to previous item
  - `ArrowRight`: Moves to next top-level item or opens nested submenu
  - `ArrowLeft`: Moves to previous top-level item or returns to parent
  - `Enter`/`Space`: Activates link
  - `Escape`: Closes submenu or mobile drawer
  - `Home`/`End`: Jump to first/last item
- **Focus Management**: Keyboard focus properly managed across menu levels
- **External Links**: Automatically adds `target="_blank"` and `rel="noopener noreferrer"` for external links

## Best Practices

- **Always use useMenu hook**: The NavigationMenu component requires menu data from the `useMenu` hook—never pass hardcoded menu structures
- **Consistent alignment**: Use the same `justifyMenu` value across navigation instances for visual consistency
- **ARIA labels**: Provide descriptive `navAriaLabel` values (e.g., "Main navigation", "Footer navigation")
- **Null checking**: Always check if menuData exists before rendering, as useMenu can return null

## Related Components

- **VerticalMenu**: Vertical navigation menu component for sidebar navigation
- **MenuItem**: Used internally to render individual menu items with support for nested children and keyboard navigation
- **Drawer**: Used internally for the mobile slide-out menu
