---
title: Navbar
description: Navigation layouts for product sites, docs, and app shells.
group: Blocks
order: 33
---

Navigation for product sites and docs, from minimal to more structured. Choose the shape that fits and replace the links.

## Logo and actions

A logo on the left, with ghost links and a primary action on the right.

```tsx
"use client";

import { useState } from "react";
import { Button } from "@/components/ui/button";

function Mark({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 18V6l8 7 8-7v12"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

function MenuIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 7h16M4 12h16M4 17h16"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

function CloseIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M6 6l12 12M18 6L6 18"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

const links = ["Product", "Docs", "Pricing"] as const;

export function Navbar01() {
  const [open, setOpen] = useState(false);

  return (
    <header className="@container w-full bg-background">
      <div className="flex w-full items-center justify-between gap-4 px-4 py-3">
        <a
          href="#"
          className="inline-flex items-center gap-2 text-foreground"
        >
          <Mark className="size-4" />
          <span className="text-sm tracking-wide">Acme</span>
        </a>

        <div className="flex items-center gap-1">
          <nav className="hidden items-center gap-1 @[32rem]:flex">
            {links.map((label) => (
              <Button key={label} type="button" variant="ghost" size="sm">
                {label}
              </Button>
            ))}
          </nav>
          <Button
            type="button"
            size="sm"
            className="hidden @[32rem]:inline-flex"
          >
            Get started
          </Button>
          <Button
            type="button"
            size="icon-sm"
            variant="ghost"
            className="@[32rem]:hidden"
            aria-label={open ? "Close menu" : "Open menu"}
            aria-expanded={open}
            onClick={() => setOpen((value) => !value)}
          >
            {open ? <CloseIcon /> : <MenuIcon />}
          </Button>
        </div>
      </div>

      {open ? (
        <div className="flex flex-col gap-1 px-4 pb-3 @[32rem]:hidden">
          <nav className="flex flex-col gap-1">
            {links.map((label) => (
              <Button
                key={label}
                type="button"
                variant="ghost"
                size="sm"
                className="justify-start"
              >
                {label}
              </Button>
            ))}
          </nav>
          <Button type="button" size="sm" className="mt-1 w-full">
            Get started
          </Button>
        </div>
      ) : null}
    </header>
  );
}
```

### Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add navbar-01
```

### Usage

```tsx
import { Navbar01 } from "@/components/blocks/navbar/navbar-01"
```

```tsx
<Navbar01 />
```

## Floating

A muted, inset bar that floats away from the page edges, with the same links and mobile menu.

```tsx
"use client";

import { useState } from "react";
import { Button } from "@/components/ui/button";

function Mark({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 18V6l8 7 8-7v12"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

function MenuIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 7h16M4 12h16M4 17h16"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

function CloseIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M6 6l12 12M18 6L6 18"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

const links = ["Product", "Docs", "Pricing"] as const;

export function Navbar02() {
  const [open, setOpen] = useState(false);

  return (
    <header className="@container w-full px-3 pt-3">
      <div className="mx-auto w-full max-w-5xl rounded-md bg-muted">
        <div className="flex w-full items-center justify-between gap-4 px-3 py-2.5">
          <a
            href="#"
            className="inline-flex items-center gap-2 text-foreground"
          >
            <Mark className="size-4" />
            <span className="text-sm tracking-wide">Acme</span>
          </a>

          <div className="flex items-center gap-1">
            <nav className="hidden items-center gap-1 @[32rem]:flex">
              {links.map((label) => (
                <Button key={label} type="button" variant="ghost" size="sm">
                  {label}
                </Button>
              ))}
            </nav>
            <Button
              type="button"
              size="sm"
              className="hidden @[32rem]:inline-flex"
            >
              Get started
            </Button>
            <Button
              type="button"
              size="icon-sm"
              variant="ghost"
              className="@[32rem]:hidden"
              aria-label={open ? "Close menu" : "Open menu"}
              aria-expanded={open}
              onClick={() => setOpen((value) => !value)}
            >
              {open ? <CloseIcon /> : <MenuIcon />}
            </Button>
          </div>
        </div>

        {open ? (
          <div className="flex flex-col gap-1 px-3 pb-3 @[32rem]:hidden">
            <nav className="flex flex-col gap-1">
              {links.map((label) => (
                <Button
                  key={label}
                  type="button"
                  variant="ghost"
                  size="sm"
                  className="justify-start"
                >
                  {label}
                </Button>
              ))}
            </nav>
            <Button type="button" size="sm" className="mt-1 w-full">
              Get started
            </Button>
          </div>
        ) : null}
      </div>
    </header>
  );
}
```

### Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add navbar-02
```

### Usage

```tsx
import { Navbar02 } from "@/components/blocks/navbar/navbar-02"
```

```tsx
<Navbar02 />
```

## Centered links

Logo left, navigation centered, and an action on the right. The mobile menu expands below.

```tsx
"use client";

import { useState } from "react";
import { Button } from "@/components/ui/button";

function Mark({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 18V6l8 7 8-7v12"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

function MenuIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 7h16M4 12h16M4 17h16"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

function CloseIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M6 6l12 12M18 6L6 18"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

const links = ["Product", "Docs", "Pricing"] as const;

export function Navbar03() {
  const [open, setOpen] = useState(false);

  return (
    <header className="@container w-full bg-background">
      <div className="grid w-full grid-cols-[1fr_auto] items-center gap-4 px-4 py-3 @[32rem]:grid-cols-[1fr_auto_1fr]">
        <a
          href="#"
          className="inline-flex items-center gap-2 justify-self-start text-foreground"
        >
          <Mark className="size-4" />
          <span className="text-sm tracking-wide">Acme</span>
        </a>

        <nav className="hidden items-center gap-1 justify-self-center @[32rem]:flex">
          {links.map((label) => (
            <Button key={label} type="button" variant="ghost" size="sm">
              {label}
            </Button>
          ))}
        </nav>

        <div className="flex items-center gap-1 justify-self-end">
          <Button
            type="button"
            size="sm"
            className="hidden @[32rem]:inline-flex"
          >
            Get started
          </Button>
          <Button
            type="button"
            size="icon-sm"
            variant="ghost"
            className="@[32rem]:hidden"
            aria-label={open ? "Close menu" : "Open menu"}
            aria-expanded={open}
            onClick={() => setOpen((value) => !value)}
          >
            {open ? <CloseIcon /> : <MenuIcon />}
          </Button>
        </div>
      </div>

      {open ? (
        <div className="flex flex-col gap-1 px-4 pb-3 @[32rem]:hidden">
          <nav className="flex flex-col gap-1">
            {links.map((label) => (
              <Button
                key={label}
                type="button"
                variant="ghost"
                size="sm"
                className="justify-start"
              >
                {label}
              </Button>
            ))}
          </nav>
          <Button type="button" size="sm" className="mt-1 w-full">
            Get started
          </Button>
        </div>
      ) : null}
    </header>
  );
}
```

### Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add navbar-03
```

### Usage

```tsx
import { Navbar03 } from "@/components/blocks/navbar/navbar-03"
```

```tsx
<Navbar03 />
```

## Menu dropdown

The same compact setup on mobile and desktop: logo, Menu dropdown, and CTA, without an expanding panel.

```tsx
"use client";

import { Button, buttonVariants } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils";

function Mark({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 18V6l8 7 8-7v12"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

function ChevronDownIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="m6 9 6 6 6-6"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

const links = ["Product", "Docs", "Pricing", "Changelog"] as const;

export function Navbar04() {
  return (
    <header className="@container w-full bg-background">
      <div className="flex w-full items-center justify-between gap-4 px-4 py-3">
        <a
          href="#"
          className="inline-flex items-center gap-2 text-foreground"
        >
          <Mark className="size-4" />
          <span className="text-sm tracking-wide">Acme</span>
        </a>

        <div className="flex items-center gap-1">
          <Button type="button" size="sm">
            Get started
          </Button>
          <DropdownMenu>
            <DropdownMenuTrigger
              aria-label="Menu"
              className={cn(
                buttonVariants({ variant: "ghost", size: "sm" }),
                "px-2 @[32rem]:px-3",
              )}
            >
              <span className="hidden @[32rem]:inline">Menu</span>
              <ChevronDownIcon className="size-3.5 opacity-60" />
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" className="w-44">
              <DropdownMenuGroup>
                {links.map((label) => (
                  <DropdownMenuItem key={label}>{label}</DropdownMenuItem>
                ))}
              </DropdownMenuGroup>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </div>
    </header>
  );
}
```

### Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add navbar-04
```

### Usage

```tsx
import { Navbar04 } from "@/components/blocks/navbar/navbar-04"
```

```tsx
<Navbar04 />
```

## Docs style

A docs-style nav with surface search, separators, an Install action, and a large-type mobile panel. It is self-contained, with no theme or GitHub chrome.

```tsx
"use client";

import { useState } from "react";

function Mark({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 18V6l8 7 8-7v12"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

function SearchIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <circle
        cx="11"
        cy="11"
        r="6.25"
        stroke="currentColor"
        strokeWidth="1.5"
      />
      <path
        d="M16.5 16.5 20 20"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

function NavSeparator() {
  return (
    <div className="h-4 w-px shrink-0 bg-foreground/20" aria-hidden="true" />
  );
}

function MenuTrigger({
  open,
  onClick,
}: {
  open: boolean;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      aria-expanded={open}
      aria-controls="navbar-05-menu"
      aria-label={open ? "Close menu" : "Open menu"}
      className="inline-flex size-8 items-center justify-center rounded-md bg-surface text-foreground"
    >
      <span className="relative block size-3.5" aria-hidden="true">
        <span
          className={`absolute right-0 left-0 h-px bg-current transition-all duration-300 ease-out ${
            open ? "top-1/2 -translate-y-1/2 rotate-45" : "top-[3px]"
          }`}
        />
        <span
          className={`absolute right-0 left-0 h-px bg-current transition-all duration-300 ease-out ${
            open ? "top-1/2 -translate-y-1/2 -rotate-45" : "top-[10px]"
          }`}
        />
      </span>
    </button>
  );
}

const links = [
  { label: "Docs", href: "#" },
  { label: "Components", href: "#" },
  { label: "Blocks", href: "#" },
] as const;

export function Navbar05() {
  const [open, setOpen] = useState(false);

  return (
    <header className="@container w-full bg-background px-4 py-3">
      <nav className="relative flex items-center" aria-label="main">
        <a
          href="#"
          className="inline-flex shrink-0 items-center gap-2 text-foreground"
        >
          <Mark className="size-4" />
          <span className="text-sm tracking-wide">Acme</span>
        </a>

        <ul className="ml-6 hidden items-center gap-0.5 @[40rem]:flex">
          {links.map((link) => (
            <li key={link.label}>
              <a
                href={link.href}
                className="block rounded-md px-2.5 py-1.5 text-sm font-normal tracking-wide text-foreground hover:bg-surface-hover"
              >
                {link.label}
              </a>
            </li>
          ))}
        </ul>

        <div className="ml-auto flex items-center justify-end gap-2">
          <button
            type="button"
            aria-label="Search"
            className="inline-flex h-8 items-center gap-2 rounded-md bg-surface px-2.5 text-sm font-normal tracking-wide text-foreground transition-colors duration-200 ease-out @[40rem]:w-44 @[40rem]:hover:bg-surface-hover"
          >
            <SearchIcon className="size-3.5 shrink-0" />
            <span className="hidden @[40rem]:inline">Search...</span>
          </button>

          <NavSeparator />

          <a
            href="#"
            className="inline-flex rounded-md bg-foreground px-3 py-1.5 text-sm font-normal tracking-wide text-background transition-opacity duration-200 ease-out hover:opacity-85"
          >
            Install
          </a>

          <div className="@[40rem]:hidden">
            <MenuTrigger open={open} onClick={() => setOpen((v) => !v)} />
          </div>
        </div>
      </nav>

      <div
        id="navbar-05-menu"
        className={`grid @[40rem]:hidden ${
          open ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
        } transition-[grid-template-rows] duration-300 ease-in-out`}
      >
        <div className="overflow-hidden">
          <div className="flex flex-col gap-1 pt-6 pb-2">
            <p className="pb-1 text-xs font-normal tracking-wide text-foreground/40">
              Menu
            </p>
            {links.map((link) => (
              <a
                key={link.label}
                href={link.href}
                className="py-2 text-2xl font-medium tracking-wide text-foreground"
              >
                {link.label}
              </a>
            ))}
          </div>
        </div>
      </div>
    </header>
  );
}
```

### Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add navbar-05
```

### Usage

```tsx
import { Navbar05 } from "@/components/blocks/navbar/navbar-05"
```

```tsx
<Navbar05 />
```

## Navigation menu

Built with `NavigationMenu` for hover and click panels, then condensed into an expandable menu on narrow widths.

```tsx
"use client";

import { useState, type ComponentPropsWithoutRef } from "react";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";
import { Button } from "@/components/ui/button";
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu";

function Mark({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 18V6l8 7 8-7v12"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

function MenuIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 7h16M4 12h16M4 17h16"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

function CloseIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M6 6l12 12M18 6L6 18"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

function ListItem({
  title,
  children,
  href,
  ...props
}: ComponentPropsWithoutRef<"li"> & { href: string; title: string }) {
  return (
    <li {...props}>
      <NavigationMenuLink href={href} className="items-start gap-0.5">
        <div className="flex flex-col gap-0.5">
          <div className="text-sm font-medium text-foreground">{title}</div>
          <p className="line-clamp-2 text-xs leading-snug text-muted-foreground">
            {children}
          </p>
        </div>
      </NavigationMenuLink>
    </li>
  );
}

const productLinks = [
  {
    title: "Overview",
    href: "#",
    description: "What Acme is and who it is for.",
  },
  {
    title: "Pricing",
    href: "#",
    description: "Plans for teams of every size.",
  },
  {
    title: "Changelog",
    href: "#",
    description: "What shipped this month.",
  },
] as const;

const resourceLinks = [
  {
    title: "Docs",
    href: "#",
    description: "Guides and API reference.",
  },
  {
    title: "Blog",
    href: "#",
    description: "Notes from the team.",
  },
  {
    title: "Customers",
    href: "#",
    description: "Stories from production.",
  },
] as const;

export function Navbar06() {
  const [open, setOpen] = useState(false);

  return (
    <header className="@container w-full bg-background">
      <div className="flex w-full items-center justify-between gap-4 px-4 py-3">
        <a
          href="#"
          className="inline-flex items-center gap-2 text-foreground"
        >
          <Mark className="size-4" />
          <span className="text-sm tracking-wide">Acme</span>
        </a>

        <div className="hidden min-w-0 flex-1 justify-center @[40rem]:flex">
          <NavigationMenu>
            <NavigationMenuList>
              <NavigationMenuItem>
                <NavigationMenuTrigger>Product</NavigationMenuTrigger>
                <NavigationMenuContent>
                  <ul className="grid w-[18rem] gap-0.5">
                    {productLinks.map((link) => (
                      <ListItem
                        key={link.title}
                        title={link.title}
                        href={link.href}
                      >
                        {link.description}
                      </ListItem>
                    ))}
                  </ul>
                </NavigationMenuContent>
              </NavigationMenuItem>
              <NavigationMenuItem>
                <NavigationMenuTrigger>Resources</NavigationMenuTrigger>
                <NavigationMenuContent>
                  <ul className="grid w-[14rem] gap-0.5">
                    {resourceLinks.map((link) => (
                      <ListItem
                        key={link.title}
                        title={link.title}
                        href={link.href}
                      >
                        {link.description}
                      </ListItem>
                    ))}
                  </ul>
                </NavigationMenuContent>
              </NavigationMenuItem>
              <NavigationMenuItem>
                <NavigationMenuLink
                  href="#"
                  className={navigationMenuTriggerStyle()}
                >
                  Pricing
                </NavigationMenuLink>
              </NavigationMenuItem>
            </NavigationMenuList>
          </NavigationMenu>
        </div>

        <div className="flex items-center gap-1">
          <Button
            type="button"
            size="sm"
            className="hidden @[40rem]:inline-flex"
          >
            Get started
          </Button>
          <Button
            type="button"
            size="icon-sm"
            variant="ghost"
            className={
              open
                ? "bg-accent text-accent-foreground @[40rem]:hidden"
                : "@[40rem]:hidden"
            }
            aria-label={open ? "Close menu" : "Open menu"}
            aria-expanded={open}
            onClick={() => setOpen((value) => !value)}
          >
            {open ? <CloseIcon /> : <MenuIcon />}
          </Button>
        </div>
      </div>

      {open ? (
        <div className="px-4 pb-3 @[40rem]:hidden">
          <Accordion type="multiple" collapsible className="w-full">
            <AccordionItem value="product" className="border-b-0">
              <AccordionTrigger className="py-2.5 text-sm font-normal">
                Product
              </AccordionTrigger>
              <AccordionContent>
                <div className="flex flex-col gap-0.5 pb-2">
                  {productLinks.map((link) => (
                    <a
                      key={link.title}
                      href={link.href}
                      className="rounded-md px-2 py-2 text-sm tracking-wide text-muted-foreground hover:bg-surface-hover hover:text-foreground"
                    >
                      {link.title}
                    </a>
                  ))}
                </div>
              </AccordionContent>
            </AccordionItem>
            <AccordionItem value="resources" className="border-b-0">
              <AccordionTrigger className="py-2.5 text-sm font-normal">
                Resources
              </AccordionTrigger>
              <AccordionContent>
                <div className="flex flex-col gap-0.5 pb-2">
                  {resourceLinks.map((link) => (
                    <a
                      key={link.title}
                      href={link.href}
                      className="rounded-md px-2 py-2 text-sm tracking-wide text-muted-foreground hover:bg-surface-hover hover:text-foreground"
                    >
                      {link.title}
                    </a>
                  ))}
                </div>
              </AccordionContent>
            </AccordionItem>
          </Accordion>
          <a
            href="#"
            className="flex items-center rounded-md py-2.5 text-sm tracking-wide text-foreground"
          >
            Pricing
          </a>
          <Button type="button" size="sm" className="mt-2 w-full">
            Get started
          </Button>
        </div>
      ) : null}
    </header>
  );
}
```

### Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add navbar-06
```

### Usage

```tsx
import { Navbar06 } from "@/components/blocks/navbar/navbar-06"
```

```tsx
<Navbar06 />
```
