This component no longer exists. It was in ns-ui’s manifest when we first indexed it and is not there now — the registry served its inventory on 2026-08-07 and this item was not on it. The install command below will fail. It is kept here because a tutorial somewhere still tells people to run it.
Breadcrumb Overflow Menu
ns-ui/breadcrumb-overflow-menuRemovedComponent
A breadcrumb trail that collapses from the middle into a menu of the hidden levels, with an accent rule that sweeps under the current level.
Live preview
live · rendered by the registry
Rendered by ns-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://design.helpmarq.com/r/breadcrumb-overflow-menu.jsonSource
1"use client";23import {4 useCallback,5 useEffect,6 useId,7 useMemo,8 useRef,9 useState,10 type KeyboardEvent as ReactKeyboardEvent,11 type ReactNode,12} from "react";13import { createPortal } from "react-dom";1415// A breadcrumb that gives way from the middle. When the trail can't fit, the16// root and the last two levels survive and everything between them folds into17// one "…" button that opens a menu of the hidden levels — so nothing is lost18// to keyboard or assistive tech, it just moves.19//20// Every width used by the fit calculation is read from a second, hidden copy21// of the FULL uncollapsed trail (absolute, visibility:hidden, nowrap) that sits22// outside flow and never changes size. Measuring the visible list instead is23// the classic way to break this: collapsing shrinks the measured content, which24// says "it fits", which expands, which overflows — permanent jitter at any25// width near the threshold. The "…" chip's own width is in the ghost layer and26// in the budget, and everything is remeasured once on document.fonts.ready27// because a webfont swap moves every number.28//29// The current level carries a 2px accent underline that sweeps 0 → text width30// whenever the last crumb's id changes (the span is keyed on it, so arriving31// somewhere new re-runs the sweep). Reduced motion renders it at full width32// with no transition and mounts the menu with no fade.3334export type Crumb = {35 id: string;36 label: string;37 /** Renders an <a>. Omit and the crumb renders a <button>. */38 href?: string;39};4041export interface WornPathProps {42 /** Ordered root → current. The last item is the current page. */43 items: Crumb[];44 /** Rendered between crumbs. Default "/". */45 separator?: ReactNode;46 /** Crumbs at the head that can never collapse. Default 1. */47 minVisibleHead?: number;48 /** Crumbs at the tail that can never collapse, current included. Default 2. */49 minVisibleTail?: number;50 onNavigate?: (item: Crumb, index: number) => void;51 ariaLabel?: string;52 className?: string;53}5455// re-expanding costs 24px more room than staying collapsed, so a container56// resting exactly on the threshold settles instead of oscillating57const HYSTERESIS = 24;5859const crumbClass = (current: boolean) =>60 current61 ? "whitespace-nowrap px-1 py-0.5 text-sm font-medium text-foreground"62 : [63 "whitespace-nowrap rounded-sm px-1 py-0.5 text-sm text-muted",64 "transition-colors duration-150 ease-out",65// … truncated
