Primitives
Breadcrumb
A row of links that shows the place of the page in a hierarchy.
import type * as React from 'react'
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from 'ferry-ui'
// The demo stays on this page. In an app, give the path to `href` and remove `onClick`.
const stay = (event: React.MouseEvent) => event.preventDefault()
export default function BreadcrumbHero() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Acme
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Projects
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Website redesign</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}PageBackLink from Page.BreadcrumbPage. It is not a link.Import the parts and put them together.
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from 'ferry-ui'
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink />
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbEllipsis />
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage />
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>| Part | Element | Role |
|---|---|---|
Breadcrumb | nav | The root. |
BreadcrumbList | ol | The list of items. It wraps on a small screen. |
BreadcrumbItem | li | One level. It holds a link, the current page or an ellipsis. |
BreadcrumbLink | a | A link to a parent page. |
BreadcrumbPage | span | The current page. |
BreadcrumbSeparator | li | The mark between two items. |
BreadcrumbEllipsis | span | The "…" mark for the levels that do not show. |
BreadcrumbLink takes an href string. It renders the link through the link component of the app. Set this component one time with Link Provider.
For one link with another component, pass linkComponent. To style a link that you render yourself, pass asChild.
<BreadcrumbLink href="/projects">Projects</BreadcrumbLink>
// `Link` is the link component of your router.
<BreadcrumbLink asChild>
<Link to="/projects">Projects</Link>
</BreadcrumbLink>The separator shows a chevron by default. Pass children to BreadcrumbSeparator to show another mark.
import type * as React from 'react'
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from 'ferry-ui'
import { Slash } from 'lucide-react'
// The demo stays on this page. In an app, give the path to `href` and remove `onClick`.
const stay = (event: React.MouseEvent) => event.preventDefault()
export default function BreadcrumbCustomSeparator() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Acme
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash className="-rotate-12" />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Settings
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash className="-rotate-12" />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>Billing</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}A link with only an icon must have a name. Add a text with the sr-only class.
import type * as React from 'react'
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from 'ferry-ui'
import { Home } from 'lucide-react'
// The demo stays on this page. In an app, give the path to `href` and remove `onClick`.
const stay = (event: React.MouseEvent) => event.preventDefault()
export default function BreadcrumbIcon() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay} className="flex items-center">
<Home className="size-3.5" />
<span className="sr-only">Home</span>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Members
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Maya Chen</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}In a deep hierarchy, replace the middle levels with BreadcrumbEllipsis. Put it in the trigger of a Dropdown Menu that lists these levels.
import type * as React from 'react'
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from 'ferry-ui'
// The demo stays on this page. In an app, give the path to `href` and remove `onClick`.
const stay = (event: React.MouseEvent) => event.preventDefault()
export default function BreadcrumbCollapsed() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Acme
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger
aria-label="Show the hidden levels"
className="flex cursor-pointer items-center rounded-sm outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring"
>
<BreadcrumbEllipsis className="size-5" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documents</DropdownMenuItem>
<DropdownMenuItem>Finance</DropdownMenuItem>
<DropdownMenuItem>2026</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Invoices
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>INV-2041</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}The list wraps when it is wider than its container. To limit the width of one item, add the classes max-w-32 truncate. Keep the full name in title.
import type * as React from 'react'
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from 'ferry-ui'
// The demo stays on this page. In an app, give the path to `href` and remove `onClick`.
const stay = (event: React.MouseEvent) => event.preventDefault()
export default function BreadcrumbLong() {
return (
<Breadcrumb className="w-full max-w-xs">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Acme
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay} className="max-w-32 truncate" title="Customer reviews of the quarter">
Customer reviews of the quarter
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage className="max-w-40 truncate" title="Review of the third quarter with Acme">
Review of the third quarter with Acme
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}Put the breadcrumb in the eyebrow prop of PageHeader. It shows above the title of the page.
import type * as React from 'react'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
Button,
PageHeader,
StatusBadge,
} from 'ferry-ui'
import { Download } from 'lucide-react'
// The demo stays on this page. In an app, give the path to `href` and remove `onClick`.
const stay = (event: React.MouseEvent) => event.preventDefault()
export default function BreadcrumbPageHeader() {
return (
<PageHeader
title="Invoice INV-2041"
badges={<StatusBadge tone="success" label="Paid" size="sm" />}
actions={<Button icon={<Download />}>Download PDF</Button>}
eyebrow={
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Billing
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="#" onClick={stay}>
Invoices
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>INV-2041</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
}
/>
)
}Breadcrumb has the label "breadcrumb". Pass aria-label to change it.BreadcrumbPage sets aria-current="page".aria-label.Each part also accepts the attributes of its element.
Breadcrumb has no props of its own. It accepts the attributes of the element it renders.
BreadcrumbList has no props of its own. It accepts the attributes of the element it renders.
BreadcrumbItem has no props of its own. It accepts the attributes of the element it renders.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | - |
Merge the crumb styles onto the single child element (e.g. a router link you render yourself) instead of rendering a link. | ||
linkComponent | LinkComponent | - |
Link component for this crumb only, overriding the one from the nearest | ||
BreadcrumbPage has no props of its own. It accepts the attributes of the element it renders.
BreadcrumbSeparator has no props of its own. It accepts the attributes of the element it renders.
BreadcrumbEllipsis has no props of its own. It accepts the attributes of the element it renders.