Horizontal navigation menu with optional dropdown panels.
A fully accessible horizontal navigation bar following the WAI-ARIA
navigation landmark pattern. Supports both simple link items and
trigger-plus-content dropdown panels. CSS-only layout — no JavaScript
hook is required for static dropdowns; use server-side assigns to
toggle panel visibility when needed.
Sub-components
| Component | Element | Purpose |
|---|---|---|
navigation_menu/1 | <nav> | Root landmark with aria-label="Main navigation" |
navigation_menu_list/1 | <ul> | Horizontal flex list of items |
navigation_menu_item/1 | <li> | Container for a link or trigger+content pair |
navigation_menu_link/1 | <a> | Styled link with active-state highlight |
navigation_menu_trigger/1 | <button> | Dropdown toggle button with chevron icon |
navigation_menu_content/1 | <div> | Absolutely-positioned dropdown panel |
Simple links only
<.navigation_menu>
<.navigation_menu_list>
<.navigation_menu_item>
<.navigation_menu_link href="/" active={@current_path == "/"}>
Home
</.navigation_menu_link>
</.navigation_menu_item>
<.navigation_menu_item>
<.navigation_menu_link href="/pricing" active={@current_path == "/pricing"}>
Pricing
</.navigation_menu_link>
</.navigation_menu_item>
<.navigation_menu_item>
<.navigation_menu_link href="/contact" active={@current_path == "/contact"}>
Contact
</.navigation_menu_link>
</.navigation_menu_item>
</.navigation_menu_list>
</.navigation_menu>With a dropdown panel
Pair navigation_menu_trigger/1 and navigation_menu_content/1 inside
the same navigation_menu_item/1. The content panel is positioned
absolutely below the item:
<.navigation_menu>
<.navigation_menu_list>
<.navigation_menu_item>
<.navigation_menu_link href="/" active={@current_path == "/"}>Home</.navigation_menu_link>
</.navigation_menu_item>
<.navigation_menu_item>
<.navigation_menu_trigger label="Products" />
<.navigation_menu_content>
<ul class="grid grid-cols-2 gap-3 p-4 w-[400px]">
<li>
<a href="/products/web" class="block rounded-md p-3 hover:bg-accent">
<p class="font-medium">Web Platform</p>
<p class="text-sm text-muted-foreground">Build scalable web apps</p>
</a>
</li>
<li>
<a href="/products/mobile" class="block rounded-md p-3 hover:bg-accent">
<p class="font-medium">Mobile SDK</p>
<p class="text-sm text-muted-foreground">Native iOS and Android</p>
</a>
</li>
</ul>
</.navigation_menu_content>
</.navigation_menu_item>
<.navigation_menu_item>
<.navigation_menu_link href="/docs">Docs</.navigation_menu_link>
</.navigation_menu_item>
</.navigation_menu_list>
</.navigation_menu>Marking the current page
Pass active={true} to navigation_menu_link/1 for the item matching the
current route. In a LiveView, compare against @current_path or use the
route helpers:
active={URI.parse(@current_url).path == "/pricing"}Accessibility
- The
<nav>root hasaria-label="Main navigation"to distinguish it from other navigation landmarks (e.g. breadcrumb, pagination). - Active links carry
aria-current="page"so screen readers announce the current location. - Trigger buttons carry
aria-haspopup="true"andaria-expanded="false"to communicate dropdown availability to assistive technologies.
Summary
Functions
Renders the navigation menu root <nav> element.
Renders the dropdown content panel for a trigger.
Renders a single navigation menu item.
Renders a styled navigation link.
Renders the horizontal menu list.
Renders a trigger button that opens a dropdown navigation panel.