# Menubar

Persistent desktop-style command strip with horizontal roving focus for top-level triggers and explicit projected menu content.

This Angular implementation follows the shadcn Menubar information architecture while intentionally reusing the existing dropdown-menu content primitives for rows, checkbox items, radio groups, labels, shortcuts, and nested submenu triggers.

## Import

```ts
import {
  MenubarComponent,
  MenubarContentDirective,
  MenubarMenuComponent,
  MenubarTriggerDirective,
} from '@edsis/component/menubar';
import {
  MenuCheckboxItemComponent,
  MenuContentDirective,
  MenuGroupComponent,
  MenuItemComponent,
  MenuLabelComponent,
  MenuRadioGroupComponent,
  MenuRadioItemComponent,
  MenuSeparatorComponent,
  MenuShortcutComponent,
  MenuSurfaceComponent,
  MenuTriggerDirective,
} from '@edsis/component/dropdown-menu';
```

## Structure

```text
Menubar
├── MenubarMenu
│   ├── button[MenubarTrigger]
│   └── ng-template[MenubarContent]
│       └── MenuSurface
│           ├── MenuGroup
│           │   ├── button[MenuItem]
│           │   └── button[MenuItem][MenuTrigger]
│           │       └── ng-template[MenuContent]
│           │           └── MenuSurface
│           ├── MenuSeparator
│           ├── button[MenuCheckboxItem]
│           └── MenuRadioGroup
│               └── button[MenuRadioItem]
└── MenubarMenu
    ├── button[MenubarTrigger]
    └── ng-template[MenubarContent]
```

## Basic usage

```html
<Menubar>
  <MenubarMenu>
    <button type="button" [MenubarTrigger]="fileMenu">File</button>
    <ng-template MenubarContent #fileMenu="MenubarContent">
      <MenuSurface class="w-56">
        <MenuGroup>
          <button MenuItem type="button">
            New Tab
            <span MenuShortcut>⌘T</span>
          </button>
          <button MenuItem type="button" [MenuTrigger]="shareMenu" side="right" align="start">
            Share
            <span class="ml-auto text-xs text-muted-foreground">›</span>
          </button>
        </MenuGroup>
      </MenuSurface>
    </ng-template>
  </MenubarMenu>
</Menubar>
```

## Common patterns

### Basic command strip

Use one `MenubarMenu` per top-level trigger. The root owns horizontal roving focus, so only one trigger participates in tab order at a time.

```html
<Menubar>
  <MenubarMenu>
    <button type="button" [MenubarTrigger]="basicFileMenu">File</button>
    <ng-template MenubarContent #basicFileMenu="MenubarContent">
      <MenuSurface class="w-48">
        <button MenuItem type="button">New Tab</button>
        <button MenuItem type="button">Open Recent</button>
        <button MenuItem type="button" [disabled]="true">Import from iCloud</button>
      </MenuSurface>
    </ng-template>
  </MenubarMenu>
</Menubar>
```

### Checkbox and radio rows

The top-level strip stays on `menubar`, while toggleable content rows remain on the dropdown-menu primitives that already own those semantics.

```ts
const showSidebar = signal(true);
const editorTheme = signal<'light' | 'dark' | 'system'>('system');
```

```html
<Menubar>
  <MenubarMenu>
    <button type="button" [MenubarTrigger]="viewMenu">View</button>
    <ng-template MenubarContent #viewMenu="MenubarContent">
      <MenuSurface class="w-56">
        <MenuGroup>
          <button MenuCheckboxItem type="button" [(checked)]="showSidebar">Sidebar</button>
        </MenuGroup>
        <MenuSeparator />
        <MenuLabel [inset]="true">Theme</MenuLabel>
        <MenuRadioGroup [(value)]="editorTheme">
          <button MenuRadioItem type="button" value="light">Light</button>
          <button MenuRadioItem type="button" value="dark">Dark</button>
          <button MenuRadioItem type="button" value="system">System</button>
        </MenuRadioGroup>
      </MenuSurface>
    </ng-template>
  </MenubarMenu>
</Menubar>
```

### Submenus

Map shadcn `MenubarSub` to `[MenuTrigger]` on a `button[MenuItem]`. This keeps overlay ownership explicit and lets the shared menu trigger keep submenu keyboard behavior in one place.

```html
<ng-template MenuContent #findMenu="MenuContent">
  <MenuSurface class="w-44">
    <button MenuItem type="button">Search the web</button>
    <button MenuItem type="button">Find...</button>
    <button MenuItem type="button">Find Next</button>
  </MenuSurface>
</ng-template>

<Menubar>
  <MenubarMenu>
    <button type="button" [MenubarTrigger]="editMenu">Edit</button>
    <ng-template MenubarContent #editMenu="MenubarContent">
      <MenuSurface class="w-56">
        <button MenuItem type="button" [MenuTrigger]="findMenu" side="right" align="start">
          Find
          <span class="ml-auto text-xs text-muted-foreground">›</span>
        </button>
      </MenuSurface>
    </ng-template>
  </MenubarMenu>
</Menubar>
```

### Icons and shortcuts

Project inline icons and shortcut hints directly into the row content.

```html
<MenuSurface class="w-56">
  <button MenuItem type="button">
    <nav-icon name="description" [size]="16" class="text-muted-foreground" />
    New File
    <span MenuShortcut>⌘N</span>
  </button>
  <button MenuItem type="button" variant="destructive">
    <nav-icon name="delete" [size]="16" class="text-current" />
    Delete
  </button>
</MenuSurface>
```

### RTL

The root menubar respects computed direction for left and right movement. Apply `dir="rtl"` directly to the projected menu surface when the content itself should render right-to-left.

```html
<section dir="rtl" lang="ar" class="text-right">
  <Menubar>
    <MenubarMenu>
      <button type="button" [MenubarTrigger]="rtlFileMenu">ملف</button>
      <ng-template MenubarContent #rtlFileMenu="MenubarContent">
        <MenuSurface dir="rtl" lang="ar" class="w-56 text-right">
          <button MenuItem type="button">تبويب جديد <span MenuShortcut>⌘T</span></button>
          <button MenuItem type="button">نافذة جديدة <span MenuShortcut>⌘N</span></button>
        </MenuSurface>
      </ng-template>
    </MenubarMenu>
  </Menubar>
</section>
```

## API Reference

### `MenubarComponent`

| Input   | Type      | Default |
| ------- | --------- | ------- |
| `class` | `string`  | `''`    |
| `loop`  | `boolean` | `true`  |

Role: `menubar`.

### `MenubarMenuComponent`

Structural wrapper for one top-level trigger plus its `MenubarContent` template.

### `MenubarTriggerDirective`

| Input            | Type                           | Default   |
| ---------------- | ------------------------------ | --------- |
| `MenubarTrigger` | `MenubarContentDirective`      | required  |
| `align`          | `'start' \| 'center' \| 'end'` | `'start'` |
| `disabled`       | `boolean`                      | `false`   |

Output: `openedChange: boolean`.

Methods: `open()`, `close()`, `toggle()`, `focus()`.

### `MenubarContentDirective`

Projected overlay template for a top-level menubar trigger.

### Dropdown-menu parts reused in content

Import these from `@edsis/component/dropdown-menu`:

- `MenuSurfaceComponent`
- `MenuItemComponent`
- `MenuCheckboxItemComponent`
- `MenuRadioGroupComponent`
- `MenuRadioItemComponent`
- `MenuLabelComponent`
- `MenuSeparatorComponent`
- `MenuShortcutComponent`
- `MenuTriggerDirective`
- `MenuContentDirective`

## Styling and theming

- Pass `class` to `Menubar` when the root needs width, border, or layout changes.
- Style content surfaces on `MenuSurface`, not on the root menubar strip.
- Use shared theme tokens such as `border-border`, `bg-background`, `bg-accent`, and `text-muted-foreground` for visual consistency.

## Accessibility

- Top-level triggers expose `role="menuitem"`, `aria-haspopup="menu"`, and `aria-expanded`.
- The root menubar keeps one active tab stop, matching desktop menubar behavior.
- Projected content rows keep the accessible menu, checkbox, and radio roles from dropdown-menu.
- Disabled rows stay visible, announce their disabled state, and are skipped by roving focus.

## Keyboard interactions

- `ArrowLeft` and `ArrowRight` move across top-level triggers.
- `Home` and `End` jump to the first and last top-level trigger.
- `ArrowDown` opens the active menu and focuses its first enabled item.
- `ArrowRight` opens right-side submenu rows built with `[MenuTrigger] side="right"`.

## Angular Notes

- Menubar is intentionally split across two entrypoints: `menubar` for the persistent strip, `dropdown-menu` for the shared content rows.
- This avoids duplicating the same menu item semantics in two packages while still exposing a dedicated shadcn-style top-level component.
- Use native buttons for triggers so keyboard activation and disabled behavior stay predictable.

## Source parity

This slice keeps the shadcn Menubar command patterns, examples, keyboard expectations, and RTL guidance while making Angular overlay ownership explicit through `MenubarContent` and the existing dropdown-menu primitives.
