breadcrumb
Displays the path to the current resource using a hierarchy of links.
Philosophy
Breadcrumbs answer "where am I?" - the most basic navigation question. We keep the API declarative (BreadcrumbList -> BreadcrumbItem -> BreadcrumbLink) rather than generating breadcrumbs from routes because not every route maps cleanly to a breadcrumb trail. The Separator and Ellipsis sub-components handle the visual connecting tissue.
Installation
npx @gentleduck/cli add breadcrumb
npx @gentleduck/cli add breadcrumb
Usage
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/components">Components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb><Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/components">Components</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>Examples
Custom separator
Use a custom component as children for <BreadcrumbSeparator /> to create a custom separator.
import { SlashIcon } from "lucide-react"
...
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbLink href="/components">Components</BreadcrumbLink>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>import { SlashIcon } from "lucide-react"
...
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbLink href="/components">Components</BreadcrumbLink>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>Dropdown
You can compose <BreadcrumbItem /> with a <DropdownMenu /> to create a dropdown in the breadcrumb.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
...
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger>
Components
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
...
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger>
Components
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>Collapsed
We provide a <BreadcrumbEllipsis /> component to show a collapsed state when the breadcrumb is too long.
import { BreadcrumbEllipsis } from "@/components/ui/breadcrumb"
...
<Breadcrumb>
<BreadcrumbList>
{/* ... */}
<BreadcrumbItem>
<BreadcrumbEllipsis />
</BreadcrumbItem>
{/* ... */}
</BreadcrumbList>
</Breadcrumb>import { BreadcrumbEllipsis } from "@/components/ui/breadcrumb"
...
<Breadcrumb>
<BreadcrumbList>
{/* ... */}
<BreadcrumbItem>
<BreadcrumbEllipsis />
</BreadcrumbItem>
{/* ... */}
</BreadcrumbList>
</Breadcrumb>Link component
To use a custom link component from your routing library, you can use the asChild prop on <BreadcrumbLink />.
import Link from "next/link"
...
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/">Home</Link>
</BreadcrumbLink>
</BreadcrumbItem>
{/* ... */}
</BreadcrumbList>
</Breadcrumb>import Link from "next/link"
...
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/">Home</Link>
</BreadcrumbLink>
</BreadcrumbItem>
{/* ... */}
</BreadcrumbList>
</Breadcrumb>Responsive
Here's an example of a responsive breadcrumb that composes <BreadcrumbItem /> with <BreadcrumbEllipsis />, <DropdownMenu />, and <Drawer />.
It displays a dropdown on desktop and a drawer on mobile.
Responsive with Ellipsis
A responsive breadcrumb that collapses intermediate items behind an ellipsis, displaying a dropdown on desktop and a drawer on mobile.
Component Composition
RTL Support
Direction is resolved through the shared primitives direction module. Use a local dir="rtl" override when the component exposes it, or set DirectionProvider at app/root level for global RTL/LTR behavior.
Motion
Motion components work standalone, but some compositions may behave unexpectedly — this is still under active development. If you find a broken composition, please file an issue.
Use MotionBreadcrumbItem for staggered fade-up entrance powered by motion. Each breadcrumb item cascades in from left to right.
Requires the motion package. Use MotionBreadcrumbItem instead of BreadcrumbItem and pass the index prop for stagger delay. All other sub-components stay the same.
API Reference
Breadcrumb
| Prop | Type | Default | Description |
|---|---|---|---|
dir | 'ltr' | 'rtl' | - | Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr'). |
separator | React.ReactNode | -- | Custom separator element between breadcrumb items |
className | string | -- | Additional class names to apply |
children | React.ReactNode | -- | Breadcrumb content (typically a BreadcrumbList) |
...props | React.HTMLProps<HTMLElement> | - | Additional props to spread to the nav element |
BreadcrumbList
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional class names to apply |
children | React.ReactNode | -- | List of BreadcrumbItem elements |
...props | React.HTMLProps<HTMLOListElement> | - | Additional props to spread to the ol element |
BreadcrumbItem
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional class names to apply |
children | React.ReactNode | -- | Item content (typically a BreadcrumbLink or BreadcrumbPage) |
...props | React.HTMLProps<HTMLLIElement> | - | Additional props to spread to the li element |
BreadcrumbLink
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | -- | If true, uses the Slot component instead of rendering an <a> directly |
className | string | -- | Additional class names to apply |
children | React.ReactNode | -- | Link content |
...props | React.HTMLProps<HTMLAnchorElement> | - | Additional props to spread to the a element |
BreadcrumbPage
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional class names to apply |
children | React.ReactNode | -- | Page content (rendered with aria-current="page") |
...props | React.ComponentPropsWithoutRef<'span'> | - | Additional props to spread to the span element |
BreadcrumbSeparator
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional class names to apply |
children | React.ReactNode | <ChevronRight /> | Custom separator icon; defaults to a ChevronRight icon |
...props | React.ComponentPropsWithoutRef<'li'> | - | Additional props to spread to the li element |
BreadcrumbEllipsis
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | 'More' | Accessible label used for aria-label on the ellipsis element |
className | string | -- | Additional class names to apply |
...props | React.ComponentPropsWithoutRef<'span'> | - | Additional props to spread to the span element |
MotionBreadcrumbList
Wraps BreadcrumbList and auto-injects a stagger index into each MotionBreadcrumbItem and MotionBreadcrumbSeparator child. Items and separators share the same counter, so they cascade together across the whole trail. Requires the motion package.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentPropsWithoutRef<'ol'> | - | All props from BreadcrumbList are supported |
MotionBreadcrumbItem
Renders directly as m.li with a scaleIn entrance using springSnappy for a tight, responsive feel. Requires the motion package.
| Prop | Type | Default | Description |
|---|---|---|---|
index | number | 0 | Stagger delay index (35ms per index). Auto-injected when used inside MotionBreadcrumbList. |
...props | React.ComponentPropsWithoutRef<'li'> | - | All props from BreadcrumbItem are supported |
MotionBreadcrumbSeparator
Renders directly as m.li with a slideFromLeft entrance so the chevron slides in from the previous item. Requires the motion package.
| Prop | Type | Default | Description |
|---|---|---|---|
index | number | 0 | Stagger delay index (35ms per index). Auto-injected when used inside MotionBreadcrumbList. |
children | React.ReactNode | <ChevronRight /> | Custom separator content |
...props | React.ComponentPropsWithoutRef<'li'> | - | All props from BreadcrumbSeparator are supported |