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
1"use client";23import { useState } from "react";4import { Button } from "@/components/ui/button";56function Mark({ className }: { className?: string }) {7 return (8 <svg9 viewBox="0 0 24 24"10 fill="none"11 aria-hidden="true"12 className={className}13 >14 <path15 d="M4 18V6l8 7 8-7v12"16 stroke="currentColor"17 strokeWidth="1.5"18 strokeLinecap="round"19 strokeLinejoin="round"20 />21 </svg>22 );23}2425function MenuIcon({ className }: { className?: string }) {26 return (27 <svg28 viewBox="0 0 24 24"29 fill="none"30 aria-hidden="true"31 className={className}32 >33 <path34 d="M4 7h16M4 12h16M4 17h16"35 stroke="currentColor"36 strokeWidth="1.5"37 strokeLinecap="round"38 />39 </svg>40 );41}4243function CloseIcon({ className }: { className?: string }) {44 return (45 <svg46 viewBox="0 0 24 24"47 fill="none"48 aria-hidden="true"49 className={className}50 >51 <path52 d="M6 6l12 12M18 6L6 18"53 stroke="currentColor"54 strokeWidth="1.5"55 strokeLinecap="round"56 />57 </svg>58 );59}6061const links = ["Product", "Docs", "Pricing"] as const;6263export function Navbar01() {64 const [open, setOpen] = useState(false);6566 return (67 <header className="@container w-full bg-background">68 <div className="flex w-full items-center justify-between gap-4 px-4 py-3">69 <a70 href="#"71 className="inline-flex items-center gap-2 text-foreground"72 >73 <Mark className="size-4" />74 <span className="text-sm tracking-wide">Acme</span>75 </a>7677 <div className="flex items-center gap-1">78 <nav className="hidden items-center gap-1 @[32rem]:flex">79 {links.map((label) => (80 <Button key={label} type="button" variant="ghost" size="sm">81 {label}82 </Button>83 ))}84 </nav>85 <Button86 type="button"87 size="sm"88 className="hidden @[32rem]:inline-flex"89 >90 Get started91 </Button>92 <Button93 type="button"94 size="icon-sm"95 variant="ghost"96 className="@[32rem]:hidden"97 aria-label={open ? "Close menu" : "Open menu"}98 aria-expanded={open}99 onClick={() => setOpen((value) => !value)}100 >101 {open ? <CloseIcon /> : <MenuIcon />}102 </Button>103 </div>104 </div>105106 {open ? (107 <div className="flex flex-col gap-1 px-4 pb-3 @[32rem]:hidden">108 <nav className="flex flex-col gap-1">109 {links.map((label) => (110 <Button111 key={label}112 type="button"113 variant="ghost"114 size="sm"115 className="justify-start"116 >117 {label}118 </Button>119 ))}120 </nav>121 <Button type="button" size="sm" className="mt-1 w-full">122 Get started123 </Button>124 </div>125 ) : null}126 </header>127 );128}Installation
npx @arctis-sh/@arctis-sh/ui@latest add navbar-01Usage
1import { Navbar01 } from "@/components/blocks/navbar/navbar-01"1<Navbar01 />Floating
A muted, inset bar that floats away from the page edges, with the same links and mobile menu.
tsx
1"use client";23import { useState } from "react";4import { Button } from "@/components/ui/button";56function Mark({ className }: { className?: string }) {7 return (8 <svg9 viewBox="0 0 24 24"10 fill="none"11 aria-hidden="true"12 className={className}13 >14 <path15 d="M4 18V6l8 7 8-7v12"16 stroke="currentColor"17 strokeWidth="1.5"18 strokeLinecap="round"19 strokeLinejoin="round"20 />21 </svg>22 );23}2425function MenuIcon({ className }: { className?: string }) {26 return (27 <svg28 viewBox="0 0 24 24"29 fill="none"30 aria-hidden="true"31 className={className}32 >33 <path34 d="M4 7h16M4 12h16M4 17h16"35 stroke="currentColor"36 strokeWidth="1.5"37 strokeLinecap="round"38 />39 </svg>40 );41}4243function CloseIcon({ className }: { className?: string }) {44 return (45 <svg46 viewBox="0 0 24 24"47 fill="none"48 aria-hidden="true"49 className={className}50 >51 <path52 d="M6 6l12 12M18 6L6 18"53 stroke="currentColor"54 strokeWidth="1.5"55 strokeLinecap="round"56 />57 </svg>58 );59}6061const links = ["Product", "Docs", "Pricing"] as const;6263export function Navbar02() {64 const [open, setOpen] = useState(false);6566 return (67 <header className="@container w-full px-3 pt-3">68 <div className="mx-auto w-full max-w-5xl rounded-md bg-muted">69 <div className="flex w-full items-center justify-between gap-4 px-3 py-2.5">70 <a71 href="#"72 className="inline-flex items-center gap-2 text-foreground"73 >74 <Mark className="size-4" />75 <span className="text-sm tracking-wide">Acme</span>76 </a>7778 <div className="flex items-center gap-1">79 <nav className="hidden items-center gap-1 @[32rem]:flex">80 {links.map((label) => (81 <Button key={label} type="button" variant="ghost" size="sm">82 {label}83 </Button>84 ))}85 </nav>86 <Button87 type="button"88 size="sm"89 className="hidden @[32rem]:inline-flex"90 >91 Get started92 </Button>93 <Button94 type="button"95 size="icon-sm"96 variant="ghost"97 className="@[32rem]:hidden"98 aria-label={open ? "Close menu" : "Open menu"}99 aria-expanded={open}100 onClick={() => setOpen((value) => !value)}101 >102 {open ? <CloseIcon /> : <MenuIcon />}103 </Button>104 </div>105 </div>106107 {open ? (108 <div className="flex flex-col gap-1 px-3 pb-3 @[32rem]:hidden">109 <nav className="flex flex-col gap-1">110 {links.map((label) => (111 <Button112 key={label}113 type="button"114 variant="ghost"115 size="sm"116 className="justify-start"117 >118 {label}119 </Button>120 ))}121 </nav>122 <Button type="button" size="sm" className="mt-1 w-full">123 Get started124 </Button>125 </div>126 ) : null}127 </div>128 </header>129 );130}Installation
npx @arctis-sh/@arctis-sh/ui@latest add navbar-02Usage
1import { Navbar02 } from "@/components/blocks/navbar/navbar-02"1<Navbar02 />Centered links
Logo left, navigation centered, and an action on the right. The mobile menu expands below.
tsx
1"use client";23import { useState } from "react";4import { Button } from "@/components/ui/button";56function Mark({ className }: { className?: string }) {7 return (8 <svg9 viewBox="0 0 24 24"10 fill="none"11 aria-hidden="true"12 className={className}13 >14 <path15 d="M4 18V6l8 7 8-7v12"16 stroke="currentColor"17 strokeWidth="1.5"18 strokeLinecap="round"19 strokeLinejoin="round"20 />21 </svg>22 );23}2425function MenuIcon({ className }: { className?: string }) {26 return (27 <svg28 viewBox="0 0 24 24"29 fill="none"30 aria-hidden="true"31 className={className}32 >33 <path34 d="M4 7h16M4 12h16M4 17h16"35 stroke="currentColor"36 strokeWidth="1.5"37 strokeLinecap="round"38 />39 </svg>40 );41}4243function CloseIcon({ className }: { className?: string }) {44 return (45 <svg46 viewBox="0 0 24 24"47 fill="none"48 aria-hidden="true"49 className={className}50 >51 <path52 d="M6 6l12 12M18 6L6 18"53 stroke="currentColor"54 strokeWidth="1.5"55 strokeLinecap="round"56 />57 </svg>58 );59}6061const links = ["Product", "Docs", "Pricing"] as const;6263export function Navbar03() {64 const [open, setOpen] = useState(false);6566 return (67 <header className="@container w-full bg-background">68 <div className="grid w-full grid-cols-[1fr_auto] items-center gap-4 px-4 py-3 @[32rem]:grid-cols-[1fr_auto_1fr]">69 <a70 href="#"71 className="inline-flex items-center gap-2 justify-self-start text-foreground"72 >73 <Mark className="size-4" />74 <span className="text-sm tracking-wide">Acme</span>75 </a>7677 <nav className="hidden items-center gap-1 justify-self-center @[32rem]:flex">78 {links.map((label) => (79 <Button key={label} type="button" variant="ghost" size="sm">80 {label}81 </Button>82 ))}83 </nav>8485 <div className="flex items-center gap-1 justify-self-end">86 <Button87 type="button"88 size="sm"89 className="hidden @[32rem]:inline-flex"90 >91 Get started92 </Button>93 <Button94 type="button"95 size="icon-sm"96 variant="ghost"97 className="@[32rem]:hidden"98 aria-label={open ? "Close menu" : "Open menu"}99 aria-expanded={open}100 onClick={() => setOpen((value) => !value)}101 >102 {open ? <CloseIcon /> : <MenuIcon />}103 </Button>104 </div>105 </div>106107 {open ? (108 <div className="flex flex-col gap-1 px-4 pb-3 @[32rem]:hidden">109 <nav className="flex flex-col gap-1">110 {links.map((label) => (111 <Button112 key={label}113 type="button"114 variant="ghost"115 size="sm"116 className="justify-start"117 >118 {label}119 </Button>120 ))}121 </nav>122 <Button type="button" size="sm" className="mt-1 w-full">123 Get started124 </Button>125 </div>126 ) : null}127 </header>128 );129}Installation
npx @arctis-sh/@arctis-sh/ui@latest add navbar-03Usage
1import { Navbar03 } from "@/components/blocks/navbar/navbar-03"1<Navbar03 />Menu dropdown
The same compact setup on mobile and desktop: logo, Menu dropdown, and CTA, without an expanding panel.
tsx
1"use client";23import { Button, buttonVariants } from "@/components/ui/button";4import {5 DropdownMenu,6 DropdownMenuContent,7 DropdownMenuGroup,8 DropdownMenuItem,9 DropdownMenuTrigger,10} from "@/components/ui/dropdown-menu";11import { cn } from "@/lib/utils";1213function Mark({ className }: { className?: string }) {14 return (15 <svg16 viewBox="0 0 24 24"17 fill="none"18 aria-hidden="true"19 className={className}20 >21 <path22 d="M4 18V6l8 7 8-7v12"23 stroke="currentColor"24 strokeWidth="1.5"25 strokeLinecap="round"26 strokeLinejoin="round"27 />28 </svg>29 );30}3132function ChevronDownIcon({ className }: { className?: string }) {33 return (34 <svg35 viewBox="0 0 24 24"36 fill="none"37 aria-hidden="true"38 className={className}39 >40 <path41 d="m6 9 6 6 6-6"42 stroke="currentColor"43 strokeWidth="1.5"44 strokeLinecap="round"45 strokeLinejoin="round"46 />47 </svg>48 );49}5051const links = ["Product", "Docs", "Pricing", "Changelog"] as const;5253export function Navbar04() {54 return (55 <header className="@container w-full bg-background">56 <div className="flex w-full items-center justify-between gap-4 px-4 py-3">57 <a58 href="#"59 className="inline-flex items-center gap-2 text-foreground"60 >61 <Mark className="size-4" />62 <span className="text-sm tracking-wide">Acme</span>63 </a>6465 <div className="flex items-center gap-1">66 <Button type="button" size="sm">67 Get started68 </Button>69 <DropdownMenu>70 <DropdownMenuTrigger71 aria-label="Menu"72 className={cn(73 buttonVariants({ variant: "ghost", size: "sm" }),74 "px-2 @[32rem]:px-3",75 )}76 >77 <span className="hidden @[32rem]:inline">Menu</span>78 <ChevronDownIcon className="size-3.5 opacity-60" />79 </DropdownMenuTrigger>80 <DropdownMenuContent align="end" className="w-44">81 <DropdownMenuGroup>82 {links.map((label) => (83 <DropdownMenuItem key={label}>{label}</DropdownMenuItem>84 ))}85 </DropdownMenuGroup>86 </DropdownMenuContent>87 </DropdownMenu>88 </div>89 </div>90 </header>91 );92}Installation
npx @arctis-sh/@arctis-sh/ui@latest add navbar-04Usage
1import { Navbar04 } from "@/components/blocks/navbar/navbar-04"1<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
1"use client";23import { useState } from "react";45function Mark({ className }: { className?: string }) {6 return (7 <svg8 viewBox="0 0 24 24"9 fill="none"10 aria-hidden="true"11 className={className}12 >13 <path14 d="M4 18V6l8 7 8-7v12"15 stroke="currentColor"16 strokeWidth="1.5"17 strokeLinecap="round"18 strokeLinejoin="round"19 />20 </svg>21 );22}2324function SearchIcon({ className }: { className?: string }) {25 return (26 <svg27 viewBox="0 0 24 24"28 fill="none"29 aria-hidden="true"30 className={className}31 >32 <circle33 cx="11"34 cy="11"35 r="6.25"36 stroke="currentColor"37 strokeWidth="1.5"38 />39 <path40 d="M16.5 16.5 20 20"41 stroke="currentColor"42 strokeWidth="1.5"43 strokeLinecap="round"44 />45 </svg>46 );47}4849function NavSeparator() {50 return (51 <div className="h-4 w-px shrink-0 bg-foreground/20" aria-hidden="true" />52 );53}5455function MenuTrigger({56 open,57 onClick,58}: {59 open: boolean;60 onClick: () => void;61}) {62 return (63 <button64 type="button"65 onClick={onClick}66 aria-expanded={open}67 aria-controls="navbar-05-menu"68 aria-label={open ? "Close menu" : "Open menu"}69 className="inline-flex size-8 items-center justify-center rounded-md bg-surface text-foreground"70 >71 <span className="relative block size-3.5" aria-hidden="true">72 <span73 className={`absolute right-0 left-0 h-px bg-current transition-all duration-300 ease-out ${74 open ? "top-1/2 -translate-y-1/2 rotate-45" : "top-[3px]"75 }`}76 />77 <span78 className={`absolute right-0 left-0 h-px bg-current transition-all duration-300 ease-out ${79 open ? "top-1/2 -translate-y-1/2 -rotate-45" : "top-[10px]"80 }`}81 />82 </span>83 </button>84 );85}8687const links = [88 { label: "Docs", href: "#" },89 { label: "Components", href: "#" },90 { label: "Blocks", href: "#" },91] as const;9293export function Navbar05() {94 const [open, setOpen] = useState(false);9596 return (97 <header className="@container w-full bg-background px-4 py-3">98 <nav className="relative flex items-center" aria-label="main">99 <a100 href="#"101 className="inline-flex shrink-0 items-center gap-2 text-foreground"102 >103 <Mark className="size-4" />104 <span className="text-sm tracking-wide">Acme</span>105 </a>106107 <ul className="ml-6 hidden items-center gap-0.5 @[40rem]:flex">108 {links.map((link) => (109 <li key={link.label}>110 <a111 href={link.href}112 className="block rounded-md px-2.5 py-1.5 text-sm font-normal tracking-wide text-foreground hover:bg-surface-hover"113 >114 {link.label}115 </a>116 </li>117 ))}118 </ul>119120 <div className="ml-auto flex items-center justify-end gap-2">121 <button122 type="button"123 aria-label="Search"124 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"125 >126 <SearchIcon className="size-3.5 shrink-0" />127 <span className="hidden @[40rem]:inline">Search...</span>128 </button>129130 <NavSeparator />131132 <a133 href="#"134 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"135 >136 Install137 </a>138139 <div className="@[40rem]:hidden">140 <MenuTrigger open={open} onClick={() => setOpen((v) => !v)} />141 </div>142 </div>143 </nav>144145 <div146 id="navbar-05-menu"147 className={`grid @[40rem]:hidden ${148 open ? "grid-rows-[1fr]" : "grid-rows-[0fr]"149 } transition-[grid-template-rows] duration-300 ease-in-out`}150 >151 <div className="overflow-hidden">152 <div className="flex flex-col gap-1 pt-6 pb-2">153 <p className="pb-1 text-xs font-normal tracking-wide text-foreground/40">154 Menu155 </p>156 {links.map((link) => (157 <a158 key={link.label}159 href={link.href}160 className="py-2 text-2xl font-medium tracking-wide text-foreground"161 >162 {link.label}163 </a>164 ))}165 </div>166 </div>167 </div>168 </header>169 );170}Installation
npx @arctis-sh/@arctis-sh/ui@latest add navbar-05Usage
1import { Navbar05 } from "@/components/blocks/navbar/navbar-05"1<Navbar05 />Navigation menu
Built with NavigationMenu for hover and click panels, then condensed into an expandable menu on narrow widths.
tsx
1"use client";23import { useState, type ComponentPropsWithoutRef } from "react";4import {5 Accordion,6 AccordionContent,7 AccordionItem,8 AccordionTrigger,9} from "@/components/ui/accordion";10import { Button } from "@/components/ui/button";11import {12 NavigationMenu,13 NavigationMenuContent,14 NavigationMenuItem,15 NavigationMenuLink,16 NavigationMenuList,17 NavigationMenuTrigger,18 navigationMenuTriggerStyle,19} from "@/components/ui/navigation-menu";2021function Mark({ className }: { className?: string }) {22 return (23 <svg24 viewBox="0 0 24 24"25 fill="none"26 aria-hidden="true"27 className={className}28 >29 <path30 d="M4 18V6l8 7 8-7v12"31 stroke="currentColor"32 strokeWidth="1.5"33 strokeLinecap="round"34 strokeLinejoin="round"35 />36 </svg>37 );38}3940function MenuIcon({ className }: { className?: string }) {41 return (42 <svg43 viewBox="0 0 24 24"44 fill="none"45 aria-hidden="true"46 className={className}47 >48 <path49 d="M4 7h16M4 12h16M4 17h16"50 stroke="currentColor"51 strokeWidth="1.5"52 strokeLinecap="round"53 />54 </svg>55 );56}5758function CloseIcon({ className }: { className?: string }) {59 return (60 <svg61 viewBox="0 0 24 24"62 fill="none"63 aria-hidden="true"64 className={className}65 >66 <path67 d="M6 6l12 12M18 6L6 18"68 stroke="currentColor"69 strokeWidth="1.5"70 strokeLinecap="round"71 />72 </svg>73 );74}7576function ListItem({77 title,78 children,79 href,80 ...props81}: ComponentPropsWithoutRef<"li"> & { href: string; title: string }) {82 return (83 <li {...props}>84 <NavigationMenuLink href={href} className="items-start gap-0.5">85 <div className="flex flex-col gap-0.5">86 <div className="text-sm font-medium text-foreground">{title}</div>87 <p className="line-clamp-2 text-xs leading-snug text-muted-foreground">88 {children}89 </p>90 </div>91 </NavigationMenuLink>92 </li>93 );94}9596const productLinks = [97 {98 title: "Overview",99 href: "#",100 description: "What Acme is and who it is for.",101 },102 {103 title: "Pricing",104 href: "#",105 description: "Plans for teams of every size.",106 },107 {108 title: "Changelog",109 href: "#",110 description: "What shipped this month.",111 },112] as const;113114const resourceLinks = [115 {116 title: "Docs",117 href: "#",118 description: "Guides and API reference.",119 },120 {121 title: "Blog",122 href: "#",123 description: "Notes from the team.",124 },125 {126 title: "Customers",127 href: "#",128 description: "Stories from production.",129 },130] as const;131132export function Navbar06() {133 const [open, setOpen] = useState(false);134135 return (136 <header className="@container w-full bg-background">137 <div className="flex w-full items-center justify-between gap-4 px-4 py-3">138 <a139 href="#"140 className="inline-flex items-center gap-2 text-foreground"141 >142 <Mark className="size-4" />143 <span className="text-sm tracking-wide">Acme</span>144 </a>145146 <div className="hidden min-w-0 flex-1 justify-center @[40rem]:flex">147 <NavigationMenu>148 <NavigationMenuList>149 <NavigationMenuItem>150 <NavigationMenuTrigger>Product</NavigationMenuTrigger>151 <NavigationMenuContent>152 <ul className="grid w-[18rem] gap-0.5">153 {productLinks.map((link) => (154 <ListItem155 key={link.title}156 title={link.title}157 href={link.href}158 >159 {link.description}160 </ListItem>161 ))}162 </ul>163 </NavigationMenuContent>164 </NavigationMenuItem>165 <NavigationMenuItem>166 <NavigationMenuTrigger>Resources</NavigationMenuTrigger>167 <NavigationMenuContent>168 <ul className="grid w-[14rem] gap-0.5">169 {resourceLinks.map((link) => (170 <ListItem171 key={link.title}172 title={link.title}173 href={link.href}174 >175 {link.description}176 </ListItem>177 ))}178 </ul>179 </NavigationMenuContent>180 </NavigationMenuItem>181 <NavigationMenuItem>182 <NavigationMenuLink183 href="#"184 className={navigationMenuTriggerStyle()}185 >186 Pricing187 </NavigationMenuLink>188 </NavigationMenuItem>189 </NavigationMenuList>190 </NavigationMenu>191 </div>192193 <div className="flex items-center gap-1">194 <Button195 type="button"196 size="sm"197 className="hidden @[40rem]:inline-flex"198 >199 Get started200 </Button>201 <Button202 type="button"203 size="icon-sm"204 variant="ghost"205 className={206 open207 ? "bg-accent text-accent-foreground @[40rem]:hidden"208 : "@[40rem]:hidden"209 }210 aria-label={open ? "Close menu" : "Open menu"}211 aria-expanded={open}212 onClick={() => setOpen((value) => !value)}213 >214 {open ? <CloseIcon /> : <MenuIcon />}215 </Button>216 </div>217 </div>218219 {open ? (220 <div className="px-4 pb-3 @[40rem]:hidden">221 <Accordion type="multiple" collapsible className="w-full">222 <AccordionItem value="product" className="border-b-0">223 <AccordionTrigger className="py-2.5 text-sm font-normal">224 Product225 </AccordionTrigger>226 <AccordionContent>227 <div className="flex flex-col gap-0.5 pb-2">228 {productLinks.map((link) => (229 <a230 key={link.title}231 href={link.href}232 className="rounded-md px-2 py-2 text-sm tracking-wide text-muted-foreground hover:bg-surface-hover hover:text-foreground"233 >234 {link.title}235 </a>236 ))}237 </div>238 </AccordionContent>239 </AccordionItem>240 <AccordionItem value="resources" className="border-b-0">241 <AccordionTrigger className="py-2.5 text-sm font-normal">242 Resources243 </AccordionTrigger>244 <AccordionContent>245 <div className="flex flex-col gap-0.5 pb-2">246 {resourceLinks.map((link) => (247 <a248 key={link.title}249 href={link.href}250 className="rounded-md px-2 py-2 text-sm tracking-wide text-muted-foreground hover:bg-surface-hover hover:text-foreground"251 >252 {link.title}253 </a>254 ))}255 </div>256 </AccordionContent>257 </AccordionItem>258 </Accordion>259 <a260 href="#"261 className="flex items-center rounded-md py-2.5 text-sm tracking-wide text-foreground"262 >263 Pricing264 </a>265 <Button type="button" size="sm" className="mt-2 w-full">266 Get started267 </Button>268 </div>269 ) : null}270 </header>271 );272}Installation
npx @arctis-sh/@arctis-sh/ui@latest add navbar-06Usage
1import { Navbar06 } from "@/components/blocks/navbar/navbar-06"1<Navbar06 />