HextaUI

Navigation menu

Açılır menülü site gezintisi ya da içeriği menüler arasında kayarken açık kalan tek bir tam genişlikte panel.

import {
  IconBook,
  IconBrandGithub,
  IconBuildingStore,
  IconChartBar,
  IconCode,
  IconComponents,
  IconLayoutDashboard,
  IconLifebuoy,
  IconPalette,
  IconRocket,
  IconShieldLock,
  IconUsers,
} from "@tabler/icons-react"

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

type Entry = {
  title: string
  description: string
  icon: typeof IconBook
}

const products: Entry[] = [
  {
    title: "Components",
    description: "Accessible building blocks with motion built in.",
    icon: IconComponents,
  },
  {
    title: "Blocks",
    description: "Full sections you can drop into a page.",
    icon: IconLayoutDashboard,
  },
  {
    title: "Themes",
    description: "Tokens for color, radius and type.",
    icon: IconPalette,
  },
  {
    title: "Templates",
    description: "Starter apps ready to deploy.",
    icon: IconBuildingStore,
  },
]

const solutions: Entry[] = [
  {
    title: "Startups",
    description: "Ship a polished product on day one.",
    icon: IconRocket,
  },
  {
    title: "Teams",
    description: "One system shared across every app.",
    icon: IconUsers,
  },
  {
    title: "Analytics",
    description: "Dashboards, tables and charts.",
    icon: IconChartBar,
  },
  {
    title: "Security",
    description: "Audited for accessibility and safe defaults.",
    icon: IconShieldLock,
  },
  {
    title: "Developers",
    description: "Typed APIs that read like shadcn.",
    icon: IconCode,
  },
  {
    title: "Open source",
    description: "Read every line on GitHub.",
    icon: IconBrandGithub,
  },
]

const resources: Entry[] = [
  {
    title: "Documentation",
    description: "Every component, example and prop.",
    icon: IconBook,
  },
  {
    title: "Support",
    description: "Questions, bugs and feature requests.",
    icon: IconLifebuoy,
  },
]

function Links({ entries }: { entries: Entry[] }) {
  return (
    <ul className="grid gap-1 sm:grid-cols-2">
      {entries.map((entry) => (
        <li key={entry.title}>
          <NavigationMenuLink href="#">
            <span className="flex size-9 shrink-0 items-center justify-center rounded-md bg-background ring-(length:--hairline) ring-border">
              <entry.icon className="text-foreground" />
            </span>
            <span className="flex min-w-0 flex-col">
              <span className="font-medium">{entry.title}</span>
              <span className="text-muted-foreground">{entry.description}</span>
            </span>
          </NavigationMenuLink>
        </li>
      ))}
    </ul>
  )
}

export function NavigationMenuDemo() {
  return (
    <div className="w-full max-w-2xl rounded-xl border px-2 py-1.5">
      <NavigationMenu variant="panel" aria-label="Main">
        <NavigationMenuList>
          <NavigationMenuItem>
            <NavigationMenuTrigger>Products</NavigationMenuTrigger>
            <NavigationMenuContent>
              <Links entries={products} />
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <NavigationMenuTrigger>Solutions</NavigationMenuTrigger>
            <NavigationMenuContent>
              <Links entries={solutions} />
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <NavigationMenuTrigger>Resources</NavigationMenuTrigger>
            <NavigationMenuContent>
              <Links entries={resources} />
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <NavigationMenuLink href="#">Pricing</NavigationMenuLink>
          </NavigationMenuItem>
        </NavigationMenuList>
      </NavigationMenu>
    </div>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/navigation-menu.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
} from "@/components/ui/navigation-menu"
<NavigationMenu variant="panel" aria-label="Main">
  <NavigationMenuList>
    <NavigationMenuItem>
      <NavigationMenuTrigger>Products</NavigationMenuTrigger>
      <NavigationMenuContent>
        <NavigationMenuLink href="/components">Components</NavigationMenuLink>
      </NavigationMenuContent>
    </NavigationMenuItem>
    <NavigationMenuItem>
      <NavigationMenuLink href="/pricing">Pricing</NavigationMenuLink>
    </NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>

variant="panel" ile tek bir kart tüm çubuğu kaplar. Tetikleyiciler arasında geçmek kartı açık ve yerinde tutar: yalnızca içerik hareket ettiğiniz yöne kayar ve yükseklik uyacak şekilde yumuşar. Hiçbir şey kapanmaz, yeniden açılmaz veya zıplamaz.

NavigationMenu
└── NavigationMenuList
    ├── NavigationMenuItem
    │   ├── NavigationMenuTrigger
    │   └── NavigationMenuContent
    │       └── NavigationMenuLink
    └── NavigationMenuItem
        └── NavigationMenuLink

Varsayılan dropdown varyantı her tetikleyicinin altında bir kart açar. Sonraki tetikleyiciye geçmek aynı kartı üzerine kaydırır ve yeni içeriğe göre yeniden boyutlandırır.

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

const guides = [
  { title: "Installation", description: "Add HextaUI to a Next.js app." },
  { title: "Theming", description: "Colors, radius and dark mode." },
  { title: "Motion", description: "Durations, easing and reduced motion." },
]

const components = [
  "Accordion",
  "Button",
  "Dialog",
  "Menubar",
  "Table",
  "Tooltip",
]

export function NavigationMenuDropdown() {
  return (
    <NavigationMenu aria-label="Docs">
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Guides</NavigationMenuTrigger>
          <NavigationMenuContent>
            <ul className="flex w-72 flex-col gap-1">
              {guides.map((guide) => (
                <li key={guide.title}>
                  <NavigationMenuLink href="#">
                    <span className="flex flex-col">
                      <span className="font-medium">{guide.title}</span>
                      <span className="text-muted-foreground">
                        {guide.description}
                      </span>
                    </span>
                  </NavigationMenuLink>
                </li>
              ))}
            </ul>
          </NavigationMenuContent>
        </NavigationMenuItem>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Components</NavigationMenuTrigger>
          <NavigationMenuContent>
            <ul className="grid w-80 grid-cols-2 gap-1">
              {components.map((name) => (
                <li key={name}>
                  <NavigationMenuLink href="#">{name}</NavigationMenuLink>
                </li>
              ))}
            </ul>
          </NavigationMenuContent>
        </NavigationMenuItem>
        <NavigationMenuItem>
          <NavigationMenuLink href="#">Blog</NavigationMenuLink>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
  )
}

Geçerli sayfa

Çubuktaki bağlantılar tetikleyici gibi görünür. Geçerli sayfayı, ayrıca aria-current="page" ayarlayan active ile işaretleyin.

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

const links = ["Overview", "Activity", "Settings"]

export function NavigationMenuActive() {
  return (
    <NavigationMenu aria-label="Project">
      <NavigationMenuList>
        {links.map((link) => (
          <NavigationMenuItem key={link}>
            <NavigationMenuLink href="#" active={link === "Activity"}>
              {link}
            </NavigationMenuLink>
          </NavigationMenuItem>
        ))}
      </NavigationMenuList>
    </NavigationMenu>
  )
}

Sağdan sola

İçerik kaymaları, sağdan sola düzenlerde tersine dönen hareket yönünüzü izler.

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

const menus = [
  { label: "المنتجات", links: ["المكونات", "القوالب", "السمات"] },
  { label: "الموارد", links: ["التوثيق", "الدعم"] },
]

export function NavigationMenuRtl() {
  return (
    <div dir="rtl" className="w-full max-w-md rounded-xl border px-2 py-1.5">
      <NavigationMenu variant="panel" aria-label="الرئيسية">
        <NavigationMenuList>
          {menus.map((menu) => (
            <NavigationMenuItem key={menu.label}>
              <NavigationMenuTrigger>{menu.label}</NavigationMenuTrigger>
              <NavigationMenuContent>
                <ul className="grid grid-cols-2 gap-1">
                  {menu.links.map((link) => (
                    <li key={link}>
                      <NavigationMenuLink href="#">{link}</NavigationMenuLink>
                    </li>
                  ))}
                </ul>
              </NavigationMenuContent>
            </NavigationMenuItem>
          ))}
        </NavigationMenuList>
      </NavigationMenu>
    </div>
  )
}
TuşAction
TabÇubukta gezinir ve açık bir tetikleyiciden içeriğine geçer.
EnterSpaceOdaktaki tetikleyicinin menüsünü açar veya kapatır.
↑↓Açık içerikteki bağlantılar arasında gezinir.
←→Çubuktaki tetikleyiciler arasında gezinir.
EscMenüyü kapatır ve odağı tetikleyicisine döndürür.
  • Kök bir <nav> işler. Sayfada birden fazla varsa ona bir aria-label verin.
  • Tetikleyiciler menülerinin açık olup olmadığını bildiren düğmelerdir ve menü kapanınca odak onlara döner.
  • Azaltılmış hareket açıkken içerik kayması ve kayan vurgu solmalara dönüşür.
PropTürVarsayılan
variantdropdown her tetikleyicinin altında açılır. panel, çubuğun altında tam genişlikte tek bir kart açar; içerik kayarken kart yerinde kalır.
"dropdown" | "panel""dropdown"
showSafeAreaİmleç menüye doğru giderken menüyü açık tutan güvenli alanı çizer. Hata ayıklama ve demolar için.
booleanfalse
align
"start" | "center" | "end""start", or "center" for panel
sideOffset
number8
value
any–
defaultValue
any–
onValueChange
(value, details) => void–
delayHover'da açılmadan önce bekleme, ms cinsinden.
number50
closeDelayİmleç ayrıldıktan sonra kapanmadan önce bekleme, ms cinsinden.
number50
orientation
"horizontal" | "vertical""horizontal"
ÖznitelikAçıklama
data-slot="navigation-menu"Gezinti; data-variant ile birlikte.
data-slot="navigation-menu-highlight"Açık tetikleyiciler arasında kayan arka plan.
data-slot="navigation-menu-popup"Kart. Yüksekliği --popup-height üzerinden yumuşar.
ÖznitelikAçıklama
data-slot="navigation-menu-trigger"CSS'te tetikleyicileri hedefleyin.
data-popup-openMenüsü açıkken bulunur. Ok işareti döner.
ÖznitelikAçıklama
data-slot="navigation-menu-content"Bir menünün içeriği; data-variant ile birlikte.
data-activation-direction"left", "right", "up" veya "down": önceki tetikleyicinin nerede olduğu. Kaydırmayı yönetir.
--navigation-menu-link-radiusBağlantı köşe yarıçapı; kartla eş merkezli.
PropTürVarsayılan
activeGeçerli sayfayı işaretler.
booleanfalse
render
ReactElement | (props, state) => ReactElement<a>
ÖznitelikAçıklama
data-slot="navigation-menu-link"CSS'te bağlantıları hedefler. Çubukta tetikleyiciler gibi kendilerini boyutlandırır.
data-activeGeçerli sayfada bulunur.