Breadcrumb
Where you are in a hierarchy, and the way back up it.
Installation
npx shadcn@latest add https://qure-ui.qure.ai/r/breadcrumb.jsonUsage
import {
Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList,
BreadcrumbPage, BreadcrumbSeparator,
} from '@/components/ui/breadcrumb'<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/worklist">Worklist</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>CT Thorax — ACC-100482</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>A breadcrumb says where a page sits in a structure that exists whether or not the user arrived through it. It is not a history trail: a radiologist who reached a study from a search still belongs under Worklist › Patient › Study, and showing them the search instead is a lie about the shape of the product. If there is no hierarchy — a flat list of settings pages — there is no breadcrumb.
Composition
Base UI has no breadcrumb primitive, and does not need one. Every affordance here comes from the elements themselves, so the parts exist to get the semantics right rather than to add behaviour.
<Breadcrumb> {/* <nav aria-label="Breadcrumb"> — names the landmark */}
<BreadcrumbList> {/* <ol> — the trail is ordered, and that order is the meaning */}
<BreadcrumbItem> {/* <li> — one crumb */}
<BreadcrumbLink /> {/* <a> — an ancestor you can go to */}
</BreadcrumbItem>
<BreadcrumbSeparator/>{/* <li role="presentation" aria-hidden> — a mark, not a crumb */}
<BreadcrumbItem>
<BreadcrumbPage /> {/* <span aria-current="page"> — where you are */}
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>Four of those are load-bearing:
| Part | Why it is what it is |
|---|---|
Breadcrumb | A nav with aria-label="Breadcrumb". Without the label it is one of several unnamed navigation landmarks and a screen-reader user cannot tell them apart. |
BreadcrumbList | An ol, not a div of links. The order carries the hierarchy, and a list announces its length — "list of five items" tells you how deep you are before you have heard a single crumb. |
BreadcrumbPage | A span with aria-current="page", not a link. The page you are on is not somewhere you can navigate to, and a link that goes nowhere is a broken promise. |
BreadcrumbSeparator | An li marked role="presentation" and aria-hidden. It stays inside the ol so the HTML is valid, and out of the accessibility tree so the trail reads "Worklist, link. CT Thorax, current page." with nothing between. |
BreadcrumbSeparator renders our Separator, turned vertical and cut to 12px, when you give it
no children. Pass children to replace it with anything else.
Basic
Study navigation: the list, the patient, the study you have open.
Chevron separators
A chevron reads as direction where a rule reads as division, which suits a trail that is going
somewhere. Anything passed as children replaces the rule; the li stays hidden either way, so
the icon is never announced.
Collapsed
Past four or five crumbs the trail stops being scannable. Drop the middle and leave a control
that brings it back — a button, not the ellipsis alone, because three crumbs the keyboard
cannot reach is a dead end.
With a router
render swaps the <a> for a router link and keeps the class and the props:
<BreadcrumbLink render={<Link href="/docs" />}>Docs</BreadcrumbLink>Do not put a breadcrumb and a back button next to each other doing the same job. The breadcrumb's last-but-one crumb is the back button, and two of them in a header means one of them is wrong the moment the user arrived sideways.
API Reference
Every part takes the props of the element it renders — nav, ol, li, a, span — so
href, target and onClick all work as they look. The one addition:
Prop
Type