Top navigation

Global navigation that persists across pages within a single app. Aligned with J&J DS v1.2 — single-line logo on the homepage, shorthand on subsequent pages. Three height modes (compact 48 / default 64 / spacious 80), structured action cells with hover and active states, and an optional secondary bar.

Default — full logo, primary nav, action cells

The canonical desktop variant. Logo on the left, optional menu icon, webapp name (20px Johnson Text Medium), inline nav with a menu item that opens a dropdown, then a CTA and action icon cells on the right.

Johnson & Johnson
Webapp name
Show source
<TopNavigation
  notSticky
  appName="Webapp name"
  links={[
    { label: "Overview", href: "#", active: true },
    { label: "Patients", href: "#" },
    { label: "Studies", href: "#" },
    {
      label: "Reports",
      type: "menu",
      items: [
        { label: "Operational", href: "#" },
        { label: "Clinical", href: "#" },
        { label: "Compliance", href: "#" },
        { label: "Custom", href: "#" },
      ],
    },
    { label: "Admin", href: "#" },
  ]}
  cta={
    <Button size="sm" variant="primaryAlt">
      <Icon icon={Plus} size="xs" />
      New study
    </Button>
  }
  actionItems={[
    { label: "Search", icon: <Icon icon={Search} size="md" /> },
    { label: "Notifications", icon: <Icon icon={Bell} size="md" /> },
  ]}
/>

Mode — Compact (48), Default (64), Spacious (80)

Three vertical densities matching the Figma `mode` variant. The webapp name shrinks to 16px in compact; the J&J logo height tracks the bar.

Show source
<TopNavigation notSticky mode="compact" appName="Webapp name" links={links} />
<TopNavigation notSticky mode="default" appName="Webapp name" links={links} />
<TopNavigation notSticky mode="spacious" appName="Webapp name" links={links} />

Logo — single-line vs shorthand

Per DS guidance: single-line on the homepage, shorthand on subsequent pages. For longer app names (~20+ chars) consider the "Full on Secondary nav" pattern using the secondaryBar slot.

Show source
<TopNavigation notSticky logoForm="single-line" appName="Trial dashboard" links={links} />
<TopNavigation notSticky logoForm="shorthand" appName="Trial dashboard" links={links} />

With menu button — collapsed nav

Use `showMenuButton` and `onMenuClick` when nav items are collapsed into a side panel. Hides inline nav below the md breakpoint automatically.

Johnson & Johnson
Webapp name
Show source
<TopNavigation
  notSticky
  showMenuButton
  onMenuClick={() => console.log("open side nav")}
  appName="Webapp name"
  actionItems={[
    { label: "Help", icon: <Icon icon={HelpCircle} size="md" /> },
    { label: "Settings", icon: <Icon icon={Settings} size="md" /> },
  ]}
/>

With secondary navigation bar

A 32px-tall bar below the main nav, useful for context like locale, region, or breadcrumbs. Two tones (white | gray).

EN · USTrial: BRIDGE-204
Show source
<TopNavigation
  notSticky
  appName="Webapp name"
  links={links}
  secondaryBarTone="gray"
  secondaryBar={
    <div className="flex items-center gap-4 text-[12px] text-jj-text-02">
      <span>EN · US</span>
      <span aria-hidden>|</span>
      <span>Trial: BRIDGE-204</span>
    </div>
  }
/>

Free-form actions slot — avatars, buttons, anything

`actions` accepts any ReactNode and renders to the right of `actionItems`. Use it when you need an avatar, custom dropdown, or anything outside the structured icon-cell pattern.

Show source
<TopNavigation
  notSticky
  appName="Webapp name"
  links={links}
  actionItems={[
    { label: "Notifications", icon: <Icon icon={Bell} size="md" /> },
  ]}
  actions={
    <Avatar size="sm">
      <AvatarImage src="https://i.pravatar.cc/80?img=12" alt="" />
      <AvatarFallback>PN</AvatarFallback>
    </Avatar>
  }
/>

States — disabled / current / open menu

Items expose `active` (current page, 2px black underline + text-01), `disabled` (text-03, no interaction), and menu items track open state automatically. Click the Reports menu in the first example to see the dropdown.

Johnson & Johnson
States
Show source
<TopNavigation
  notSticky
  appName="States"
  links={[
    { label: "Active", href: "#", active: true },
    { label: "Default", href: "#" },
    { label: "Disabled", href: "#", disabled: true },
    {
      label: "Open menu",
      type: "menu",
      items: [
        { label: "Item one", href: "#" },
        { label: "Item two (disabled)", disabled: true },
        { label: "Item three", href: "#" },
      ],
    },
  ]}
/>

Custom brand

Pass `brand` to swap the J&J logo for any element. Useful for co-branded experiences.

Acme Health
Co-branded
Show source
<TopNavigation
  notSticky
  brand={
    <Link href="/" className="flex items-center gap-2 font-semibold text-jj-text-01">
      <ArrowUpRight aria-hidden="true" className="h-4 w-4" />
      Acme Health
    </Link>
  }
  appName="Co-branded"
  actionItems={[{ label: "Profile", icon: <Icon icon={User} size="md" /> }]}
/>