Breadcrumb
Shows where the page sits in the product and gives a link to each level above it.
Examples
560px
320px
200px
Fit
fulldefault
folded
cut
States
rest
current
Usage
When to use it
- Use
- The page is three or more levels deep: workspace, agent, run.
- Use
- A detail page needs a way back to its list and to the levels above.
- Not for
- The page is a peer of its neighbours, like Runs next to Keys. Use Tabs.
- Not for
- The person pages through results. Use Pagination.
- Not for
- The page is one level below home. The page header title is enough.
Rules
7 rules
- Should
- Use BreadcrumbTrail with items; compose the parts by hand only for a fixed trail of three or fewer. Because the trail measures its container and folds crumbs into a menu in a fixed order, which hand-built parts do not.
- Must
- Make the last item the current page, with no href. Because the current page is ink and not a link, and aria-current="page" tells a screen reader where it is.
- Must
- Order items from the root to the current page. Because the trail folds from the left and keeps the current page last, so a reversed list folds the wrong crumbs.
- Must
- Set an ID crumb with id: true or BreadcrumbId. Because it sets the ID in mono and cuts the middle while keeping the type prefix, so run_8f2a…e5b6a7 stays readable.
- Must
- Pass renderLink with your router link so a press does not reload the page. Because without it every crumb is a plain anchor and each press is a full page load.
- Should
- Use the page title as the crumb label, and a short noun for a list level. Because a crumb that names a page differently from its heading sends the person to a place they do not recognise.
- Never
- Render two breadcrumbs on one page. Because each is a nav landmark with the same name, so a screen reader cannot tell them apart.
Accessibility
5 checks
- The root is a nav named "Breadcrumb" holding an ordered list; the separators are aria-hidden.
- The current page has aria-current="page" and is not a link.
- The fold button names its count ("2 more levels") and opens a menu of links with arrow keys and Escape.
- A cut current page carries its full text as a title, and an ID crumb keeps the whole ID for screen readers.
- Links show a 2px ink outline on focus and underline on hover; touch targets are at least 24px tall.
Edge cases
8 edge cases
- Trail too wide
- Middle crumbs fold into a "…" menu from the left, then the current page truncates, then the root joins the menu.
- Current page
- Never shrinks below 8ch and the trail never ends in a slash.
- One item
- Renders the current page alone; it truncates if it does not fit.
- Long ID
- Past 18 characters it shows the type prefix and 4 characters, an ellipsis and the last 6.
- First paint
- It measures a hidden copy before it decides, so nothing jumps while it folds.
- Container resizes
- It measures again and unfolds as room returns.
- Right to left
- The trail mirrors; labels use dir="auto".
- Zoom 200%
- More crumbs fold sooner, and every folded one stays one menu press away.
API
5 props
itemsCrumb[]defaultrequiredrenderLink(href: string) => ReactElementCrumb idbooleandefaultfalseBreadcrumb partsBreadcrumbList, Item, Link, Page, Separator, EllipsisclassNamestring
Tokens
11 tokens
--crumb-floor- 8ch
--radius-inner- 4px
--radius-soft- 6px
--text-1- var(--ink)
--text-2- oklch(var(--ink-c) / 0.80)
--text-3- oklch(var(--ink-c) / 0.66)
--surface-hover- oklch(var(--ink-c) / 0.05)
--surface-pressed- oklch(var(--ink-c) / 0.08)
--popover- 288px
--type-label- 400 14px/16px var(--font-sans)
--type-tag- var(--type-code-sm)