Breadcrumbs
Displays the current location within the hierarchy. It allows users to go back higher in the hierarchy.
import { Breadcrumb, Breadcrumbs } from "@opengovsg/oui"import { Home } from "lucide-react"export const Example = () => { return ( <Breadcrumbs> <Breadcrumb href="#"> <Home /> Home </Breadcrumb> <Breadcrumb href="#">Components</Breadcrumb> <Breadcrumb>Breadcrumbs</Breadcrumb> </Breadcrumbs> )}Usage
import { Breadcrumb, Breadcrumbs } from "@opengovsg/oui"<Breadcrumbs>
<Breadcrumb href="#">Home</Breadcrumb>
<Breadcrumb href="#">Components</Breadcrumb>
<Breadcrumb>Breadcrumbs</Breadcrumb>
</Breadcrumbs>Alternatively, install the component as local source via the shadcn CLI:
npx shadcn@latest add https://oui.open.gov.sg/r/breadcrumbs.jsonpnpm dlx shadcn@latest add https://oui.open.gov.sg/r/breadcrumbs.jsonnpx shadcn@latest add https://oui.open.gov.sg/r/breadcrumbs.jsonbunx --bun shadcn@latest add https://oui.open.gov.sg/r/breadcrumbs.jsonOUI exports 2 breadcrumb-related components:
- Breadcrumbs: The container component that provides context and layout for breadcrumb items.
- Breadcrumb: An individual breadcrumb item, rendered as a link by default. The last item is automatically styled as the current page.
Examples
Custom Separator
Use the separator prop to change the separator between breadcrumb items. The default separator is a chevron icon. You can pass any string (e.g. "/", "|") or a custom React node.
import { Breadcrumb, Breadcrumbs } from "@opengovsg/oui"export const Example = () => { return ( <div className="flex flex-col gap-4"> <Breadcrumbs separator="/"> <Breadcrumb href="#">Home</Breadcrumb> <Breadcrumb href="#">Components</Breadcrumb> <Breadcrumb>Breadcrumbs</Breadcrumb> </Breadcrumbs> <Breadcrumbs separator="|"> <Breadcrumb href="#">Home</Breadcrumb> <Breadcrumb href="#">Components</Breadcrumb> <Breadcrumb>Breadcrumbs</Breadcrumb> </Breadcrumbs> </div> )}Disabled
Use the isDisabled prop to disable all breadcrumb items, preventing navigation while maintaining layout consistency.
import { Breadcrumb, Breadcrumbs } from "@opengovsg/oui"export const Example = () => { return ( <Breadcrumbs isDisabled> <Breadcrumb href="#">Home</Breadcrumb> <Breadcrumb href="#">Components</Breadcrumb> <Breadcrumb>Breadcrumbs</Breadcrumb> </Breadcrumbs> )}Truncation
When breadcrumbs have many items, you can use the itemsBeforeTruncate prop to collapse middle items behind an ellipsis. Clicking the ellipsis opens a dropdown menu showing the hidden items.
Use itemsAfterTruncate to control how many items are shown after the ellipsis (default: 2).
Note: Truncation props are ignored when using the Collection API (
itemsprop). These two modes are mutually exclusive and this is enforced at the type level.
import { Breadcrumb, Breadcrumbs } from "@opengovsg/oui"export const Example = () => { return ( <Breadcrumbs itemsBeforeTruncate={1}> <Breadcrumb href="#">Home</Breadcrumb> <Breadcrumb href="#">Category</Breadcrumb> <Breadcrumb href="#">Subcategory A</Breadcrumb> <Breadcrumb onPress={() => alert("Subcategory B pressed")}> Subcategory B </Breadcrumb> <Breadcrumb href="#">Subcategory C</Breadcrumb> <Breadcrumb>Current Page</Breadcrumb> </Breadcrumbs> )}Truncation Without Dropdown
Set renderTruncate={null} to display the ellipsis without an interactive dropdown.
import { Breadcrumb, Breadcrumbs } from "@opengovsg/oui"export const Example = () => { return ( <Breadcrumbs itemsBeforeTruncate={1} renderTruncate={null}> <Breadcrumb href="#">Home</Breadcrumb> <Breadcrumb href="#">Category</Breadcrumb> <Breadcrumb href="#">Subcategory A</Breadcrumb> <Breadcrumb onPress={() => alert("Subcategory B pressed")}> Subcategory B </Breadcrumb> <Breadcrumb href="#">Subcategory C</Breadcrumb> <Breadcrumb>Current Page</Breadcrumb> </Breadcrumbs> )}Custom Truncation Dropdown
Pass a custom render function to renderTruncate to fully control the dropdown content and styling.
import { Breadcrumb, Breadcrumbs, Menu, MenuItem } from "@opengovsg/oui"export const Example = () => { return ( <Breadcrumbs itemsBeforeTruncate={1} renderTruncate={(items) => ( <Menu placement="bottom start" classNames={{ base: "bg-brand-primary-50 p-2" }} items={items} > {(item) => ( <MenuItem key={item.id} {...item} classNames={{ container: "text-brand-primary-700 font-bold", }} > {item.children} </MenuItem> )} </Menu> )} > <Breadcrumb href="#">Home</Breadcrumb> <Breadcrumb href="#">Category</Breadcrumb> <Breadcrumb href="#">Subcategory A</Breadcrumb> <Breadcrumb onPress={() => alert("Subcategory B pressed")}> Subcategory B </Breadcrumb> <Breadcrumb href="#">Subcategory C</Breadcrumb> <Breadcrumb>Current Page</Breadcrumb> </Breadcrumbs> )}Collection API
As an alternative to JSX children, you can use the Collection API by passing an items array. Items are rendered using a render function.
Note: The Collection API cannot be used simultaneously with truncation props (
itemsBeforeTruncate,itemsAfterTruncate,renderTruncate). This is enforced at the type level.
import { Breadcrumb, Breadcrumbs } from "@opengovsg/oui"export const Example = () => { const items = [ { id: "home", href: "#", children: "Home" }, { id: "category", href: "#", children: "Category" }, { id: "subcategory-a", href: "#", children: "Subcategory A" }, { id: "subcategory-b", onPress: () => alert("Subcategory B pressed"), children: "Subcategory B", }, { id: "subcategory-c", href: "#", children: "Subcategory C" }, { id: "current-page", children: "Current Page" }, ] return ( <Breadcrumbs items={items}> {(item) => <Breadcrumb {...item} />} </Breadcrumbs> )}Custom Breadcrumb Content
Breadcrumb items accept arbitrary content. For example, you can embed a MenuTrigger inside a breadcrumb to create a dropdown navigation item.
import { Breadcrumb, Breadcrumbs, Link, Menu, MenuItem, MenuTrigger,} from "@opengovsg/oui"export const Example = () => { return ( <Breadcrumbs> <Breadcrumb href="#">Home</Breadcrumb> <Breadcrumb href="#">Category</Breadcrumb> <Breadcrumb> <MenuTrigger> <Link>Subcategory</Link> <Menu> <MenuItem id="option-1" href="#"> Option 1 </MenuItem> <MenuItem id="option-2" href="#"> Option 2 </MenuItem> <MenuItem id="option-3" href="#"> Option 3 </MenuItem> </Menu> </MenuTrigger> </Breadcrumb> <Breadcrumb>Current Page</Breadcrumb> </Breadcrumbs> )}Slots
- base: The outer container of the breadcrumbs list.
- crumb: The wrapper for each individual breadcrumb item.
- link: The link element inside each breadcrumb.
- separator: The separator element between breadcrumb items.
- ellipsisTrigger: The trigger element for the truncation ellipsis.
Custom Styles
You can customize the Breadcrumbs component by passing custom Tailwind CSS classes to the component slots via the classNames prop.
<Breadcrumbs
classNames={{
base: "gap-2",
crumb: "gap-2",
link: "text-brand-primary-500",
separator: "text-base-content-medium",
}}
>
<Breadcrumb>Home</Breadcrumb>
</Breadcrumbs>Individual Breadcrumb items also accept a classNames prop to override styles on a per-item basis (all slots except base).
<Breadcrumb
classNames={{
crumb: "font-bold",
link: "text-brand-primary-700",
separator: "text-base-content-strong",
}}
>
Highlighted
</Breadcrumb>Accessibility
- Breadcrumbs are rendered as an ordered list (
<ol>) inside a<nav>element, providing semantic navigation structure. - The last breadcrumb item is automatically marked as the current page with
aria-current="page". - Separators are hidden from assistive technologies with
aria-hidden. - The truncation ellipsis has an
aria-labelof "Show more breadcrumbs" for screen readers. - Full keyboard navigation is supported.
Props
Breadcrumbs
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | The breadcrumb items |
items | Iterable<T> | - | Item data for the Collection API. Cannot be used with truncation props |
separator | "chevron" | React.ReactNode | string | null | "chevron" | The separator between breadcrumb items |
itemsBeforeTruncate | number | null | null | Number of items to show before the ellipsis. Setting a number enables truncation |
itemsAfterTruncate | number | 2 | Number of items to show after the ellipsis |
renderTruncate | ((items: BreadcrumbEllipsisItem[]) => React.ReactNode) | null | - | Custom render function for the truncation dropdown. Set to null to disable the dropdown |
truncateProps | Partial<MenuProps<object>> | - | Props to pass to the truncation dropdown Menu |
isDisabled | boolean | - | Whether all breadcrumbs are disabled |
classNames | SlotsToClasses<BreadcrumbsSlots> | - | Custom CSS classes for component slots |
Breadcrumb
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | The content of the breadcrumb |
href | string | - | The URL the breadcrumb links to. Omit for the current page |
separator | "chevron" | React.ReactNode | string | null | - | Override the separator for this item |
isDisabled | boolean | - | Whether this breadcrumb is disabled |
classNames | SlotsToClasses<Exclude<BreadcrumbsSlots, "base">> | - | Custom CSS classes for this item's slots |
BreadcrumbEllipsisItem
The shape of items passed to the renderTruncate function.
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for the item |
href | string | The URL the item links to |
children | React.ReactNode | The content of the breadcrumb item |
onPress | (e: PressEvent) => void | Press event handler from the original breadcrumb |