HeroUI Pro

Navbar

A composable top navigation bar with hide-on-scroll, responsive mobile menu, and client-side routing support.

Usage

Docs Site

A docs-site style navbar with a search bar, theme segment, and responsive mobile menu.

With Dropdowns

SaaS-style navbar with a team switcher, user dropdown, and mobile menu.

Dashboard

Breadcrumb-style dashboard navbar built with InlineSelect for the workspace, project, and timezone selectors.

Compact

A dense navbar tuned via --spacing and height overrides for a Luma-style compact layout.

With Menu

Responsive navbar with a mobile hamburger toggle and animated dropdown menu.

Hide on Scroll

Pass hideOnScroll to hide the navbar when the user scrolls down and reveal it on scroll up.

Responsive Mobile Menu

Navbar.MenuToggle and Navbar.Menu provide a built-in mobile dropdown. Use hidden md:flex on desktop-only groups and keep the toggle visible below the breakpoint:

<Navbar>
  <Navbar.Header>
    <Navbar.MenuToggle className="md:hidden" />
    <Navbar.Brand>…</Navbar.Brand>

    {/* Desktop-only nav */}
    <Navbar.Content className="hidden md:flex">
      <Navbar.Item href="/features">Features</Navbar.Item>
      <Navbar.Item href="/pricing">Pricing</Navbar.Item>
    </Navbar.Content>
  </Navbar.Header>

  {/* Mobile-only menu — animates in when the toggle is pressed */}
  <Navbar.Menu>
    <Navbar.MenuItem href="/features">Features</Navbar.MenuItem>
    <Navbar.MenuItem href="/pricing">Pricing</Navbar.MenuItem>
  </Navbar.Menu>
</Navbar>

The menu open state can be controlled via isMenuOpen / onMenuOpenChange on Navbar, or uncontrolled via defaultMenuOpen. By default the navbar locks body scroll while the menu is open — pass shouldBlockScroll={false} to disable.

Compact Density

Scale the entire navbar (paddings, gaps, icon sizes) by overriding the Tailwind v4 --spacing variable on the navbar or a wrapper, and tune the bar height with the height prop:

<Navbar
  height="2.75rem"
  size="sm"
  style={{"--spacing": "0.22rem"} as React.CSSProperties}
>

</Navbar>
  • --spacing scales every Tailwind spacing utility (gap-*, p-*, size-*) inside the navbar
  • height overrides the internal --navbar-height CSS variable
  • size="sm" applies the built-in compact text + padding variants

Client-Side Routing

Navbar.Item renders a real <a> element when href is set (and Navbar.MenuItem does the same for the mobile menu), so it works with any router. You have two ways to integrate client-side routing:

Pass your router's push function to Navbar. Every Navbar.Item / Navbar.MenuItem with an href will route through it, preventing full-page reloads.

Next.js (App Router)

"use client";

import { useRouter } from "next/navigation";
import { Navbar } from "@heroui-pro/react";

export function AppNavbar() {
  const router = useRouter();

  return (
    <Navbar navigate={router.push}>
      <Navbar.Header>
        <Navbar.Brand>Acme</Navbar.Brand>
        <Navbar.Content>
          <Navbar.Item href="/features">Features</Navbar.Item>
          <Navbar.Item href="/pricing">Pricing</Navbar.Item>
        </Navbar.Content>
      </Navbar.Header>
    </Navbar>
  );
}

React Router

import { useNavigate } from "react-router";
import { Navbar } from "@heroui-pro/react";

export function AppNavbar() {
  const navigate = useNavigate();

  return (
    <Navbar navigate={navigate}>
      {/* ... */}
    </Navbar>
  );
}

TanStack Router

import { useRouter } from "@tanstack/react-router";
import { Navbar } from "@heroui-pro/react";

export function AppNavbar() {
  const router = useRouter();

  return (
    <Navbar navigate={(href) => router.navigate({ to: href })}>
      {/* ... */}
    </Navbar>
  );
}

Since Navbar.Item and Navbar.MenuItem are polymorphic, you can swap the rendered element entirely to use a framework-specific <Link> component (preserving prefetch, scroll restoration, and any router-level behaviors):

import Link from "next/link";
import { Navbar } from "@heroui-pro/react";

export function AppNavbar() {
  return (
    <Navbar>
      <Navbar.Header>
        <Navbar.Content>
          <Navbar.Item
            href="/features"
            render={(props) => <Link href="/features" {...props} />}
          >
            Features
          </Navbar.Item>
        </Navbar.Content>
      </Navbar.Header>
    </Navbar>
  );
}

Same works for Navbar.MenuItem in the mobile menu and for React Router's Link, TanStack Router's Link, etc.

Combine both approaches if you like — render owns the element/prefetch, and navigate is used as the fallback for programmatic navigations (e.g. closing the mobile menu and pushing to the href).

External URLs (starting with http:// or https://) are automatically opened in a new tab via window.open(href, "_blank", "noopener,noreferrer"). For internal links that need a full page reload instead of client-side navigation, use the forceReload prop:

<Navbar.Item href="https://github.com/heroui-inc/heroui">GitHub</Navbar.Item>

<Navbar.Item href="/legacy-page" forceReload>Legacy page</Navbar.Item>

If no navigate function is provided, href falls back to the browser's default navigation.

Positioning

Use the position prop to control how the navbar is anchored:

  • "sticky" (default) — sticks to the top of its scroll container (sticky top-0)
  • "static" — flows inline with the page
  • "floating" — sticky, but detached from the edges with rounded corners, margin, border, and a shadow
<Navbar position="floating" maxWidth="xl">…</Navbar>

Programmatic Control

Use the useNavbar hook inside children of Navbar for programmatic access to the menu state and scroll-hidden state:

import { useNavbar } from "@heroui-pro/react";

function CloseMenuButton() {
  const { isMenuOpen, setMenuOpen } = useNavbar();

  return (
    <Button onPress={() => setMenuOpen(false)} isDisabled={!isMenuOpen}>
      Close menu
    </Button>
  );
}

CSS Classes

Base & Variant Classes

  • .navbar — Root <nav> element. Flex column, bg-background, z-40.
  • .navbar--sticky — Sticky to the top of the scroll container.
  • .navbar--static — Inline positioning.
  • .navbar--floating — Sticky, detached with rounded-2xl, border, shadow-surface, and mx-2.
  • .navbar[data-hidden="true"] — Applied while the navbar is hidden via hideOnScroll.
  • .navbar[data-menu-open="true"] — Applied while the mobile menu is open.

Layout Classes

  • .navbar__header — Horizontal bar wrapper. flex items-center gap-4 px-6, clamped by --navbar-max-width and --navbar-height.
  • .navbar__header--max-sm|md|lg|xl|2xl|full — Sets --navbar-max-width to 640px / 768px / 1024px / 1280px / 1536px / 100%.
  • .navbar__header--sm|md|lg — Size variants that tune --navbar-height and header padding.
  • .navbar__brand — Logo / site-title container. flex shrink-0 items-center gap-2.
  • .navbar__content — Horizontal group of items. flex items-center gap-1.
  • .navbar__spacer — Flex-grow gap that pushes sibling content to the edges.

Item Classes

  • .navbar__item — Nav link/button. text-muted text-sm, hover → text-foreground, rounded-lg.
  • .navbar__item--sm|lg — Size variants for items (padding + font size).
  • .navbar__item[data-current="true"] — Applied when isCurrent is true; bumps to text-foreground. Also sets aria-current="page".
  • .navbar__label — Truncated text inside items.
  • .navbar__separator — Vertical decorative divider (h-6 self-center).
  • .navbar__menu-toggle — Hamburger button (size-9). Toggles between hamburger and close icon via ::before/::after pseudo-elements.
  • .navbar__menu-toggle--sm|lg — Size variants.
  • .navbar__menu-toggle-icon — Inner span housing the animated pseudo-element lines.
  • .navbar__menu — Mobile dropdown menu. flex flex-col gap-1 overflow-y-auto px-6 pb-6 pt-2. Height animates between 0 and calc(100dvh - var(--navbar-height)).
  • .navbar__menu-item — Individual mobile menu item. text-foreground text-base font-medium, hover → bg-default.
  • .navbar__menu-item--sm|lg — Size variants.
  • .navbar__menu-item[data-current="true"] — Current mobile menu item (bg-default).

CSS Variables

  • --navbar-height — Height of the horizontal bar (default: 4rem; 3rem for sm; 5rem for lg). Can also be set via the height prop on Navbar.
  • --navbar-max-width — Max content width inside the header (default: 1024px, overridable via maxWidth).
  • --navbar-transition-duration — Reserved for future transitions (default: 300ms).
  • --spacing — Tailwind v4 base spacing token. Override on the navbar root (or a wrapper) to uniformly scale all internal paddings, gaps, and icon sizes.

Accessibility

  • Rendered as a <nav> landmark. Add an aria-label when multiple navigation regions share the page.
  • Navbar.Item with isCurrent sets aria-current="page" automatically.
  • Navbar.MenuToggle is backed by RAC ToggleButton; its selected state is wired to isMenuOpen. Customize the screen-reader label via the srLabel prop.
  • Animations respect the user's prefers-reduced-motion preference.

API Reference

The root <nav> landmark and the context provider. Accepts all <nav> props.

PropTypeDefaultDescription
position"sticky" | "static" | "floating""sticky"How the navbar is anchored to the page.
size"sm" | "md" | "lg""md"Applies the matching size variants to the header, items, and menu toggle.
maxWidth"sm" | "md" | "lg" | "xl" | "2xl" | "full""lg"Caps the header's content width via --navbar-max-width.
heightstring"4rem"CSS height for the bar. Sets --navbar-height inline.
hideOnScrollbooleanfalseHide the navbar when scrolling down and reveal on scroll up. Uses a spring transform so layout stays intact.
parentRefRefObject<HTMLElement | null>windowScroll container used by hideOnScroll. Defaults to the window.
isMenuOpenbooleanControlled mobile menu open state.
defaultMenuOpenbooleanfalseInitial mobile menu open state (uncontrolled).
onMenuOpenChange(isOpen: boolean) => voidCallback when the mobile menu state changes.
shouldBlockScrollbooleantrueLock body scroll while the mobile menu is open.
navigate(href: string) => voidProgrammatic navigation function used by Navbar.Item / Navbar.MenuItem when pressed.

Horizontal bar wrapper. Renders a <header> with the header size and max-width slot classes applied.

Logo / site-title container. Polymorphic — accepts a render prop to customize the rendered element. Renders a <div> by default.

Horizontal group of nav items. Renders a <div>.

A single nav link or action. Renders an <a> when href is set, otherwise a <button>. Polymorphic via the render prop.

PropTypeDefaultDescription
hrefstringDestination URL. Uses the parent Navbar's navigate for client-side routing, or the browser's default navigation as a fallback. External URLs (http://, https://) open in a new tab.
isCurrentbooleanfalseMarks the item as the current page. Sets aria-current="page" and data-current="true".
forceReloadbooleanfalseSkip the navigate callback and use window.location.href for this item.
render(props) => ReactElementOverride the rendered element (e.g. to render a Next.js / React Router <Link>).

Truncated text span for use inside Navbar.Item.

Vertical divider. Wraps HeroUI Separator with orientation="vertical".

Flex-grow spacer that pushes surrounding content to opposite ends of the header.

Hamburger button for the mobile menu. Wraps RAC ToggleButton; its selected state is bound to isMenuOpen.

PropTypeDefaultDescription
srLabelstring"Toggle navigation menu"Screen-reader label for the toggle.
childrenReactNodeCustom icon. When omitted, the built-in animated hamburger/close icon is used.

Animated mobile dropdown. Only renders when isMenuOpen is true. Fills the viewport below the navbar with calc(100dvh - var(--navbar-height)).

An individual item inside Navbar.Menu. Same API surface as Navbar.Item — but pressing an item automatically closes the mobile menu.

PropTypeDefaultDescription
hrefstringDestination URL. Same client-side routing rules as Navbar.Item.
isCurrentbooleanfalseMarks the item as the current page.
forceReloadbooleanfalseSkip the navigate callback and use window.location.href.
render(props) => ReactElementOverride the rendered element.

useNavbar

A hook for reading and mutating navbar state from inside Navbar's children.

const { height, isHidden, isMenuOpen, setMenuOpen, navigate } = useNavbar();
PropertyTypeDescription
heightstringCurrent navbar height (as passed via the height prop).
isHiddenbooleanWhether the navbar is currently hidden via hideOnScroll.
isMenuOpenbooleanWhether the mobile menu is currently open.
setMenuOpen(open: boolean) => voidProgrammatically open/close the mobile menu.
navigate((href: string) => void) | undefinedThe navigation function passed to Navbar, if any.

On this page