Navbar
ProA composable top navigation bar for marketing, product and ecommerce shells. Layout is composition, not configuration: a NavbarSpacer pushes groups apart. Collapses to a hamburger disclosure below md.
Installation#
Usage#
The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.
Have a license? Unlock it here
Anatomy#
import {
Navbar,
NavbarInner,
NavbarBrand,
NavbarNav,
NavbarLink,
NavbarSearch,
NavbarSpacer,
NavbarActions,
NavbarMobileToggle,
NavbarMobileMenu,
NavbarMobileLink,
NavbarMobileActions,
} from "@/components/ui/navbar"
<Navbar>
<NavbarInner>
<NavbarBrand />
<NavbarNav>
<NavbarLink />
</NavbarNav>
<NavbarSpacer />
<NavbarSearch />
<NavbarActions>…</NavbarActions>
<NavbarMobileToggle />
</NavbarInner>
<NavbarMobileMenu>
<NavbarMobileLink />
<NavbarMobileActions>…</NavbarMobileActions>
</NavbarMobileMenu>
</Navbar>Floating#
variant="floating" detaches the bar into a rounded card that hovers over the page. Give it top margin and a background to float over.
Floating island#
Release the width cap with w-fit max-w-none and the floating card stops stretching: it shrinks to its content and the recipe's own mx-auto centers it, so the whole bar becomes a compact pill hovering over the page. Best with a short link set and one CTA.
Underline links#
linkStyle changes what a link is, which is the one thing composition cannot express. The default, "pill", makes each link a ghost chip floating in the bar: bg-accent on hover in the light themes, a faint foreground/8 tint in the dark ones, where the accent would read as a heavy grey block. "underline" makes it a tab: the box fills the bar's full height so its indicator, a square 3px foreground stroke spanning the whole box, welds to the bar's bottom rule (ink, not brand: at full width it is already the loudest mark in the row). Hover previews that indicator in border instead of painting a full-height chip.
Text links#
"text" makes each link a plain word: no chip, no stroke. Links rest in muted-foreground and light up to full ink on hover and while their menu is open, so the only thing that moves is the label's color. The current page is simply the link that stays lit, and a page that is not live yet dims one step below its siblings.
Many links#
A marketing bar that carries six links and two actions runs out of row long before the md breakpoint where the hamburger normally takes over, so on a tablet it would overflow or wrap. collapseAt="lg" moves the handover to 1024px: the inline nav, the toggle and the mobile panel switch together. A page that is not live yet renders as a <span aria-disabled> through asChild: muted, inert to the pointer, and paired with a small Badge.
Elevate on scroll#
elevateOnScroll rests the bar flat, borderless and shadowless, flush with the content, then brings its border and shadow in together the moment the page scrolls under it. Pair it with sticky top-0. The bar listens to the nearest scroll container, so it works on a page or inside a panel; scroll the preview to see it engage.
Alignment#
There is no alignment prop. A NavbarSpacer pushes the groups on either side of it apart, which pins the nav to the right. To truly center it, swap the bar for a three-column grid: spacers would only center the nav between the brand and the actions, leaving it off the bar's centreline by half the difference in their widths.
Dropdown links#
A link that opens a menu is a NavbarLink wrapped in the standard DropdownMenu. The caret flips when its menu opens.
Open on hover, fluid between links#
Swap the click-triggered DropdownMenu for a NavigationMenu when the bar carries more than one dropdown link. It opens on hover, and every trigger shares one panel: moving from “Product” to “Resources” resizes it instead of swapping popovers.
Search#
NavbarSearch is the DS Input with a leading magnifier. Set a width like w-64 for a normal field, or flex-1 to fill the center of the bar. Add collapsible and it rests as one of the bar's icon chips instead, growing into the same field on click (an ExpandableSearch): the choice for a bar whose links need the room until someone searches.
Product app shell#
A compact bar with a global search and an account cluster. Pass bg-muted border-transparent to NavbarSearch for the pill look, and drop an Avatar into NavbarActions. To make it the header of a whole app, put it in a LayoutTopbar: it docks onto the shell and spans the window.
Toolbar#
Drop the brand and the links and the same parts become a toolbar: the view's controls on the left, its actions on the right. This is the bar that sits under an app shell's real header. Fold navigation back in and it takes the three-column grid, so controls, tabs, and account each hold their own third.
Logo in the middle#
A 3-column grid on NavbarInner centers the brand independently of the side groups: links left, logo centered, actions right.
Multiple actions#
Stack two quiet outline actions and a solid primary in NavbarActions for a stronger conversion path. Give the secondaries a hidden sm:inline-flex so they shed themselves as the bar narrows and the primary always survives.
Badge beside the brand#
Group a Badge next to NavbarBrand to flag a beta, plan, or environment.
Ecommerce#
The same parts build a storefront header, with two conventions of its own: the links go uppercase and wide-tracked, and the marketing CTAs give way to the search, account, and cart trio. Unlike a marketing CTA the trio stays in the bar at every width, because the cart is the one control a shopper must never have to go looking for. Both are composition, so no variant is involved: the brand can lead, or the catalogue can, with the mark on the centreline.
Density#
density tightens the bar height and gutters for application shells. Set it per navbar or for a whole subtree with DensityProvider. See Density.
API reference#
Navbar
The root <header>: owns the mobile disclosure and gives every part its styling. Forwards all <header> props. Every part accepts className, merged last.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "full" | "floating" | "full" | full is an edge-to-edge bar over a hairline; floating detaches it into a rounded card. |
| linkStyle | "pill" | "underline" | "text" | "pill" | Ghost chips with an ink underline, full-height tabs whose ink stroke welds to the bottom rule, or plain muted words that light up. |
| density | "comfortable" | "compact" | - | Bar height, 64 or 56px. Inherits the nearest DensityProvider (compact with none) when unset. |
| collapseAt | "md" | "lg" | "xl" | "md" | Where the inline links hand over to the hamburger. Six links and two actions want lg; seven, or long labels, xl. |
| mobileMenu | "inline" | "overlay" | "inline" | inline drops the links into the header's flow. overlay fills the screen under the bar, locks the page, closes on Escape and pins NavbarMobileActions to the bottom. |
| elevateOnScroll | boolean | false | Rests flat and gains its border and shadow once its scroll container moves. |
| docked | boolean | - | Sits on an app shell's surface: no fill, no bottom rule, a full-width row. Inherited inside a LayoutTopbar, else false. |
| open | boolean | - | The mobile menu's open state, controlled. |
| defaultOpen | boolean | false | The mobile menu's initial state, uncontrolled. |
| onOpenChange | (open: boolean) => void | - | Called when the mobile menu opens or closes. |
| Data attribute | Description |
|---|---|
| data-mobile-menu | open or closed. |
| data-scrolled | Present once the page scrolls under an elevateOnScroll bar. |
| data-navbar-menu | Set to open on <html> while an overlay menu is open, so a floating widget can step aside. |
NavbarInner
The max-width row holding brand, nav, spacers, actions and toggle. Forwards native <div> props.
NavbarBrand
The logo lockup. Renders an <a> and forwards all its props.
| Prop | Type | Default | Description |
|---|---|---|---|
| asChild | boolean | false | Renders the child (a framework Link) as the brand. |
NavbarNav
The inline link list, a <nav> labelled Main unless you pass aria-label. Hidden below collapseAt.
NavbarLink
A link in the bar, shaped by the root's linkStyle. Renders an <a>; aria-disabled turns a page that is not live yet muted and inert.
| Prop | Type | Default | Description |
|---|---|---|---|
| active | boolean | false | The current page: full ink, the style's indicator, and aria-current="page". |
| asChild | boolean | false | Renders the child (a framework Link, a menu trigger, a <span> for a page not live yet) as the link. |
| Data attribute | Description |
|---|---|
| data-active | Present when active. |
| data-state | open while a menu it triggers is open (set by the trigger); the caret flips. |
NavbarSearch
The DS Input with a leading magnifier and a default width. Forwards InputRoot props (size, hasError); children sit at the field's end, e.g. a Kbd hint.
| Prop | Type | Default | Description |
|---|---|---|---|
| placeholder | string | "Search" | Also the field's aria-label. |
| inputProps | InputFieldProps | - | Reaches the <input>: value, onChange, name. |
| size | "sm" | "md" | "lg" | "sm" | Field height; md when collapsible. |
| collapsible | boolean | false | Rests as a 36px icon chip that grows into the field on click (an ExpandableSearch); className sets the open width. |
| open | boolean | - | A collapsible search's open state, controlled. |
| defaultOpen | boolean | false | A collapsible search's initial state. |
| onOpenChange | (open: boolean) => void | - | Called when a collapsible search expands or collapses. |
NavbarSpacer
A flexible gap that pushes the groups on either side apart. aria-hidden. Forwards native <div> props.
NavbarActions
The right-hand cluster; a run of icon-only buttons sits flush as one strip. Forwards native <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "sm" | "md" | "lg" | "sm" | Control size imposed on the buttons inside. |
| Data attribute | Description |
|---|---|
| data-control-size | The imposed size. |
NavbarMobileToggle
The hamburger, visible only below collapseAt. Renders a <button> with aria-expanded and forwards its props.
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | "Toggle menu" | The accessible name. |
| Data attribute | Description |
|---|---|
| data-state | open or closed, morphing the glyph. |
NavbarMobileMenu
The disclosed panel of stacked links. Mounts only while open and closes on Escape. Forwards native <div> props.
| CSS variable | Description |
|---|---|
| --navbar-menu-top | Under overlay: the bar's bottom edge, where the full-screen panel starts. |
NavbarMobileLink
A stacked link in the mobile panel: a 56px row under overlay, 44px inside an AccordionContent. Renders an <a>.
| Prop | Type | Default | Description |
|---|---|---|---|
| active | boolean | false | The current page: full ink, the style's indicator, and aria-current="page". |
| asChild | boolean | false | Renders the child (a framework Link, a menu trigger, a <span> for a page not live yet) as the link. |
| Data attribute | Description |
|---|---|
| data-active | Present when active. |
NavbarMobileActions
The panel's closing call to action (Log in, Buy now). Pinned to the screen's bottom under overlay. Forwards native <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "sm" | "md" | "lg" | "lg" | Control size imposed on the buttons inside. |