DocumentationComponentsTheme Creator
Theme CreatorGitHubIntroduction
InstallationUsageThemingMotion
Components
BreadcrumbTabsPaginationStepperMenu ItemToolbarMenubarNavigation MenuAccordionCollapsibleCommandBottom NavTop Header MobileTop Header DesktopSidebar
AI agentsContributing
  1. Components
  2. Breadcrumb

Breadcrumb

Navigation trail showing the user's location in a hierarchy, with collapsible middle levels, custom separators, icons and RTL.

$ pnpm add @tessinaui/ui

When to use

  • Pages that sit several levels deep. A trail shows where the page lives and lets people jump back up to any level above it.
  • Pages people land on from outside. A search result or a shared link arrives with no history; the trail supplies the context.
  • Secondary wayfinding. Place it above the page title, next to the primary navigation, never instead of it.
  • Trails you compose yourself. You decide how many crumbs there are, which one is current, and where a level is left out with BreadcrumbEllipsis.
  • Either ending. End on the current page with BreadcrumbPage, or end on the parent when the page's own <h1> is the current node.

When not to use

  • For a linear flow. Checkout, onboarding and wizards are steps, not a hierarchy. Show position with a segmented Progress.
  • On a flat site. With one level below home, a breadcrumb says nothing a back affordance does not.
  • As the only navigation. It tells people where they are, not where else they can go; pair it with a header, Sidebar or Tabs.
  • To switch between siblings at the same level. Use Tabs, or a menu on a crumb (below).
  • To move through pages of a list. Use Pagination.

Installation

Terminal
pnpm add @tessinaui/ui

Usage

example.tsx
import {
  Breadcrumb,
  BreadcrumbList,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbPage,
  BreadcrumbSeparator,
  BreadcrumbEllipsis,
  BreadcrumbSkeleton,
} from "@tessinaui/ui";
example.tsx
<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink href="/">Home</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbLink href="/components">Components</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbPage>Breadcrumb</BreadcrumbPage>
    </BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>

The trail is composed, not configured: you write the crumbs, so you decide how many there are, which one is current, and where a level is left out. The component owns the landmark, the list semantics, the separators and the scale.

Where the trail ends

Both shapes are correct and both are common:

  • End on the current page — the last crumb is a BreadcrumbPage. Use this when the page title is not visible on screen, or repeats far down the page.
  • End on the parent — every crumb is a link and the page's own <h1> is the current node. Most storefronts do this (the trail sits directly above the product title), and it saves reading the same words twice.

Examples

Default

A trail of links ending in the current page.

Sizes

Five scales from xs to xl. Text, separator and ellipsis all step together; on phones every crumb keeps a 44px touch target regardless of size.

Separators

separator="chevron" (default), "slash" or "dot" — or pass your own node to BreadcrumbSeparator. Separators are hidden from assistive tech: they are punctuation, and a screen reader that reads "slash" between every crumb is noise.

Collapsed

BreadcrumbEllipsis marks levels that were left out, so a deep trail still fits one line.

Collapsed, with the hidden levels reachable

Better, when the levels matter: put them behind a real button. The name counts what is hidden ("3 more levels") rather than announcing an ellipsis.

A crumb that opens its siblings

render lets a crumb be whatever element it needs to be — a menu trigger here, a framework router's <Link> in an app — while keeping the trail's own ink, size and focus ring.

Icons

An icon beside a label is decorative. An icon-only crumb needs its own aria-label, or it announces as an empty link.

Counts and status

A badge inside a crumb joins that crumb's accessible name, so keep it short.

Long labels

The trail wraps by default, which is right on a phone. To hold it to one line, cap the label and let it ellipsize — the accessible name is untouched, so a screen reader still reads the whole label. On a link, cap a span inside it rather than the link itself: truncation clips, and on the link it would clip the link's touch target to the height of its text.

RTL

Set dir="rtl" and the trail mirrors, the built-in chevron turns, and anything opened from a crumb lands on the correct side. Leave it unset and the component follows the page.

Background

background paints the trail on a filled plate, which also re-publishes the surface contract so a focus ring inside draws its gap in the plate's colour.

On color

Inside a coloured Surface the trail draws in the plate's own ink: resting crumbs, separators and the ellipsis at its muted tier, the current page and a hovered crumb at full ink. It reads the tone from the Surface, so there is nothing to pass. A trail with background keeps its own page plate wherever it sits.

Loading

BreadcrumbSkeleton is the same box as the real trail. Silent by default; pass label when this trail is the region a reader should be told about.

API Reference

Breadcrumb

Renders <nav aria-label="Breadcrumb">.

PropTypeDefaultDescription
size"xs" | "sm" | "md" | "lg" | "xl""md"Scales text, separator and ellipsis together
rounded"none" | "sm" | "md" | "lg" | "full""full"Corner scale. Rounds the background plate, and steps each crumb's focus corner with it
separator"chevron" | "slash" | "dot""chevron"Glyph rendered by BreadcrumbSeparator when it has no children
dir"ltr" | "rtl"—Writing direction. Unset, the trail inherits the page's; when set it also directs any popup opened from a crumb
backgroundbooleanfalsePaints the trail on a filled plate with size-appropriate padding

Forwards className, ref and any other <nav> attribute.

BreadcrumbList

Renders <ol>. Takes the row's gap and type scale from size.

BreadcrumbItem

Renders <li>, carrying the phone touch floor.

BreadcrumbLink

PropTypeDefaultDescription
hrefstring—Destination
disabledbooleanfalseMutes the crumb, drops pointer events and removes it from the tab order
renderReact.ReactElement—Render as this element instead — a router <Link>, a menu trigger. Classes and props merge onto it, and both refs are kept

Forwards every other <a> attribute.

BreadcrumbPage

The current page: a <span aria-current="page">. Forwards all span attributes.

BreadcrumbSeparator

Renders <li role="presentation" aria-hidden="true">. Empty, it draws the trail's separator; with children, exactly what you pass:

example.tsx
<BreadcrumbSeparator>
  <span aria-hidden="true">→</span>
</BreadcrumbSeparator>

The built-in chevron mirrors itself under RTL. A separator you supply is left alone — mirroring an arbitrary glyph is as likely to be wrong as right.

BreadcrumbEllipsis

PropTypeDefaultDescription
labelstring"More pages"What assistive tech hears in place of the glyph

BreadcrumbSkeleton

PropTypeDefaultDescription
itemsnumber3Crumb placeholders, including the current page
labelsnumber[]—Per-crumb label lengths in characters, so each bar measures what its label will
collapsedbooleanfalseRender first · … · last two, the shape a collapsed trail produces
labelstring—Announcement for assistive tech. Silent when unset
size · rounded · separator · background · dir—mirrors BreadcrumbKeep these equal to the real trail's so nothing shifts when it arrives

Accessibility

VoiceOver + Safari: passed 2026-09-14. The trail reads "Breadcrumb, navigation", "list 3 items", "link, Home", "link, Components", and the current page as plain text, "Breadcrumb" — its separators are silent. NVDA and JAWS are untested.

  • The root is a <nav> landmark named Breadcrumb, wrapping an ordered list — the shape the ARIA Authoring Practices Guide prescribes. Pass aria-label to translate that name; do not remove it.
  • The current page carries aria-current="page". It is a plain span, not a disabled link: the page you are already on is not a broken destination.
  • Separators are aria-hidden. They exist visually and nowhere else.
  • BreadcrumbEllipsis announces "More pages" (override with label), while its glyph is hidden. When you wrap it in a button, name the button and hide the ellipsis inside it — otherwise the same thing is announced twice.
  • No keyboard interaction to learn. A breadcrumb is a row of links, so Tab and Enter are the whole model. Anything more means you have built a menu, and it should say so with the right role.
  • Touch targets are ≥44px on phones. Crumbs wrap rather than scroll, so no level is ever placed out of reach.
CoachMarkTabs

On this page

When to useWhen not to useInstallationUsageWhere the trail endsExamplesDefaultSizesSeparatorsCollapsedCollapsed, with the hidden levels reachableA crumb that opens its siblingsIconsCounts and statusLong labelsRTLBackgroundOn colorLoadingAPI ReferenceBreadcrumbBreadcrumbListBreadcrumbItemBreadcrumbLinkBreadcrumbPageBreadcrumbSeparatorBreadcrumbEllipsisBreadcrumbSkeletonAccessibility