Skip to content
kerfjsGitHub

Nav

A row or column of links with a bar that slides to the current one.

SourcePackage @kerf-js/veneerTry it

Preview

tsx
import { state } from '@kerf-js/core'import { Nav } from '@kerf-js/veneer'export function Across() {  const at = state('Deploys')  const go = (e: Event, name: string) => {    e.preventDefault()    at.value = name  }  return (    <Nav label="Project">      {PAGES.map((name) => (        <a          key={name}          href={`#${name}`}          aria-current={            at.value === name ? 'page' : undefined          }          onClick={(e) => go(e, name)}        >          {name}        </a>      ))}    </Nav>  )}const PAGES = [  'Overview',  'Deploys',  'Logs',  'Settings',]

Installation

npm install @kerf-js/veneer

Try it

Change the controls: the preview and its code update together. The address keeps what you set, so you can link to it.

Live preview
Controls
Axis
Codeupdates as you change the controls
import { Nav } from '@kerf-js/veneer'<Nav label="Project">  <a href="/overview">Overview</a>  <a href="/deploys" aria-current="page">Deploys</a>  <a href="/logs">Logs</a>  <a href="/settings">Settings</a></Nav>

Usage

tsx
import { Nav } from '@kerf-js/veneer'

A column

axis="y" puts the bar beside the links.

App header

Put Nav links beside a title, and set aria-current on the link for the current page.

Settings pages

Use axis="y" to stack the links down the side, with aria-current marking the current page.

Table of contents

spy lights the link whose heading is at the top of the window. Scroll to watch it move.

When to use

Use it for

  • Links to the pages of an app or a section
  • A table of contents that follows the reader

Reach for something else

  • Tabs, when the views swap in place and have no URL
  • Menu, when the links run actions, or there are too many to show

Accessibility

Tab
Moves between links
Enter
Follows the link
  • label names the landmark, so a page with two navs can tell them apart.
  • The links are plain anchors. aria-current is what announces the page, as well as moving the bar.

Theming

Restyle it app-wide from veneer() in your kerf config. Every key takes colour, spacing, size, radius, shadow, type and motion; its own keys are listed. A state nests inside: hover: { bg: 'ink' }. Text on a fill you set is contrast-checked at build. How theming works

KeyOwn keysStates
parts.nav—none
parts.nav.item—hover, focus, press, active, open, disabled
parts.nav.underlinecolor, width, durationnone
ts
veneer({  colors: { brand: '#e8590c', ink: '#1b1b1f' },  parts: {    nav: { gap: 24, item: { hover: { text: 'brand' } }, underline: { color: 'brand', width: 3 } },  },})

API Reference

PropTypeDefaultDescription
labelstring—The name of the navigation landmark.
axis"x" | "y"'x'x for a row, y for a column.
spybooleanfalseFollow the headings the links point at, for a table of contents.
childrenunknown—What it contains.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="nav"] [data-part="indicator"]

indicator

RelatedTabsLinkShell