# Nav Menu

## Usage

`NavMenu` is a `role="menu"`. `NavMenuItem` is one entry and becomes a link when `href` is set. `NavDisclosure` owns the trigger, positioning, and dismissal: click, hover, outside press, and Escape all close it. ArrowDown opens on the first item, ArrowUp on the last. Inside the menu, arrows move and a typed character jumps to a matching prefix.

The top nav and overflow list already compose these parts. Use them directly for an account menu.

Menus attached to a side or top heading use `NavHeadingMenu` and `NavHeadingMenuItem`. Put the menu in the heading `menu` slot. The heading owns closing and where focus goes after open. An item with an address is a link. An item without one is a `menuitem`. Arrows move, and Enter or Space activates the current item.

```vue
<script setup lang="ts">
import { NavDisclosure, NavMenu, NavMenuItem } from '@astryx-vue/core/NavMenu'
</script>

<template>
  <NavDisclosure label="Account">
    <template #trigger="{ isOpen, panelId }">
      <button type="button" :aria-controls="panelId" :aria-expanded="isOpen">
        Account
      </button>
    </template>
    <template #default="{ close, focusRequest }">
      <NavMenu label="Account" :focus-request="focusRequest" @close="close">
        <NavMenuItem href="/profile" label="Profile" />
      </NavMenu>
    </template>
  </NavDisclosure>
</template>
```

## Best practices

| Guidance | Practice |
| --- | --- |
| Do | Write `aria-expanded` and `aria-controls` on the trigger. The slot already passes that state. |
| Do | Items close the menu by default. Set `keepOpen` when the menu should stay. |
| Avoid | Do not leave `menuitem` elements in a drawer. Set `isMenuItem` to false there. |

## Examples

### Product switcher

The side nav heading opens a product switcher. Dashboard, Analytics, and Settings are the destinations.

```vue
<script setup lang="ts">
import { NavHeadingMenu, NavHeadingMenuItem } from '@astryx-vue/core/NavMenu'
import { SideNav, SideNavHeading } from '@astryx-vue/core/SideNav'
</script>

<template>
  <div style="height: 100px">
    <SideNav>
      <template #header>
        <SideNavHeading heading="Acme Platform">
          <template #icon>
            <span class="i-carbon-grid css-icon css-icon--sm" />
          </template>
          <template #menu>
            <NavHeadingMenu label="Acme Platform" size="lg">
              <NavHeadingMenuItem href="/dashboard" label="Dashboard" />
              <NavHeadingMenuItem href="/analytics" label="Analytics" />
              <NavHeadingMenuItem href="/settings" label="Settings" />
            </NavHeadingMenu>
          </template>
        </SideNavHeading>
      </template>
    </SideNav>
  </div>
</template>
```

## NavMenu Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | - | Accessible name of the menu. |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Menu width. |
| `focusRequest` | `'first' \| 'last' \| null` | `null` | Moves focus to the first or last item after open. |

## NavMenu events

| Name | Description |
| --- | --- |
| `close` | Fired on Escape. `NavDisclosure` listens and closes the panel. |

## NavMenuItem Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | - | Item text. |
| `description` | `string` | - | Supporting line under the text. |
| `href` | `string` | - | Renders a link when set. |
| `as` | `NavLinkComponent` | `'a'` | Link root. |
| `iconClass` | `string` | - | CSS icon class. |
| `isDisabled` | `boolean` | `false` | Disabled. Keyboard navigation skips it. |
| `keepOpen` | `boolean` | `false` | Leaves the menu open after activation. |
| `isMenuItem` | `boolean` | `true` | Uses `menuitem` inside a menu. Set false in a drawer. |

## NavDisclosure Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | - | Accessible name of the popup. |
| `placement` | `'above' \| 'below' \| 'start' \| 'end'` | `'below'` | Position relative to the trigger. |
| `alignment` | `'start' \| 'center' \| 'end'` | `'start'` | Cross-axis alignment. |
| `hover` | `boolean` | `false` | Opens after a hover delay and closes after the pointer leaves. |
| `showDelay` | `number` | `150` | Hover open delay, in milliseconds. |
| `hideDelay` | `number` | `200` | Pointer-leave close delay, in milliseconds. |

## NavHeadingMenu Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | - | Accessible name of the menu. |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Menu width, also passed through as item padding. |
| `minWidth` | `number \| string` | - | Overrides the width that comes from the size. A number is pixels. |
| `focusRequest` | `'first' \| 'last' \| null` | - | Moves focus to the first or last item after open. A heading menu slot passes this in. |

## NavHeadingMenu events

| Name | Description |
| --- | --- |
| `close` | Fired on Escape. |

## NavHeadingMenuItem Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | - | Primary text. The default slot wins when it is set. |
| `description` | `string` | - | Supporting line under the text. |
| `href` | `string` | - | Renders a link when set. |
| `as` | `NavLinkComponent` | `'a'` | Link root. |
| `iconClass` | `string` | - | CSS icon class. |
| `isDisabled` | `boolean` | `false` | Disabled. Arrow keys and typeahead skip it. |
