---
type: doc
title: Navigation Menu
description: A collection of links for navigating websites.
---

> Fulldev UI for Astro. The `@fulldev` registry in `components.json` points at `https://ui.full.dev/r/styles/{style}/{name}.json`; see [installation](/astro/docs/installation.md).

```astro title="src/components/examples/navigation-menu/navigation-menu-demo.astro"
---
import CircleAlertIcon from "@lucide/astro/icons/circle-alert"
import CircleCheckIcon from "@lucide/astro/icons/circle-check"
import CircleDashedIcon from "@lucide/astro/icons/circle-dashed"

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"

const gettingStarted = [
  {
    title: "Introduction",
    href: "/docs",
    description: "Re-usable components built with Tailwind CSS.",
  },
  {
    title: "Installation",
    href: "/docs/installation",
    description: "How to install dependencies and structure your app.",
  },
  {
    title: "Typography",
    href: "https://ui.shadcn.com/docs/typeset",
    description: "Styles for headings, paragraphs, lists...etc",
  },
]

const components: { title: string; href: string; description: string }[] = [
  {
    title: "Alert Dialog",
    href: "https://ui.shadcn.com/docs/components/base/alert-dialog",
    description:
      "A modal dialog that interrupts the user with important content and expects a response.",
  },
  {
    title: "Hover Card",
    href: "https://ui.shadcn.com/docs/components/base/hover-card",
    description:
      "For sighted users to preview content available behind a link.",
  },
  {
    title: "Progress",
    href: "https://ui.shadcn.com/docs/components/base/progress",
    description:
      "Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.",
  },
  {
    title: "Scroll-area",
    href: "https://ui.shadcn.com/docs/components/base/scroll-area",
    description: "Visually or semantically separates content.",
  },
  {
    title: "Tabs",
    href: "https://ui.shadcn.com/docs/components/base/tabs",
    description:
      "A set of layered sections of content, known as tab panels, that are displayed one at a time.",
  },
  {
    title: "Tooltip",
    href: "https://ui.shadcn.com/docs/components/base/tooltip",
    description:
      "A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.",
  },
]
---

<NavigationMenu>
  <NavigationMenuList>
    <NavigationMenuItem value="getting-started">
      <NavigationMenuTrigger>Getting started</NavigationMenuTrigger>
      <NavigationMenuContent>
        <ul class="w-96">
          {gettingStarted.map((item) => (
            <li>
              <NavigationMenuLink href={item.href}>
                <div class="flex flex-col gap-1 text-sm">
                  <div class="leading-none font-medium">{item.title}</div>
                  <div class="line-clamp-2 text-muted-foreground">
                    {item.description}
                  </div>
                </div>
              </NavigationMenuLink>
            </li>
          ))}
        </ul>
      </NavigationMenuContent>
    </NavigationMenuItem>
    <NavigationMenuItem value="components" class="hidden md:flex">
      <NavigationMenuTrigger>Components</NavigationMenuTrigger>
      <NavigationMenuContent>
        <ul class="grid w-[400px] gap-2 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
          {components.map((component) => (
            <li>
              <NavigationMenuLink href={component.href}>
                <div class="flex flex-col gap-1 text-sm">
                  <div class="leading-none font-medium">{component.title}</div>
                  <div class="line-clamp-2 text-muted-foreground">
                    {component.description}
                  </div>
                </div>
              </NavigationMenuLink>
            </li>
          ))}
        </ul>
      </NavigationMenuContent>
    </NavigationMenuItem>
    <NavigationMenuItem value="with-icon">
      <NavigationMenuTrigger>With Icon</NavigationMenuTrigger>
      <NavigationMenuContent>
        <ul class="grid w-[200px]">
          <li>
            <NavigationMenuLink href="#" class="flex-row items-center gap-2">
              <CircleAlertIcon />
              Backlog
            </NavigationMenuLink>
            <NavigationMenuLink href="#" class="flex-row items-center gap-2">
              <CircleDashedIcon />
              To Do
            </NavigationMenuLink>
            <NavigationMenuLink href="#" class="flex-row items-center gap-2">
              <CircleCheckIcon />
              Done
            </NavigationMenuLink>
          </li>
        </ul>
      </NavigationMenuContent>
    </NavigationMenuItem>
    <NavigationMenuItem value="docs">
      <NavigationMenuLink href="/docs" class={navigationMenuTriggerStyle()}>
        Docs
      </NavigationMenuLink>
    </NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>
```

## Installation

```bash
npx shadcn@latest add @fulldev/navigation-menu
```

## Usage

```ts
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
} from "@/components/ui/navigation-menu"
```

```astro
<NavigationMenu>
  <NavigationMenuList>
    <NavigationMenuItem value="item-one">
      <NavigationMenuTrigger>Item One</NavigationMenuTrigger>
      <NavigationMenuContent>
        <NavigationMenuLink href="/docs">Link</NavigationMenuLink>
      </NavigationMenuContent>
    </NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>
```

Every `NavigationMenuItem` needs a unique `value`. `NavigationMenuLink` renders
an `a`; pass `href` and, for the current route, `active`. Use
`navigationMenuTriggerStyle()` to give a top-level link the trigger look.

## Composition

```text
NavigationMenu
├── NavigationMenuList
│   ├── NavigationMenuItem
│   │   ├── NavigationMenuTrigger
│   │   └── NavigationMenuContent
│   │       ├── NavigationMenuLink
│   │       └── NavigationMenuLink
│   └── NavigationMenuItem
│       └── NavigationMenuLink
└── NavigationMenuIndicator
```

## RTL

Set `dir` on `NavigationMenu` and `NavigationMenuContent`, and `align="end"` to
open panels from the start edge in RTL.

```astro title="src/components/examples/navigation-menu/navigation-menu-rtl.astro"
---
import CircleAlertIcon from "@lucide/astro/icons/circle-alert"
import CircleCheckIcon from "@lucide/astro/icons/circle-check"
import CircleDashedIcon from "@lucide/astro/icons/circle-dashed"

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"

const translations = {
  en: {
    dir: "ltr",
    values: {
      gettingStarted: "Getting started",
      introduction: "Introduction",
      introductionDesc: "Re-usable components built with Tailwind CSS.",
      installation: "Installation",
      installationDesc: "How to install dependencies and structure your app.",
      typography: "Typography",
      typographyDesc: "Styles for headings, paragraphs, lists...etc",
      components: "Components",
      alertDialog: "Alert Dialog",
      alertDialogDesc:
        "A modal dialog that interrupts the user with important content and expects a response.",
      hoverCard: "Hover Card",
      hoverCardDesc:
        "For sighted users to preview content available behind a link.",
      progress: "Progress",
      progressDesc:
        "Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.",
      scrollArea: "Scroll-area",
      scrollAreaDesc: "Visually or semantically separates content.",
      tabs: "Tabs",
      tabsDesc:
        "A set of layered sections of content, known as tab panels, that are displayed one at a time.",
      tooltip: "Tooltip",
      tooltipDesc:
        "A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.",
      withIcon: "With Icon",
      backlog: "Backlog",
      toDo: "To Do",
      done: "Done",
      docs: "Docs",
    },
  },
  ar: {
    dir: "rtl",
    values: {
      gettingStarted: "البدء",
      introduction: "مقدمة",
      introductionDesc:
        "مكونات قابلة لإعادة الاستخدام مبنية باستخدام Tailwind CSS.",
      installation: "التثبيت",
      installationDesc: "كيفية تثبيت التبعيات وتنظيم تطبيقك.",
      typography: "الطباعة",
      typographyDesc: "أنماط للعناوين والفقرات والقوائم...إلخ",
      components: "المكونات",
      alertDialog: "حوار التنبيه",
      alertDialogDesc: "حوار نافذة يقطع المستخدم بمحتوى مهم ويتوقع استجابة.",
      hoverCard: "بطاقة التحويم",
      hoverCardDesc: "للمستخدمين المبصرين لمعاينة المحتوى المتاح خلف الرابط.",
      progress: "التقدم",
      progressDesc:
        "يعرض مؤشرًا يوضح تقدم إتمام المهمة، عادةً يتم عرضه كشريط تقدم.",
      scrollArea: "منطقة التمرير",
      scrollAreaDesc: "يفصل المحتوى بصريًا أو دلاليًا.",
      tabs: "التبويبات",
      tabsDesc:
        "مجموعة من أقسام المحتوى المتعددة الطبقات، المعروفة بألواح التبويب، التي يتم عرضها واحدة في كل مرة.",
      tooltip: "تلميح",
      tooltipDesc:
        "نافذة منبثقة تعرض معلومات متعلقة بعنصر عندما يتلقى العنصر التركيز على لوحة المفاتيح أو عند تحويم الماوس فوقه.",
      withIcon: "مع أيقونة",
      backlog: "قائمة الانتظار",
      toDo: "المهام",
      done: "منجز",
      docs: "الوثائق",
    },
  },
  he: {
    dir: "rtl",
    values: {
      gettingStarted: "התחלה",
      introduction: "הקדמה",
      introductionDesc: "רכיבים לשימוש חוזר שנבנו עם Tailwind CSS.",
      installation: "התקנה",
      installationDesc: "כיצד להתקין תלויות ולבנות את האפליקציה שלך.",
      typography: "טיפוגרפיה",
      typographyDesc: "סגנונות לכותרות, פסקאות, רשימות...וכו'",
      components: "רכיבים",
      alertDialog: "דיאלוג התראה",
      alertDialogDesc: "דיאלוג מודאלי שמפריע למשתמש עם תוכן חשוב ומצפה לתגובה.",
      hoverCard: "כרטיס ריחוף",
      hoverCardDesc:
        "למשתמשים רואים כדי להציג תצוגה מקדימה של תוכן זמין מאחורי קישור.",
      progress: "התקדמות",
      progressDesc:
        "מציג אינדיקטור המציג את התקדמות ההשלמה של משימה, בדרך כלל מוצג כסרגל התקדמות.",
      scrollArea: "אזור גלילה",
      scrollAreaDesc: "מפריד תוכן חזותית או סמנטית.",
      tabs: "כרטיסיות",
      tabsDesc:
        "קבוצה של חלקי תוכן מרובדים, המכונים לוחות כרטיסיות, המוצגים אחד בכל פעם.",
      tooltip: "טולטיפ",
      tooltipDesc:
        "חלון קופץ המציג מידע הקשור לאלמנט כאשר האלמנט מקבל מיקוד מקלדת או כאשר העכבר מרחף מעליו.",
      withIcon: "עם אייקון",
      backlog: "רשימת המתנה",
      toDo: "לעשות",
      done: "הושלם",
      docs: "תיעוד",
    },
  },
} as const

const components = [
  {
    titleKey: "alertDialog",
    descriptionKey: "alertDialogDesc",
    href: "https://ui.shadcn.com/docs/components/base/alert-dialog",
  },
  {
    titleKey: "hoverCard",
    descriptionKey: "hoverCardDesc",
    href: "https://ui.shadcn.com/docs/components/base/hover-card",
  },
  {
    titleKey: "progress",
    descriptionKey: "progressDesc",
    href: "https://ui.shadcn.com/docs/components/base/progress",
  },
  {
    titleKey: "scrollArea",
    descriptionKey: "scrollAreaDesc",
    href: "https://ui.shadcn.com/docs/components/base/scroll-area",
  },
  {
    titleKey: "tabs",
    descriptionKey: "tabsDesc",
    href: "https://ui.shadcn.com/docs/components/base/tabs",
  },
  {
    titleKey: "tooltip",
    descriptionKey: "tooltipDesc",
    href: "https://ui.shadcn.com/docs/components/base/tooltip",
  },
] as const

const language = "ar"
const { dir, values: t } = translations[language]

const gettingStarted = [
  { title: t.introduction, href: "/docs", description: t.introductionDesc },
  {
    title: t.installation,
    href: "/docs/installation",
    description: t.installationDesc,
  },
  {
    title: t.typography,
    href: "https://ui.shadcn.com/docs/typeset",
    description: t.typographyDesc,
  },
]
---

<NavigationMenu dir={dir} align={dir === "rtl" ? "end" : "start"}>
  <NavigationMenuList>
    <NavigationMenuItem value="getting-started">
      <NavigationMenuTrigger>{t.gettingStarted}</NavigationMenuTrigger>
      <NavigationMenuContent
        dir={dir}
        data-lang={dir === "rtl" ? language : undefined}
      >
        <ul class="w-96">
          {gettingStarted.map((item) => (
            <li>
              <NavigationMenuLink href={item.href}>
                <div class="flex flex-col gap-1 text-sm">
                  <div class="leading-none font-medium">{item.title}</div>
                  <div class="line-clamp-2 text-muted-foreground">
                    {item.description}
                  </div>
                </div>
              </NavigationMenuLink>
            </li>
          ))}
        </ul>
      </NavigationMenuContent>
    </NavigationMenuItem>
    <NavigationMenuItem value="components" class="hidden md:flex">
      <NavigationMenuTrigger>{t.components}</NavigationMenuTrigger>
      <NavigationMenuContent
        dir={dir}
        data-lang={dir === "rtl" ? language : undefined}
      >
        <ul class="grid w-[400px] gap-2 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
          {components.map((component) => (
            <li>
              <NavigationMenuLink href={component.href}>
                <div class="flex flex-col gap-1 text-sm">
                  <div class="leading-none font-medium">
                    {t[component.titleKey]}
                  </div>
                  <div class="line-clamp-2 text-muted-foreground">
                    {t[component.descriptionKey]}
                  </div>
                </div>
              </NavigationMenuLink>
            </li>
          ))}
        </ul>
      </NavigationMenuContent>
    </NavigationMenuItem>
    <NavigationMenuItem value="with-icon">
      <NavigationMenuTrigger>{t.withIcon}</NavigationMenuTrigger>
      <NavigationMenuContent
        dir={dir}
        data-lang={dir === "rtl" ? language : undefined}
      >
        <ul class="grid w-[200px]">
          <li>
            <NavigationMenuLink href="#" class="flex-row items-center gap-2">
              <CircleAlertIcon />
              {t.backlog}
            </NavigationMenuLink>
            <NavigationMenuLink href="#" class="flex-row items-center gap-2">
              <CircleDashedIcon />
              {t.toDo}
            </NavigationMenuLink>
            <NavigationMenuLink href="#" class="flex-row items-center gap-2">
              <CircleCheckIcon />
              {t.done}
            </NavigationMenuLink>
          </li>
        </ul>
      </NavigationMenuContent>
    </NavigationMenuItem>
    <NavigationMenuItem value="docs">
      <NavigationMenuLink
        href="/docs"
        class={navigationMenuTriggerStyle()}
        data-lang={dir === "rtl" ? language : undefined}
      >
        {t.docs}
      </NavigationMenuLink>
    </NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>
```

## Notes

- Closed panels start hidden in the rendered HTML to prevent a flash before
  JavaScript initializes. The controller manages visibility after
  initialization.
- Place `NavigationMenuIndicator` inside `NavigationMenuList` so its position is
  relative to the list whose measurements Data Slot uses.
- The menu opens below its trigger, aligned to the start, with an 8px gap. Set
  `side`, `align`, `sideOffset` and `alignOffset` on `NavigationMenu` to change
  this placement. Data Slot reads the root configuration and positions the
  shared popup.

## Content mounting

Data Slot's recommended `"lazy"` strategy is the default: closed content is
retained but detached from the document. Fulldev initializes nested Data Slot
components inside that retained content too.

Use `mountStrategy="eager"` when an integration needs to query closed content
through the document. Both strategies include content in server-rendered HTML;
neither adds a no-JavaScript fallback.

## API Reference

Source: [`src/components/ui/navigation-menu`](https://github.com/fulldotdev/ui/tree/main/src/components/ui/navigation-menu)

See the [Data Slot docs](https://github.com/bejamas/data-slot/blob/main/packages/navigation-menu/README.md) for the interactive behavior.

## Install what this page shows

```bash
npx shadcn@latest add @fulldev/navigation-menu-examples
```
