Skip to content
Nizivo UI

TopBar

The bar above the page on screens 640 px and wider, with the page's name or a Breadcrumb at the start, the search, then notifications and the account.

Server component, no client JS

Import

import { TopBar } from '@nizivo/react/top-bar';

// Once per app (Getting started), after
// @nizivo/tokens/tokens.css and @nizivo/react/css/base.css
import '@nizivo/react/css/top-bar.css';

Static or interactive

Server. It is a layout with slots and ships no client JavaScript of its own. What you put in the slots brings its own: the examples' SearchField and IconButton are client components. How to choose.

In a client app (a Vite or React Router single-page app, or a 'use client' file) it is an ordinary React component: event handlers, refs and state work as usual. In a client app.

Slots

  • title: the page's name, in Heading/H3's look. It is text, not a heading: the page's PageHeader holds its one <h1>.
  • start: in place of title, for example a Breadcrumb on a page deeper in the app.
  • search: usually a SearchField in a <form method="get">, a real input (M49). It is 360 px at most and gives up width first.
  • actions: at the end, a notifications IconButton and the account's Avatar or menu.

In the shell

AppShell shows the TopBar from 640 px and the MobileTopBar below that. The bar is not sticky: it scrolls with the page. Its padding follows the grid's margin, so its contents line up with the page's.

Hooks: --nz-top-bar-gap, --nz-top-bar-padding-inline, --nz-top-bar-search-width, --nz-top-bar-bg, --nz-top-bar-border.

Examples

Basic

Figma's Top Bar: the page's name, the search (a real input, M49) with its shortcut, then notifications and the account. The title is text, not a heading: the page's PageHeader is the <h1>.

Overview
import type { JSX } from 'react';
import { Avatar } from '@nizivo/react/avatar';
import { IconButton } from '@nizivo/react/icon-button';
import { SearchField } from '@nizivo/react/search-field';
import { TopBar } from '@nizivo/react/top-bar';

/** Stands in for an `@nizivo/icons` glyph (20 px Lucide strokes). */
function Bell(): JSX.Element {
  return (
    <svg
      viewBox="0 0 24 24"
      width="1em"
      height="1em"
      fill="none"
      stroke="currentColor"
      strokeWidth={1.92}
      strokeLinecap="round"
      strokeLinejoin="round"
    >
      <path d="M10.3 21a1.94 1.94 0 0 0 3.4 0M3.26 15.33A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.67C19.41 13.96 18 12.5 18 8A6 6 0 0 0 6 8c0 4.5-1.41 5.96-2.74 7.33" />
    </svg>
  );
}

export function TopBarExample(): JSX.Element {
  return (
    <TopBar
      title="Overview"
      search={
        <form method="get" action="/search">
          <SearchField
            name="q"
            placeholder="Search orders, products, customers"
            shortcut="mod+k"
            labels={{ label: 'Search the store' }}
          />
        </form>
      }
      actions={
        <>
          <IconButton icon={<Bell />} label="Notifications, 3 unread" variant="secondary" />
          <Avatar name="Maya Lindqvist" />
        </>
      }
    />
  );
}

Breadcrumb

Deeper in the app, a Breadcrumb takes the title's place.

import type { JSX } from 'react';
import { Avatar } from '@nizivo/react/avatar';
import { Breadcrumb } from '@nizivo/react/breadcrumb';
import { TopBar } from '@nizivo/react/top-bar';

export function TopBarBreadcrumbExample(): JSX.Element {
  return (
    <TopBar
      start={
        <Breadcrumb.Root>
          <Breadcrumb.Item href="/orders">Orders</Breadcrumb.Item>
          <Breadcrumb.Item current>#1042</Breadcrumb.Item>
        </Breadcrumb.Root>
      }
      actions={<Avatar name="Maya Lindqvist" />}
    />
  );
}

Props

The bar above the page on screens 640 px and wider (AppShell's topBar).

Server component Renders data-slot="top-bar" with the class nz-top-bar. Props: TopBarProps. Source: src/top-bar/top-bar.tsx.

NameTypeDefaultDescription
actionsReactNode–

At the end: the notifications IconButton, the account's Avatar or menu.

renderRenderProp<Record<string, never>>–
searchReactNode–

The search, usually a SearchField (M49: a real input). 360 px at most.

startReactNode–

In place of title, for example a Breadcrumb for a page deeper in the app.

titleReactNode–

The page's name, in Heading/H3's look (Figma's Title). Not a heading element.

  • Also takes every attribute of <header> except children, title. (Omit<ComponentPropsWithRef<"header">, "title" | "children">)

render takes an element, or, in client code, a function of the props and no state.

Other exports

TopBarProps type

import type { TopBarProps } from '@nizivo/react/top-bar'

The props of TopBar, listed above.

Data attributes and slots

Style parts by class (.nz-<slot>) and state by data attribute. Attribute meanings come from contracts/vocabulary.json.

SlotRendered byData attributes
top-bar
.nz-top-bar
TopBar
root (takes render)
none
top-bar-actions
.nz-top-bar-actions
TopBar
inner element (CSS only)
none
top-bar-search
.nz-top-bar-search
TopBar
inner element (CSS only)
none
top-bar-start
.nz-top-bar-start
TopBar
inner element (CSS only)
none
top-bar-title
.nz-top-bar-title
TopBar
inner element (CSS only)
none

CSS hooks

Set a hook on the component's class or any ancestor to restyle it without specificity games; leave it unset for the default shown.

HookDefaultRead as
--nz-top-bar-bg--nz-bg-canvas
  • background on .nz-top-bar
--nz-top-bar-border--nz-border-subtle
  • border-block-end on .nz-top-bar
--nz-top-bar-gap--nz-space-6
  • gap on .nz-top-bar
--nz-top-bar-padding-inline--nz-grid-margin
  • padding-inline on .nz-top-bar
--nz-top-bar-search-width22.5rem
  • flex on .nz-top-bar-search

Layers: nz.components. Classes: .nz-top-bar, .nz-top-bar-actions, .nz-top-bar-search, .nz-top-bar-start, .nz-top-bar-title.

Tokens this stylesheet reads (10)

--nz-bg-canvas, --nz-border-subtle, --nz-border-width-default, --nz-font-heading-h3, --nz-grid-margin, --nz-space-3, --nz-space-4, --nz-space-6, --nz-text-primary, --nz-tracking-heading-h3

Accessibility

Nothing in this component takes focus or keyboard input.

Keyboard

None.

Figma

Node ids from design/component-map.json, which nz gen writes from component.json. The links open the Nizivo Figma library, which may ask you to sign in.

On this page