DocumentationComponentsTheme Creator
Theme CreatorGitHubIntroduction
InstallationUsageThemingMotion
Components
BreadcrumbTabsPaginationStepperMenu ItemToolbarMenubarNavigation MenuAccordionCollapsibleCommandBottom NavTop Header MobileTop Header DesktopSidebar
AI agentsContributing
  1. Components
  2. Top Header Desktop

Top Header Desktop

Desktop navigation bar with brand, nav, search, actions and subRow slots. Six variants, five sizes, radius cascade, true-centre nav, scroll elevation, floating inset mode, skip link, and full RTL support.

$ pnpm add @tessinaui/ui

When to use

  • A persistent bar at the top of every page that identifies the product and holds its global navigation and utilities. Keep the same position and content from page to page so people learn where things are.
  • Global utilities only: search, notifications, an account menu, one emphasized action. Anything specific to the current page belongs in the page.
  • A short primary nav. A handful of destinations fit in the nav slot; a second tier goes in subRow (tabs, a category strip).
  • Product shells and marketing sites alike. Product bars are solid (filled or elevated); transparent and blur are for marketing pages laid over a hero or scrolling content.
  • Keyboard users on content-heavy pages. Pair the bar with TopHeaderDesktopSkipLink so the first Tab stop jumps past it.

When not to use

  • On a phone or in a collapsed layout. Use Top Header Mobile or a Sidebar for hamburger and drawer navigation.
  • For menus with panels. The nav slot holds links; hover-intent and aria-expanded menus come from Navigation Menu composed into it.
  • For an announcement strip. Stack a Banner above the bar; it is never a header variant.
  • For a page's own sections or views. Use Tabs.
  • For a trail of parents. Use Breadcrumb, alone or as the bar's leading content.
  • To hold many actions. Keep one emphasized action and make the rest ghost or outline; do not add nav links that read as verbs.

Installation

Terminal
pnpm add @tessinaui/ui

Usage

example.tsx
import {
  TopHeaderDesktop,
  TopHeaderDesktopBrand,
  TopHeaderDesktopNavList,
  TopHeaderDesktopNavItem,
  TopHeaderDesktopActions,
} from "@tessinaui/ui";
import { Search } from "@tessinaui/ui";       // library Search in the search slot
import { IconButton } from "@tessinaui/ui";   // library IconButton in actions
example.tsx
<TopHeaderDesktop
  bordered
  brand={
    <TopHeaderDesktopBrand href="/" name="Tessina">
      <img src="/logo.svg" alt="" className="size-7" />
    </TopHeaderDesktopBrand>
  }
  nav={
    <TopHeaderDesktopNavList>
      <TopHeaderDesktopNavItem active href="/">Home</TopHeaderDesktopNavItem>
      <TopHeaderDesktopNavItem href="/about">About</TopHeaderDesktopNavItem>
    </TopHeaderDesktopNavList>
  }
  search={<Search variant="filled" rounded="full" placeholder="Search…" />}
  actions={
    <TopHeaderDesktopActions>
      <IconButton variant="ghost" size="sm" aria-label="Notifications">
        <Bell className="size-4.5" />
      </IconButton>
    </TopHeaderDesktopActions>
  }
/>

The bar publishes its tone through <Surface>, so library components dropped into any slot — Button, IconButton, Avatar, Badge, Search — adapt to primary / on-color / hero-overlay bars automatically. On those bars the current nav item is the bar's inverse chip.

Examples

Default

A basic desktop header with brand, nav, and trailing actions.

App shell

The product bar: workspace switcher in the brand slot, global search with a ⌘K hint, create action, notification badge, and an avatar account menu — composed entirely from library components.

Commerce

Double-row store header: search-dominant main row, wishlist, cart count, locale selector, and a category nav in the subRow slot with the underline indicator.

Marketing

An announcement Banner stacked above the bar (a sibling — never a header variant), a "New" badge on a nav item, a disabled item, and the quiet-login + filled-signup pair.

Sub row

The subRow slot stacks any second row under the bar — here a Tabs strip. It inherits the bar's horizontal padding and maxWidth containment.

Breadcrumb bar

The doc-tool pattern: a Breadcrumb trail as the bar's leading content.

Transparent over a hero

variant="transparent" inside <Surface ink="light"> — the bar inherits the plate's ink with no tone prop at all.

Blur + scroll elevation

variant="blur" + sticky + scrollBehavior="elevate": flat at rest, then a hairline and shadow the moment content scrolls underneath. Inside a coloured <Surface> the glass stands down and the bar paints opaque, as filled: over a flat plate the glass is mostly the plate, and a focus ring on the bar would lose its ground.

Floating (inset)

inset detaches the bar from the screen edges; its shell corners join the rounded cascade (full ⇒ rounded-3xl).

Active-item styles

indicator="pill" (default) vs indicator="underline", plus a disabled item that drops its href and leaves the tab order.

Skip link

TopHeaderDesktopSkipLink — invisible until keyboard focus, the first Tab stop, jumping straight to your content region (WCAG 2.4.1).

Dropdown menu

A nav item that opens a hover/focus dropdown — composed from NavigationMenu, which owns the aria-expanded / keyboard contract.

Mega menu

Full-width mega menu with a two-column product grid and a promotional footer card.

Enterprise dashboard

Icon-labelled nav items, ghost icon actions, and a primary CTA.

Variants

The six visual styles.

Nav positions

start, center (truly centred — a 1fr auto 1fr grid, so the centre cell holds position regardless of side widths), and end.

With search

The search slot fills the flex-1 middle zone. The zone is a plain box — the field you compose owns the search landmark, so Search brings its own and nothing is nested. Passing a bare <input>? Wrap it yourself in <search> or <form role="search">.

Sizes

Five height and padding scales — the bar's controls and search step with them.

On color

A transparent bar inherits the tone around it, so over a coloured Surface or a hero its brand, nav and actions take the plate's ink. primary and on-color publish on-color themselves, and blur turns opaque on a coloured plate so its focus rings keep their ground.

Loading

The built-in skeleton mirrors the header layout — including navPosition — to avoid content shift.

RTL

Set dir="rtl" and the bar mirrors: the brand sits at the right, the nav runs right to left, and the actions sit at the left. Logos and icons do not flip. An explicit dir="rtl" also defaults the header's own strings to Arabic: the nav landmark's name and the skip link's text. Leave dir unset and the header follows the page, in English. label and the skip link's children still override their defaults, and strings overrides any entry of TOP_HEADER_DESKTOP_STRINGS.

API Reference

TopHeaderDesktop

PropTypeDefaultDescription
variant"filled" | "elevated" | "transparent" | "primary" | "on-color" | "blur""filled"Visual style
size"xs" | "sm" | "md" | "lg" | "xl""md"Bar height scale — see the height table below
rounded"none" | "sm" | "md" | "lg" | "full""full"Corner cascade for everything inside the bar (nav pills, search, icon buttons, skeleton bars) and, when inset, the shell itself. An attached bar's own corners stay square
brandReactNode—Leading slot: logo, workspace switcher, breadcrumb
navReactNode—Navigation slot — position via navPosition
navPosition"start" | "center" | "end""start"center is truly centred via a 1fr auto 1fr grid
searchReactNode—Search slot; a plain box, the composed field owns the search landmark
actionsReactNode—Trailing actions
subRowReactNode—Second full-width row under the bar (tabs, category nav, breadcrumb strip)
borderedbooleanfalse1px bottom hairline
stickybooleanfalsesticky top-0 z-40 (top-3 when inset)
insetbooleanfalseFloating bar: margins, hairline, shadow, shell corners from rounded
scrollBehavior"none" | "elevate""none"elevate: data-scrolled + hairline + shadow once content scrolls under (IntersectionObserver sentinel; works in any scroll container)
indicator"pill" | "underline""pill"Active nav-item treatment
maxWidth"sm" | "md" | "lg" | "xl" | "2xl" | "full""full"Content-row containment — 48 / 64 / 72 / 80 / 96rem
labelstringstrings.navAccessible name of the nav landmark — make it unique per page, never containing the word "navigation"
skeletonbooleanfalseLoading placeholder
dir"ltr" | "rtl"inheritedDirection; "rtl" also gives the header and the parts inside it the Arabic strings
stringsPartial<TopHeaderDesktopStrings>—Overrides single entries — the nav landmark's name, the skip link's text. label wins for the nav name
tone"default" | "on-color"autoPublished via <Surface>; auto-on-color for primary/on-color variants, otherwise inherited from the surrounding Surface

Bar heights: xs 48px · sm 56px · md 64px · lg 72px · xl 80px (min-heights on the content row; xs/sm match the common 48px app shell and 56px global nav).

TopHeaderDesktopSkipLink

First-Tab "Skip to content" link (WCAG 2.4.1). Render it first inside brand, or immediately after <body>.

PropTypeDefaultDescription
hrefstring"#content"Jump target — your main content region
childrenReactNodestrings.skipLinkLink text; inside the header it follows the header's language
dir"ltr" | "rtl"—"rtl" gives the link the Arabic text on its own, for a link rendered outside the header
stringsPartial<TopHeaderDesktopStrings>—Overrides skipLink; children wins

TopHeaderDesktopBrand

<a> (or anything via render) with focus ring and flex gap.

PropTypeDefaultDescription
namestring—Brand name next to children
hrefstring—Link destination
renderReactElement | fn—Replace the element — render={<Link href="/" />}

TopHeaderDesktopNavList

<ul> container for nav items and dividers.

TopHeaderDesktopNavItem

<a> (or anything via render) styled as a nav link.

PropTypeDefaultDescription
activebooleanfalseCurrent page — aria-current="page" + the bar's indicator treatment
disabledbooleanfalsearia-disabled, href dropped (leaves tab order), muted paint
hasDropdownbooleanfalseChevron only — compose NavigationMenu for a real menu
renderReactElement | fn—Replace the element — render={<Link href="/pricing" />}

TopHeaderDesktopNavDivider

<li> vertical separator between nav items.

TopHeaderDesktopActions

Flex row wrapper for trailing action elements.

Deprecated sub-components

TopHeaderDesktopSearch, TopHeaderDesktopIconButton and TopHeaderDesktopAvatar are deprecated (kept working for one minor). Slot the library components instead — they carry the full contracts and adapt to the header's Surface tone automatically:

DeprecatedUse instead
TopHeaderDesktopSearchSearch (variant="filled" rounded="full")
TopHeaderDesktopIconButtonIconButton (variant="ghost")
TopHeaderDesktopAvatarAvatar inside a button / DropdownMenu trigger

Variants

  • Filled (default) — solid bg-background app bar.
  • Elevated — filled + shadow-sm, for bars floating over scrollable content.
  • Transparent — no fill; overlay a hero (className="absolute inset-x-0 top-0") inside a <Surface ink> so the tone is inherited.
  • Primary — brand-coloured. Rare in the wild (3 of 206 surveyed headers) — prefer filled or on-color unless the brand calls for it.
  • On Color — dark plate with light ink; the common "dark bar on a light app" (24 of 206 surveyed).
  • Blur — frosted glass; pair with sticky and scrollBehavior="elevate". Opaque inside a coloured <Surface>.

Transparent and blur are marketing-page patterns — the survey found zero in product shells. Product bars are solid.

Boundaries

  • Announcement strips stack a Banner above the bar — never a header variant.
  • Real nav menus (aria-expanded, hover intent, keyboard) come from NavigationMenu composed into the nav slot.
  • Collapsed/hamburger navigation belongs to TopHeaderMobile and Sidebar.
  • Crowded navs: keep ≤5 primary items. A nav that must hold more takes NavigationMenu's own bar, whose overflow moves items into a "More" menu one at a time.
  • Keep one emphasized action in the bar — everything else ghost/outline.

Keyboard Navigation

KeyAction
Tab / Shift+TabMove between the bar's interactive elements
Enter / SpaceActivate focused link or button
Enter on skip linkJump to the content region

Menus composed via NavigationMenu add the full APG pattern: arrows rove between triggers, ArrowDown enters an open panel, Home/End jump, Esc closes and returns focus to the trigger.

Accessibility

  • Renders <header> without a hardcoded role — it is a banner landmark exactly when your page places it at body level (APG rule).
  • <nav aria-label={label}> wraps the nav slot; set label uniquely per page and never include the word "navigation".
  • The search slot is a plain box — no landmark of its own, so a composed Search (which renders role="search") is not nested inside a second one. Wrap a bare <input> yourself if you want the landmark.
  • Active item: aria-current="page". Disabled item: aria-disabled, no href, out of the tab order.
  • TopHeaderDesktopSkipLink provides the WCAG 2.4.1 bypass block.
  • Touch targets floor at 44px wherever the pointer is coarse — phones, and tablets at any width. A search input in the bar floors at 16px text there too, so iOS does not zoom the page on focus.
  • Focus rings visible on every interactive part, both themes.
  • dir="rtl" flips the layout via logical properties.
  • AT matrix: VoiceOver + Safari passed 2026-09-14. Reading from the top: "link Tessina", "Main navigation", "list 3 items", "current page link Overview", "link Analytics", "link Reports", "Search button", "Account button". NVDA and JAWS untested (no Windows host).

Migration (from the pre-TES-35 API)

  • Attached-bar corner rounding is gone: rounded no longer curves the bar's own bottom edge (it drives the inner cascade, and the shell only when inset). Want the old look? Add className="rounded-b-md" etc.
  • maxWidth remap: lg is now 72rem (was 80), xl is 80rem (was a duplicate 1280px). 2xl/sm/md/full unchanged.
  • rounded="xl" never existed — the old docs table was wrong; the scale is none–full.
  • TopHeaderDesktopTone is now an alias of SurfaceTone.
  • The three deprecated sub-components keep rendering unchanged for one minor.
Top Header MobileSidebar

On this page

When to useWhen not to useInstallationUsageExamplesDefaultApp shellCommerceMarketingSub rowBreadcrumb barTransparent over a heroBlur + scroll elevationFloating (inset)Active-item stylesSkip linkDropdown menuMega menuEnterprise dashboardVariantsNav positionsWith searchSizesOn colorLoadingRTLAPI ReferenceTopHeaderDesktopTopHeaderDesktopSkipLinkTopHeaderDesktopBrandTopHeaderDesktopNavListTopHeaderDesktopNavItemTopHeaderDesktopNavDividerTopHeaderDesktopActionsDeprecated sub-componentsVariantsBoundariesKeyboard NavigationAccessibilityMigration (from the pre-TES-35 API)