--primitiv-breadcrumb-overflow-trigger-hover-background--primitiv-breadcrumb-overflow-trigger-active-backgroundA Breadcrumb trail that collapses its middle entries behind an overflow menu once the trail exceeds keepStart + keepEnd items.
primitiv add breadcrumb-overflow installs it whichever mode you are reading.Preview
import { BreadcrumbOverflow } from "@/components/ui/breadcrumb-overflow";import { BreadcrumbLink, BreadcrumbPage } from "@/components/ui/breadcrumb";
<BreadcrumbOverflow keepStart={1} keepEnd={1} size="md"> <BreadcrumbLink href="#home">Home</BreadcrumbLink> <BreadcrumbLink href="#library">Library</BreadcrumbLink> <BreadcrumbLink href="#fiction">Fiction</BreadcrumbLink> <BreadcrumbLink href="#mystery">Mystery</BreadcrumbLink> <BreadcrumbPage>Neuromancer</BreadcrumbPage></BreadcrumbOverflow>Density is set by a data-density ancestor — the Context system, not a BreadcrumbOverflow prop.
npx primitiv add breadcrumb-overflowpnpm dlx primitiv add breadcrumb-overflowyarn dlx primitiv add breadcrumb-overflowbunx primitiv add breadcrumb-overflowImport
import { BreadcrumbOverflow } from "@/components/ui/breadcrumb-overflow";No headless primitive — this one ships only as a copied styled surface, so primitiv add is the only way in, whichever mode you are reading.
Extends HTMLElement — every native attribute of that element is accepted and forwarded.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | — | The trail's BreadcrumbLink / BreadcrumbPage elements, in order. |
| keepEnd | number | 1 | How many crumbs to always show at the end of the trail (typically including the current page) after the overflow menu. |
| keepStart | number | 1 | How many crumbs to always show at the start of the trail before the overflow menu. |
| menuLabel | string | "Show hidden pages" | Accessible label for the overflow trigger button. |
| size | "xs" | "sm" | "md" | "lg" | "xl" | "md" | Matches Breadcrumb's own size; also sizes the overflow trigger button
and the menu it opens. |
--primitiv-breadcrumb-overflow-trigger-hover-background--primitiv-breadcrumb-overflow-trigger-active-background| Key | Behaviour |
|---|---|
| Enter | Open the overflow menu when the … trigger is focused. |
| Space | Also opens the overflow menu — it is a real <button>. |
| ArrowDown / ArrowUp | Move between the hidden crumbs once the menu is open (the Dropdown's roving focus). |
| Escape | Close the menu and return focus to the … trigger. |
Breadcrumb.Ellipsis (a decorative …), BreadcrumbOverflow's ellipsis is a real menu button opening a Dropdown of the collapsed crumbs — so every ancestor page is still navigable by keyboard and screen reader, not just by sight.menuLabel (e.g. Show 3 hidden pages) for a name that says what the … does; a bare ellipsis announces nothing useful.<nav>. The same landmark and aria-current="page" current-page rules as Breadcrumb apply — the last child should be a BreadcrumbPage, not a link.anchor-name per instance; BreadcrumbOverflow derives its own from useId(), so you can render several without the menus fighting over one anchor — no wiring needed on your part.href, click handler or asChild router link on a BreadcrumbLink keeps working whether it shows in the trail or the overflow menu.Pass the crumbs as flat BreadcrumbLinks ending in a BreadcrumbPage, and BreadcrumbOverflow keeps keepStart at the front and keepEnd at the back, folding the middle behind an ellipsis. Click the … — it opens a real menu of the hidden crumbs (a Dropdown), so nothing is lost. The anchor wiring is handled for you: it derives a unique anchor-name from useId(), so two of these on one page don't collide.
import { BreadcrumbOverflow } from "@/components/ui/breadcrumb-overflow";import { BreadcrumbLink, BreadcrumbPage } from "@/components/ui/breadcrumb";
<BreadcrumbOverflow keepStart={1} keepEnd={1}> <BreadcrumbLink href="#home">Home</BreadcrumbLink> <BreadcrumbLink href="#library">Library</BreadcrumbLink> <BreadcrumbLink href="#fiction">Fiction</BreadcrumbLink> <BreadcrumbLink href="#mystery">Mystery</BreadcrumbLink> <BreadcrumbPage>Neuromancer</BreadcrumbPage></BreadcrumbOverflow>keepStart / keepEnd are separate axes, not a single maxVisible, so you choose how many crumbs anchor each end independently — keep two at the front (Home / Library / … / Neuromancer) when the top of the hierarchy is the useful context, or two at the back when the leaf's neighbours are. The middle collapses only when more than one crumb would be hidden; otherwise every crumb shows.
import { BreadcrumbOverflow } from "@/components/ui/breadcrumb-overflow";import { BreadcrumbLink, BreadcrumbPage } from "@/components/ui/breadcrumb";
<BreadcrumbOverflow keepStart={2} keepEnd={1}> <BreadcrumbLink href="#home">Home</BreadcrumbLink> <BreadcrumbLink href="#library">Library</BreadcrumbLink> <BreadcrumbLink href="#fiction">Fiction</BreadcrumbLink> <BreadcrumbLink href="#mystery">Mystery</BreadcrumbLink> <BreadcrumbPage>Neuromancer</BreadcrumbPage></BreadcrumbOverflow>When the trail fits — keepStart + keepEnd covers it, with at most one crumb that would be hidden — nothing collapses and no menu appears: it renders every crumb exactly like a plain Breadcrumb. So you can wire BreadcrumbOverflow up unconditionally and it only reaches for the ellipsis when the trail actually outgrows the space.
import { BreadcrumbOverflow } from "@/components/ui/breadcrumb-overflow";import { BreadcrumbLink, BreadcrumbPage } from "@/components/ui/breadcrumb";
{/* three crumbs, keepStart 1 + keepEnd 1 → nothing to collapse */}<BreadcrumbOverflow keepStart={1} keepEnd={1}> <BreadcrumbLink href="#home">Home</BreadcrumbLink> <BreadcrumbLink href="#library">Library</BreadcrumbLink> <BreadcrumbPage>Neuromancer</BreadcrumbPage></BreadcrumbOverflow>size matches Breadcrumb's own scale and also sizes the overflow trigger and its menu, so the whole trail stays consistent. Each size rescales again with the nearest data-density ancestor.
import { BreadcrumbOverflow } from "@/components/ui/breadcrumb-overflow";import { BreadcrumbLink, BreadcrumbPage } from "@/components/ui/breadcrumb";
<div data-density="comfortable"> <BreadcrumbOverflow size="sm" keepStart={1} keepEnd={1}>{/* … */}</BreadcrumbOverflow></div>