Navigation Menu
Top-level nav with hover-open content panels on bits-ui NavigationMenu. The viewport fades and scales in with a cubic-bezier ease; the chevron flips 180° when a trigger opens.
Usage
navigation-menu.svelte
<script lang="ts">
import * as NavigationMenu from '$lib/components/ui/navigation-menu';
</script>
<NavigationMenu.Root>
<NavigationMenu.List>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Components</NavigationMenu.Trigger>
<NavigationMenu.Content>
<ul class="grid w-[22rem] gap-2 p-3">
<li><NavigationMenu.Link href="/components/accordion">Accordion</NavigationMenu.Link></li>
<li><NavigationMenu.Link href="/components/tabs">Tabs</NavigationMenu.Link></li>
</ul>
</NavigationMenu.Content>
</NavigationMenu.Item>
</NavigationMenu.List>
</NavigationMenu.Root>Without viewport
Set viewport={false} to anchor content panels directly
under each trigger instead of rendering in a shared viewport.
navigation-menu.svelte
<script lang="ts">
import { NavigationMenu as NavigationMenuPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import NavigationMenuViewport from './navigation-menu-viewport.svelte';
let {
ref = $bindable(null),
class: className,
viewport = true,
children,
...restProps
}: NavigationMenuPrimitive.RootProps & {
viewport?: boolean;
} = $props();
</script>
<NavigationMenuPrimitive.Root
bind:ref
data-slot="navigation-menu"
data-viewport={viewport}
class={cn(
'group/navigation-menu relative flex max-w-max max-w-max flex-1 items-center justify-center',
className
)}
{...restProps}
>
{@render children?.()}
{#if viewport}
<NavigationMenuViewport />
{/if}
</NavigationMenuPrimitive.Root>
With icons
Drop a Remix icon (the <Icon> primitive) inside
each NavigationMenu.Link — the link's flex layout
handles spacing. Sized to size-4 to read alongside the link title.
navigation-menu-with-icons.svelte
<NavigationMenu.Link href="/dashboard">
<Icon name="layout-grid-line" size="1rem" class="size-4" />
<div>
<div class="font-medium text-foreground">Dashboard</div>
<div class="text-xs text-muted-foreground">Live overview</div>
</div>
</NavigationMenu.Link>NavigationMenu.Root props
Inherits bits-ui NavigationMenu.Root props. Subcomponents passthrough unless noted.
| Prop | Type | Default | Description |
|---|---|---|---|
string (bindable) | — | Currently open menu item. Empty string for no open item. | |
boolean | true | When true, content renders in a shared floating viewport under the list. Set false to render each panel anchored to its trigger. | |
number | 200 | Milliseconds before hover opens a menu. | |
number | 300 | Grace period where moving between triggers skips the hover delay. | |
'horizontal' | 'vertical' | 'horizontal' | Layout axis for the list. |
NavigationMenu.Link props
| Prop | Type | Default | Description |
|---|---|---|---|
boolean | false | Marks this link as the current route. Applies the muted highlight. | |
string | — | Anchor href. Standard HTMLAnchorAttributes pass through. | |
string | — | Merged onto the link via tailwind-merge. |