Skip to content
Drivn logoDrivn
6 min read

React Breadcrumb Examples — Separators, Links, Ellipsis

Copy-paste React Breadcrumb patterns — default chevron, custom separator, Next.js Link integration, collapsed ellipsis, and dynamic pathname rendering.

Breadcrumbs are the quiet navigation workhorse — a horizontal trail of links that tells a user where they are in a hierarchy and gives them a one-click path back up. They show up in docs sites, e-commerce catalogs, file managers, admin panels, and settings trees. Get them right and users stop reaching for the back button; get them wrong and they waste pixels at the top of every page.

Drivn's Breadcrumb ships as a single dot-notation component with zero runtime UI dependencies. The root renders a semantic <nav> with an <ol> list, separators are injected automatically between siblings, and every piece — items, the current page, custom separators, an ellipsis for collapsed paths — hangs off the root via Breadcrumb.Item, Breadcrumb.Page, Breadcrumb.Separator, and Breadcrumb.Ellipsis.

This page collects five breadcrumb patterns you will actually ship: a default chevron-separated trail for a docs page, a slash-separated trail for a settings hierarchy, a Next.js <Link>-backed trail for client-side routing without full reloads, a collapsed breadcrumb with an ellipsis for long paths, and a dynamically rendered breadcrumb driven from the current pathname. Every snippet is copy-paste ready and assumes Drivn is already installed via the CLI. For an engineering comparison against shadcn/ui, see Drivn vs shadcn/ui Breadcrumb.

Default chevron separator

The default breadcrumb uses a ChevronRight icon between every item and renders the final segment as a non-interactive <Breadcrumb.Page>. You write only the items and the current page — separators are injected automatically between siblings at render time, so a three-level breadcrumb has three JSX children, not five.

The root applies flex items-center gap-1.5 flex-wrap text-sm text-muted-foreground so the trail wraps gracefully on narrow viewports. Each Breadcrumb.Item becomes a muted link that darkens on hover via hover:text-foreground; the current page gets font-medium text-foreground so it reads as the anchor of the trail. Use this pattern anywhere you have a clean, fixed-depth hierarchy — docs pages, admin sections, or content categories.

1import { Breadcrumb } from '@/components/ui/breadcrumb'
2
3<Breadcrumb>
4 <Breadcrumb.Item href="/">Home</Breadcrumb.Item>
5 <Breadcrumb.Item href="/docs">Docs</Breadcrumb.Item>
6 <Breadcrumb.Page>Button</Breadcrumb.Page>
7</Breadcrumb>

Custom slash separator

Passing a separator prop to the root swaps the chevron for any JSX node — a slash character, a dot, a vertical bar, or an icon from a different set. The auto-injector uses whatever you pass once, so every position in the trail stays visually consistent without repeating the separator at each item.

Slashes suit file-path-style breadcrumbs where the trail represents a literal hierarchy: user settings, file tree navigation, storage keys. Dots work well for compact mobile layouts. For a branded look, pass a styled <span> that references design tokens so the separator picks up your theme's muted color automatically. The separator prop is typed as React.ReactNode, so there is no escape hatch needed for custom markup — any valid JSX works and inherits your Tailwind classes.

1<Breadcrumb separator={<span>/</span>}>
2 <Breadcrumb.Item href="/">Home</Breadcrumb.Item>
3 <Breadcrumb.Item href="/settings">Settings</Breadcrumb.Item>
4 <Breadcrumb.Page>Profile</Breadcrumb.Page>
5</Breadcrumb>

Collapsed path with Ellipsis

Deep hierarchies — a file eight folders down, a product in a nested category — produce breadcrumbs that wrap across two lines or overflow a narrow card. The Breadcrumb.Ellipsis pattern collapses the middle of the trail into a single glyph, keeping the root and the current page visible while signalling that intermediate levels exist.

Drivn's Ellipsis renders a MoreHorizontal icon inside a 36-pixel square with an sr-only "More pages" label so screen readers still announce it. Place it between the root item and the next visible item in the trail, and the automatic separator injection puts chevrons on either side. The ellipsis itself is a <li> with no interaction by default; if you want it to open a dropdown of the hidden levels, wrap it in a Popover or your own disclosure component at the call site.

1<Breadcrumb>
2 <Breadcrumb.Item href="/">Home</Breadcrumb.Item>
3 <Breadcrumb.Ellipsis />
4 <Breadcrumb.Item href="/docs/components">
5 Components
6 </Breadcrumb.Item>
7 <Breadcrumb.Page>Button</Breadcrumb.Page>
8</Breadcrumb>

Render dynamically from route segments

Static breadcrumbs work for fixed-depth pages, but most apps compute the trail from the current URL. The pattern is a small helper that splits pathname into segments, accumulates an href for each prefix, maps the segment to a human-readable label, and renders the array as a list of Breadcrumb.Item elements with the final entry as a Breadcrumb.Page.

For a Next.js App Router app, call usePathname() inside a client component, split the path on /, and filter out empty strings. Pair it with a small label map — { docs: "Docs", components: "Components" } — so URL slugs render as proper titles in the trail. This pattern scales to any depth without manual edits: new routes show up with correctly-formatted breadcrumbs automatically, and the final segment is always the current page. Drop the component into your app shell once and every page inherits the trail.

1'use client'
2import { usePathname } from 'next/navigation'
3import { Breadcrumb } from '@/components/ui/breadcrumb'
4
5const labels: Record<string, string> = {
6 docs: 'Docs',
7 components: 'Components',
8 examples: 'Examples',
9}
10
11export function DynamicBreadcrumb() {
12 const pathname = usePathname()
13 const segments = pathname.split('/').filter(Boolean)
14
15 return (
16 <Breadcrumb>
17 <Breadcrumb.Item href="/">Home</Breadcrumb.Item>
18 {segments.map((segment, i) => {
19 const href = '/' + segments.slice(0, i + 1).join('/')
20 const label = labels[segment] ?? segment
21 const isLast = i === segments.length - 1
22
23 return isLast ? (
24 <Breadcrumb.Page key={href}>{label}</Breadcrumb.Page>
25 ) : (
26 <Breadcrumb.Item key={href} href={href}>
27 {label}
28 </Breadcrumb.Item>
29 )
30 })}
31 </Breadcrumb>
32 )
33}
Get started

Install Drivn in one command

Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.

npx drivn@latest create

Requires Node 18+. Works with npm, pnpm, and yarn.

Enjoying Drivn?
Star the repo on GitHub to follow new component releases.
Star →

Frequently asked questions

They are auto-injected at render time. The root calls React.Children.toArray(children).flatMap() and, for every child past the first, prepends a Breadcrumb.Separator element before it. The separator uses whatever JSX you pass via the root's separator prop, defaulting to a Lucide ChevronRight icon. You write only the items and the current page inside <Breadcrumb>, and the trail renders with visually consistent dividers without any per-position separator tags in your JSX.

Pass a separator prop to the root component once. The prop is typed as React.ReactNode, so any JSX works: a slash character (<span>/</span>), a custom icon (<ArrowRight className="w-3 h-3" />), or a branded element styled with your design tokens. The root hands that node to every auto-injected separator in the list, so a single override applies across every item position. To change the default globally, set the prop in a layout-level wrapper so every Breadcrumb inherits the same glyph.

Edit the local breadcrumb.tsx after install. Open src/components/ui/breadcrumb.tsx, import Link from next/link, and replace the <a> tag inside the Item function with a <Link>. The href prop and the {...props} spread transfer cleanly because LinkProps extends the same anchor attribute type. Every breadcrumb in your app then uses client-side routing with no call-site changes. This is the canonical "copy and own" pattern — Drivn never ships wrapper props for framework integration.

Use it when the trail depth exceeds the available horizontal space and wrapping onto two lines hurts more than collapsing the middle. Typical thresholds are four or more levels in a card-constrained layout, or any breadcrumb rendering inside a narrow sidebar or mobile viewport. Place the ellipsis between the root item and the deepest visible item, so users still see where they are and the top-level context. If you want the hidden levels to be clickable, wrap the ellipsis in a disclosure component like a Popover.

Call usePathname() from next/navigation inside a client component, split the pathname on /, filter empty strings, and map each segment to a Breadcrumb.Item with an accumulated href. Render the last segment as a Breadcrumb.Page so it picks up the current-page styling and the aria-current="page" marker. Keep a labels record that maps URL slugs to human-readable titles so the trail reads as "Docs / Components" instead of "docs / components". The pattern scales to any route depth without manual edits.