# Breadcrumb

A row of links that shows the place of the page in a hierarchy.

```tsx
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>
  )
}
```

## Usage guidelines

- **More than one level.** A breadcrumb links to each parent of the page. For one parent, use `PageBackLink` from [Page](/docs/components/page).
- **One current page.** The last item is a `BreadcrumbPage`. It is not a link.
- **Above the title.** In a page, the breadcrumb goes in the header, above the title.
- **Not for the steps of a task.** A breadcrumb shows a hierarchy. It does not show progress.

## Anatomy

Import the parts and put them together.

```tsx title="Anatomy"

  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. |

## Examples

### Router links

`BreadcrumbLink` takes an `href` string. It renders the link through the link component of the app. Set this component one time with [Link Provider](/docs/utilities/link-provider).

For one link with another component, pass `linkComponent`. To style a link that you render yourself, pass `asChild`.

```tsx
<BreadcrumbLink href="/projects">Projects</BreadcrumbLink>

// `Link` is the link component of your router.
<BreadcrumbLink asChild>
  <Link to="/projects">Projects</Link>
</BreadcrumbLink>
```

### Separator

The separator shows a chevron by default. Pass children to `BreadcrumbSeparator` to show another mark.

```tsx
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>
  )
}
```

### Icon

A link with only an icon must have a name. Add a text with the `sr-only` class.

```tsx
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>
  )
}
```

### Collapsed levels

In a deep hierarchy, replace the middle levels with `BreadcrumbEllipsis`. Put it in the trigger of a [Dropdown Menu](/docs/components/dropdown-menu) that lists these levels.

```tsx
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>
  )
}
```

### Long names

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`.

```tsx
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>
  )
}
```

### Page header

Put the breadcrumb in the `eyebrow` prop of `PageHeader`. It shows above the title of the page.

```tsx
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>
      }
    />
  )
}
```

## Accessibility

- `Breadcrumb` has the label "breadcrumb". Pass `aria-label` to change it.
- `BreadcrumbPage` sets `aria-current="page"`.
- Screen readers ignore the separators and the ellipsis. Give the trigger of the ellipsis an `aria-label`.

## API reference

Each part also accepts the attributes of its element.

### Breadcrumb

`Breadcrumb` has no props of its own. It accepts the attributes of the element it renders.

### BreadcrumbList

`BreadcrumbList` has no props of its own. It accepts the attributes of the element it renders.

### BreadcrumbItem

`BreadcrumbItem` has no props of its own. It accepts the attributes of the element it renders.

### BreadcrumbLink

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `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` is ignored. |
| `linkComponent` | `LinkComponent` |  | Link component for this crumb only, overriding the one from the nearest `LinkProvider` (a plain `<a>` by default). Usually you set a `LinkProvider` once at the app root instead. |

### BreadcrumbPage

`BreadcrumbPage` has no props of its own. It accepts the attributes of the element it renders.

### BreadcrumbSeparator

`BreadcrumbSeparator` has no props of its own. It accepts the attributes of the element it renders.

### BreadcrumbEllipsis

`BreadcrumbEllipsis` has no props of its own. It accepts the attributes of the element it renders.
