Skip to main content

Design system components

Breadcrumb

Navigation trail with current page indication; middle items collapse into an ellipsis menu when the trail overflows or exceeds maxItems.

Status: stable. Group: navigation. Markdown version: /design-system/components/breadcrumb.md

When to use

Breadcrumb renders the page's location trail as a labelled nav landmark containing an ordered list. Pass items in root-to-current order; entries with href render as links except the last, which always renders as the current page in plain text. Middle entries without href render as text too, so levels without landing pages stay honest. When the trail is wider than its container (or longer than maxItems), the middle entries collapse into an ellipsis button that opens a menu of the hidden levels; the first entry and the current page stay visible. Keep labels short; a breadcrumb is orientation, not prose.

When not to use

  • Do not include the home icon as a separate item. Use label: 'Home' with href: '/' so the AT user hears a word, not a glyph.
  • Do not skip levels to make the trail shorter. If the user is at /work/acme, the parent must be /work, not /.
  • Do not render the breadcrumb above a hero; it gets lost. Place it immediately above the page title so it forms a single "where am I" block.

Look-alikes

The contract names no look-alike with a deciding condition.

Props

Breadcrumb props
PropTypeDefaultDescriptionRequired
itemsBreadcrumbItem[]noneBreadcrumb items in root-to-current order (label, optional href); the last renders as plain text.Yes
aria-labelstringnoneAccessible name for the nav landmark. Defaults to the translated "Breadcrumb" (breadcrumb.label).No
underline"always" | "hover" | "none"alwaysUnderline mode forwarded to the Link for each trail item, the same contract as Link: "always" shows the underline permanently, "hover" reveals it on hover and keyboard focus, "none" omits it. Defaults to always.No
maxItemsnumbernoneStatic collapse cap. When set to a positive number smaller than the item count, the middle items collapse into an ellipsis menu WITHOUT measuring: the first maxItems - 2 leading items and the current item stay visible. Leave unset (or 0) for automatic width-based collapse (the default).No
collapseLabelstringnoneAccessible name for the ellipsis menu trigger. Defaults to the translated "Show N hidden breadcrumbs" (breadcrumb.showHiddenOne / breadcrumb.showHiddenOther).No
homeIconbooleanfalseRender the first item as a house icon instead of its text label. The item's label becomes the icon's accessible name, so screen readers still announce it (e.g. "Home"). Defaults to false.No

Variants

  • Allowed underline values: always, hover, none (default always).

Invalid combinations

The contract records no invalid combinations.

Keyboard

Breadcrumb keyboard behaviour
KeyBehaviour
TabMoves focus to the control and on to the next focusable element. (standard)
EnterActivates the focused control. (standard)
SpaceActivates or toggles the focused control. (standard)
ArrowDownMoves focus or the value in that direction. (standard)
ArrowUpMoves focus or the value in that direction. (standard)
EscapeCloses or dismisses the open layer. (standard)

Rows marked (standard) name a key the contract lists without a description; the behaviour shown is the usual one for that key.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

Breadcrumb rules
LevelRuleHow it is checked
MUSTARIA: Nav landmark.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Aria-label.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Current page on last item.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Default names follow the active language (nav "Breadcrumb" from breadcrumb.label; ellipsis "Show N hidden breadcrumb(s)" from breadcrumb.showHiddenOne / breadcrumb.showHiddenOther, singular or plural by count); aria-label and collapseLabel override them.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTEvery documented keyboard interaction works as specified.Not yet verified: no evidence record. WCAG 2.1.1, 2.1.2.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-11-04.
SHOULDOrder items root -> current; the last item is the page the user is standing on.Not stated in the contract.
SHOULDRely on the translated default names, or pass aria-label (and collapseLabel) when a page has more than one trail and each needs its own name.Not stated in the contract.
SHOULDPoint hrefs at real route segments so every linked level is actually navigable.Not stated in the contract.
SHOULDOmit href on middle levels that have no landing page; they render as plain text instead of dead links.Not stated in the contract.
SHOULD NOTDo not start every trail with the site name; begin at the section root ("Home" at most).Not stated in the contract.
SHOULD NOTDo not hand-author "…" items to fake a collapsed middle; the trail collapses its middle items into an ellipsis menu itself, on overflow or at maxItems.Not stated in the contract.

Install and import

  • Install: npm install @digitaltableteur/react (version 0.9.1, restricted access on npm).
  • Import: import { Breadcrumb } from "@digitaltableteur/react";
  • Entry point: @digitaltableteur/react/navigation exports it too.
  • Styles: import @digitaltableteur/react/style.css once at the app boundary.
  • Also available as the custom element <dt-breadcrumb>; see the custom elements manifest.