affectUI › Components › Navigation

Breadcrumb

Where a page sits and the way back up – links with quiet separators, the current page last, a long middle folded into a … menu, long names shortened with the full one on hover.

Free and open source (MIT). Install: npx shadcn@latest add https://www.affectui.com/r/breadcrumb.json · Import from @/components/ui/breadcrumb

When to use

  • Where a page sits in a hierarchy: workspace, agent, runs, the run
  • Going back up several levels in one press – files and folders, a settings section, an issue in a project
  • Deep trails: the middle folds into a … menu past maxItems, and on its own when the row gets narrow

When not to use

  • Moving between pages of one list – use the Pagination
  • Switching between views on the same level – use the Segmented Control or tabs
  • Steps of a flow the user goes through in order – use the Stepper Form
  • Picking another workspace or project from the trail – put a Dropdown Menu on that crumb yourself

Usage

import { Breadcrumb } from "@/components/ui/breadcrumb";

export function RunHeader({ agent, run }: { agent: { id: string; name: string }; run: { title: string } }) {
  return (
    <Breadcrumb
      items={[
        { label: "Agents", href: "/agents" },
        { label: agent.name, href: `/agents/${agent.id}` },
        { label: "Runs", href: `/agents/${agent.id}/runs` },
        { label: run.title },
      ]}
    />
  );
}

Props

NameTypeDefaultDescription
itemsBreadcrumbItem[]From the top down; the last one is the page you are on – shown in ink, not a link, marked aria-current="page"
items[].labelstringThe name. Long ones shorten with … at 200px and show in full on hover
items[].hrefstringMakes the crumb a link
items[].onClick(event) => voidWithout href the crumb is a button; with href it runs first (call preventDefault to navigate with a router)
items[].iconReactNode | HugeIconA 14px glyph before the label, e.g. the workspace's mark on the first crumb
separator"slash" | "chevron" | ReactNode"chevron"What sits between the crumbs – a 14px chevron (mirrored right to left), a quiet slash or your own
maxItemsnumber4The most crumbs shown; past it the ones after the first fold into …, so the first and the last ones stay. A row too narrow folds more on its own
aria-labelstring"Breadcrumb"Names the navigation landmark
...nav propsComponentProps<"nav">className, style, ref and the rest go to the <nav>

Keyboard

  • Tab: Moves through the crumbs and the …
  • Enter: Follows a crumb, or opens the folded ones
  • ↓ / ↑: Moves through the folded crumbs; ↓ on the … opens them
  • Home / End: The first or the last folded crumb
  • Esc: Closes the folded crumbs and goes back to the …

Accessibility

  • A <nav> landmark named Breadcrumb around an ordered list, so screen readers hear the levels and their count
  • The page you are on is marked aria-current="page" and isn't a link
  • Separators are hidden from screen readers
  • The … says how many crumbs it holds ("Show 2 more crumbs") and opens a real menu with aria-expanded; the focus moves in and comes back
  • Each label gets dir="auto", so a name in another script reads the right way
  • The ring shows only under keyboard focus (:focus-visible), never after a click

Responsive

  • One line that never wraps: crumbs shorten first, the current page last; when they would get too short, more of the middle folds into …
  • Touch screens get larger hit areas around the crumbs and the …, and taller menu rows – the text doesn't move
  • Right to left: the chevrons turn round and the menu opens from the right edge
  • Dark mode built in: switches when an ancestor (usually <html>) has the class dark or data-theme="dark"

Requirements

  • React 19
  • Optional: @hugeicons/core-free-icons – its icon objects can be passed straight to an item's icon

Related

  • Pagination – Pages of a long list – the range you see, previous and next, page numbers with … between them and rows per page, tabular numbers that keep the row still from 1 page to 10,000
  • Dropdown Menu – Actions and choices behind any trigger – icons, shortcuts, checks, red items and submenus, a gliding highlight, type-ahead and the full menu keyboard
  • Segmented Control – Switch between two to six options – a raised pill or underline that glides, stretches a little and can be dragged across, with icons, counts and badges
  • Stepper Form – A multi-step flow for onboarding and setup – steps that fill and check off, sliding steps, a card that morphs to each step, inline validation and a success state