Skip to contentAsheeUIAsheeUI

Navbar

The bar at the top of a page, a brand, the destinations, and the actions beside them.

A navbar is the band a page starts with: the product's name, the handful of places a reader moves between, and the one or two actions that are always within reach. It states where its destinations sit and how its surface is treated, and it leaves the destinations themselves to the page, the bar has no idea what a campaign is.

Below the md breakpoint the same destinations move into a panel behind a labelled control, rather than into a second row the bar has no height for. Every destination renders through the framework's link primitive, so a router substituted once keeps working here.

Usage

import { Button, Navbar } from "@asheeui/web";

const links = [
  { label: "Campaigns", href: "/campaigns", isActive: true },
  { label: "Contacts", href: "/contacts" },
  { label: "Reports", href: "/reports" },
];

<Navbar
  brand="Ashee SMS"
  brandHref="/"
  links={links}
  actions={<Button size="sm">Start free</Button>}
/>;

The bar renders what it was given: with no links there is no navigation landmark and no disclosure control, so a bar that only carries a brand and an action is a brand and an action.

Destinations

A destination is label, href and its state. isActive marks the page the reader is on, which is both an emphasis and an announcement; icon puts content before the label; disabled refuses the press and says so. id is optional and defaults to the position in the list.

A destination can also state the component that renders it, which is how a single link in the bar differs from its siblings, a destination that needs a different prefetch policy, say. Where a destination states component, it wins over the bar's own link, and the two sets of componentProps are merged with the destination's last, so the more specific statement takes effect. That precedence is the one links and substitution describes.

The second row

secondary is a row of its own under the destinations, which is what keeps a search field from competing with the navigation for the same line. children renders after it, for a banner or a notice that belongs to the bar.

The bar's own shape is five options. position is sticky or static; variant is solid, ghost or bordered; align places the destinations at the start, in the center or at the end; and contained with containerSize decides whether the content is held to the framework's width and gutter. A ghost bar is the one to use over a hero, where a band behind the bar would cut the image in two.

Props

All five shape options are registered by the component, sticky, solid, start, true and lg, so each resolves from the instance, then from components.navbar, then from the registration. The bar does not read the application's defaultVariant or defaultRadius: its surface vocabulary is solid, ghost and bordered, which is not the vocabulary of a button, and a rounded bar above a square page reads as a mistake. label and mobileLabel are not configuration, the name of a landmark belongs to the page that places the bar, not to the product's look.

Accessibility

  • The element is a <header> by default, which is the banner landmark when the bar sits at the top of the page, and it contains a navigation landmark named by label ("Main"). The name is what distinguishes this region from any other navigation on the page.
  • isActive sets aria-current="page" on the destination as well as the active treatment, so the current page is announced rather than only coloured.
  • Below md the destinations are repeated in a panel opened by a Button whose accessible name is mobileLabel ("Menu"). The control reports its state with aria-expanded, and points at the panel with aria-controls only while the panel exists; Escape closes it and returns focus to the control when focus is inside the panel, and choosing a destination closes it. Escape pressed anywhere else in the bar, typing in the secondary row's search field, for instance, is left to whatever is handling it.
  • A crowded bar wraps its destinations onto a second line rather than letting them paint over the actions; the link list carries min-w-0 and wraps, and the actions keep their own space.
  • A disabled destination is refused by the link primitive and marked aria-disabled, so it reads as unavailable rather than as absent.

Every destination and the brand are drawn by the framework's link primitive, so the page keeps its own element for them: see links and substitution.