Skip to content
design
Components

Breadcrumbs

Hierarchical links show where a page belongs and give direct access to its ancestors.

On this page
The current page stays visible at the end of a hierarchy of real links.
Code
import { Breadcrumbs } from "@bosunkit/components/breadcrumbs";
import { House } from "lucide-react";
import type { ReactElement } from "react";
export const description: string =
  "Parent destinations are real links; the current page is plain text with aria-current. Icons supplement the names.";
export default function Showcase(): ReactElement {
  return (
    <Breadcrumbs
      label="Documentation hierarchy"
      expandLabel="Show ancestors"
      collapseLabel="Hide ancestors"
      items={[
        { id: "home", label: "Design", href: "/", icon: <House /> },
        { id: "components", label: "Components", href: "/docs/components" },
        { id: "navigation", label: "Navigation", href: "/docs/components/navigation" },
        { id: "current", label: "Breadcrumbs" },
      ]}
    />
  );
}

Breadcrumbs describe the current page's place in a hierarchy. The final item is text marked aria-current="page"; each ancestor with an href is a real link. Names match the destination titles. The component reads no router state.

01Show the hierarchyBuild the path from parent relationships. A breadcrumb trail is independent of the sequence of pages a person visited.
02Keep the current page clearPreserve the root and the closest ancestors when a deep path collapses. Keep the current page visible.
03Keep links usefulUse real destinations so browser navigation, copied URLs and opening another tab remain available.

Examples

Deep paths and controlled disclosure

maxItems counts destinations, including the root and current page; its default is four and its minimum is two. The disclosure is an additional control. It reveals the middle ancestors in place and keeps keyboard focus on the same button. The caller supplies both its expanded and collapsed names.

A deep hierarchy keeps the root, parent and current item visible. Reveal the middle ancestors, or use the switch to control disclosure externally.
Code
import { Breadcrumbs } from "@bosunkit/components/breadcrumbs";
import { Switch } from "@bosunkit/components/switch";
import { useState, type Dispatch, type ReactElement, type SetStateAction } from "react";
export const description: string =
  "A deep hierarchy keeps the root, parent and current item visible. Reveal the middle ancestors, or use the switch to control disclosure externally.";
export default function LongPath(): ReactElement {
  const [expanded, setExpanded]: [boolean, Dispatch<SetStateAction<boolean>>] = useState(false);
  return (
    <div style={{ display: "grid", gap: "var(--space-lg)" }}>
      <label style={{ display: "flex", alignItems: "center", gap: "var(--space-sm)" }}>
        <Switch checked={expanded} onCheckedChange={setExpanded} />
        Show the complete path
      </label>
      <Breadcrumbs
        label="Report example hierarchy"
        maxItems={3}
        expanded={expanded}
        onExpandedChange={setExpanded}
        expandLabel="Show all report ancestors"
        collapseLabel="Collapse report ancestors"
        items={[
          { id: "home", label: "Design", href: "/" },
          { id: "consumers", label: "Consumers", href: "/docs/consumers" },
          { id: "reports", label: "Reports and docs", href: "/docs/consumers/reports-and-docs" },
          { id: "types", label: "Report types", href: "/docs/consumers/report-types" },
          { id: "current", label: "An engineering review with a deliberately long title" },
        ]}
      />
    </div>
  );
}

Placement and navigation

Place breadcrumbs above the page heading. They complement the main navigation and provide a quick route upward. Do not use them for a task's progress; Steps names a workflow's stages and their states.

Pass unique item ids and one ordered path. The final item is current even if it has an href; a parent without an href is plain text. An empty array renders an empty landmark, so omit the component when there is no hierarchy to convey. One item can name a root page without creating an unnecessary link to itself.

Long names and small screens

Names wrap without clipping. Use a small maxItems when the available column is narrow and keep the destination's complete name available. Icons are decorative beside text, and separators are hidden from assistive technology. The disclosure remains a touch target and uses the shared focus ring. Expanded paths can take several lines.

expanded, defaultExpanded and onExpandedChange support controlled and local disclosure state. Changing the page hierarchy does not change browser history; the application's route owns the actual path.

Accessibility and integration

Give each navigation landmark a useful label, such as “Report hierarchy”. Ordinary links use Tab and Enter; the disclosure also supports Space. Internal paths use the provider's link adapter. Its native anchor props, accessible names, refs and event handlers must reach the rendered link.

Props

PropTypeDefaultDescription
labelrequiredstring–Name of this navigation landmark, translated by the caller.
itemsrequiredreadonly BreadcrumbItem[]–Ancestors in order, ending with the current page. Ids must be unique.
expandLabelrequiredstring–Name of the control that reveals the hidden ancestors.
collapseLabelrequiredstring–Name of the same control while all ancestors are visible.
maxItemsnumber | undefined4Maximum visible destinations while collapsed, including root and current page; at least two, four by default.
expandedboolean | undefined–Whether all ancestors are visible. Omit to let the component own the disclosure.
defaultExpandedboolean | undefinedfalseInitial disclosure state in uncontrolled use.
onExpandedChange((expanded: boolean) => void) | undefined–Requests a disclosure change; navigation itself remains a real link.
classNamestring | undefined–Additional root classes.
testIdstring | undefined–Root test id; the disclosure uses --expand.
refRef<HTMLElement> | undefined–The navigation landmark.
Do

Reports / Engineering / Storage review

Name the parent sections and keep the page title at the end.
Don't

Weather / Crew / Storage review

Do not turn recent browsing history into a page hierarchy.

Usage reference: Atlassian breadcrumbs.