Skip to main content
WireKit
Copy for LLM

Navigation Menu

The <x-wirekit::navigation-menu> component creates a top-level navigation with flyout panels (mega menus). It combines simple links with rich dropdown panels triggered by hover or click, following the WAI-ARIA Disclosure pattern.

Usage

Navigation Menu with Flyout Panels

Items come in two modes:

  • Simple link: pass href -- renders a plain navigation link
  • Flyout trigger: pass trigger -- renders a disclosure button that opens a panel on hover or click
{{-- Simple link -- navigates directly --}}
<x-wirekit::navigation-menu.item href="/pricing">Pricing</x-wirekit::navigation-menu.item>

{{-- Flyout trigger -- opens a panel --}}
<x-wirekit::navigation-menu.item trigger="Products">
    <div>Panel content here</div>
</x-wirekit::navigation-menu.item>

Active State

Mark the currently active item with the active prop on links inside panels:

Active Link in Flyout Panel

In a real Laravel app, pair the active prop with request()->is('…') (or request()->routeIs('…')) so the current page is highlighted automatically — e.g. :active="request()->is('docs*')". Active links receive an accent underline and use aria-current="page".

Mega Menu Layout

For complex navigation with multiple columns, use CSS Grid inside the panel:

Mega Menu with Columns

Behavior

  • Hover-to-open with configurable delay prevents accidental panel triggers
  • Bridge gap keeps the panel open while the cursor travels from trigger to panel
  • Floating UI (bundled ~3.5 KB) positions panels below their triggers with flip and shift
  • Click outside closes any open panel
  • Livewire SPA navigation (wire:navigate) automatically closes open panels
  • Transitions use opacity + slide for smooth panel reveal

Props

<x-wirekit::navigation-menu>

Prop Type Default Description
scope string|null null Scoped personalization key

<x-wirekit::navigation-menu.item>

Prop Type Default Description
trigger string|null null Label text for flyout trigger (enables panel mode)
href string|null null URL for simple link mode (no panel)
scope string|null null Scoped personalization key
Prop Type Default Description
href string '#' Link destination
active bool false Highlights as current page (sets aria-current="page")
scope string|null null Scoped personalization key

Sub-Components

Component Purpose
navigation-menu.item Top-level trigger (flyout) or simple link
navigation-menu.link Navigation link inside a flyout panel

Accessibility

  • Navigation wrapper: <nav aria-label="Main"> semantic landmark
  • Flyout triggers: aria-haspopup="menu", aria-expanded (dynamic)
  • Panels: role="menu", linked via aria-controls
  • Links inside panels: standard <a> elements, aria-current="page" when active
  • Roving tabindex on top-level items: only the focused item has tabindex="0"
  • Hover intent: panels open on hover with a short delay to prevent accidental triggers; panels stay open when the cursor moves between trigger and panel (bridge delay)
  • Click also works as a fallback for touch devices
  • Chevron indicators on flyout triggers are aria-hidden="true" (decorative)

Keyboard Interaction

Key Context Action
Tab Top-level items Move focus through the navigation items
Arrow Left / Right Top-level items Move focus between navigation items
Home / End Top-level items Jump to first / last navigation item
Enter / Space Flyout trigger Toggle the panel open/closed
Arrow Down Flyout trigger (panel closed) Open panel, focus first link
Tab Open panel Move focus through links inside the panel
Escape Open panel Close panel, return focus to trigger

Pitfalls

  • Don't use navigation-menu for app-internal commands. It's purpose-built for site navigation (top-level sections). Reach for <x-wirekit::menubar> for File > Edit > View patterns.
  • Don't bury the active page deep in a submenu. WCAG 2.4.8 (Location) is best served by surfacing the current section visibly — keep the top-level link active even when a child is shown.

Design Tokens

Element Token
Bar background --color-wk-bg-elevated
Item text --color-wk-text
Item hover text --color-wk-accent
Active indicator --color-wk-accent
Panel background --color-wk-bg-elevated
Panel border --color-wk-border / --border-wk-width
Panel radius --radius-wk-lg
Panel shadow --shadow-wk-lg
Panel padding --padding-wk-x-md
Link text --color-wk-text
Link hover bg --color-wk-bg-subtle
Link active text --color-wk-accent
Link description --color-wk-text-muted
Font family --font-wk-sans
Font size --text-wk-md
Transition --transition-wk-duration

Personalization

Override defaults in config/wirekit.php:

'components' => [
    'navigation-menu' => [],
],

Scoped Personalization

<x-wirekit::navigation-menu scope="marketing-nav">
    ...
</x-wirekit::navigation-menu>
'personalizations' => [
    'navigation-menu' => [
        'marketing-nav' => [
            'base' => 'border-b-2',
        ],
    ],
],

Further Reading

Was this page helpful?

Thanks — that helps.

Voting requires cookies or local storage. What we store