Breadcrumb

PreviousNext

Displays the path to the current resource using a hierarchy of links.

  1. Home
  2. Components
  3. Breadcrumb
"use client"

import {
  Breadcrumb,
  BreadcrumbEllipsis,
  BreadcrumbLink,
  Breadcrumbs,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Button } from "@/components/ui/button"
import { Menu, MenuItem, MenuTrigger } from "@/components/ui/menu"

export function BreadcrumbDemo() {
  return (
    <Breadcrumbs>
      <Breadcrumb>
        <BreadcrumbLink href="/">Home</BreadcrumbLink>
        <BreadcrumbSeparator />
      </Breadcrumb>
      <Breadcrumb>
        <MenuTrigger>
          <Button
            variant="ghost"
            className="flex h-auto items-center gap-1 p-0 hover:bg-transparent"
          >
            <BreadcrumbEllipsis className="size-4" />
            <span className="sr-only">Toggle menu</span>
          </Button>
          <Menu placement="bottom start">
            <MenuItem>Documentation</MenuItem>
            <MenuItem>Themes</MenuItem>
            <MenuItem>GitHub</MenuItem>
          </Menu>
        </MenuTrigger>
        <BreadcrumbSeparator />
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbLink href="/docs/components">Components</BreadcrumbLink>
        <BreadcrumbSeparator />
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbLink>Breadcrumb</BreadcrumbLink>
      </Breadcrumb>
    </Breadcrumbs>
  )
}

Installation

pnpm dlx shadcn@latest add breadcrumb

Usage

import {
  Breadcrumb,
  BreadcrumbLink,
  Breadcrumbs,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
<Breadcrumbs>
  <Breadcrumb>
    <BreadcrumbLink href="/">Home</BreadcrumbLink>
    <BreadcrumbSeparator />
  </Breadcrumb>
  <Breadcrumb>
    <BreadcrumbLink href="/components">Components</BreadcrumbLink>
    <BreadcrumbSeparator />
  </Breadcrumb>
  <Breadcrumb>
    <BreadcrumbLink>Breadcrumb</BreadcrumbLink>
  </Breadcrumb>
</Breadcrumbs>

Examples

Custom separator

Use a custom component as children for <BreadcrumbSeparator /> to create a custom separator.

  1. Home
  2. Components
  3. Breadcrumb
import { SlashIcon } from "lucide-react"

import {
  Breadcrumb,
  BreadcrumbLink,
  Breadcrumbs,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"

export function BreadcrumbWithCustomSeparator() {
  return (
    <Breadcrumbs>
      <Breadcrumb>
        <BreadcrumbLink href="/">Home</BreadcrumbLink>
        <BreadcrumbSeparator>
          <SlashIcon />
        </BreadcrumbSeparator>
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbLink href="/components">Components</BreadcrumbLink>
        <BreadcrumbSeparator>
          <SlashIcon />
        </BreadcrumbSeparator>
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbLink>Breadcrumb</BreadcrumbLink>
      </Breadcrumb>
    </Breadcrumbs>
  )
}
import { SlashIcon } from "lucide-react"
 
...
 
<Breadcrumbs>
  <Breadcrumb>
    <BreadcrumbLink href="/">Home</BreadcrumbLink>
    <BreadcrumbSeparator>
      <SlashIcon />
    </BreadcrumbSeparator>
  </Breadcrumb>
  <Breadcrumb>
    <BreadcrumbLink href="/components">Components</BreadcrumbLink>
    <BreadcrumbSeparator>
      <SlashIcon />
    </BreadcrumbSeparator>
  </Breadcrumb>
  <Breadcrumb>
    <BreadcrumbLink>Breadcrumb</BreadcrumbLink>
  </Breadcrumb>
</Breadcrumbs>

You can compose <Breadcrumb /> with a <Menu /> to create a dropdown menu in the breadcrumb.

  1. Home
  2. Breadcrumb
"use client"

import { ChevronDownIcon, SlashIcon } from "lucide-react"

import {
  Breadcrumb,
  BreadcrumbLink,
  Breadcrumbs,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Button } from "@/components/ui/button"
import { Menu, MenuItem, MenuTrigger } from "@/components/ui/menu"

export function BreadcrumbWithDropdown() {
  return (
    <Breadcrumbs>
      <Breadcrumb>
        <BreadcrumbLink href="/">Home</BreadcrumbLink>
        <BreadcrumbSeparator>
          <SlashIcon />
        </BreadcrumbSeparator>
      </Breadcrumb>
      <Breadcrumb>
        <MenuTrigger>
          <Button
            variant="ghost"
            className="flex h-auto items-center gap-1 p-0 hover:bg-transparent [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5"
          >
            Components
            <ChevronDownIcon />
          </Button>
          <Menu placement="bottom start">
            <MenuItem>Documentation</MenuItem>
            <MenuItem>Themes</MenuItem>
            <MenuItem>GitHub</MenuItem>
          </Menu>
        </MenuTrigger>
        <BreadcrumbSeparator>
          <SlashIcon />
        </BreadcrumbSeparator>
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbLink>Breadcrumb</BreadcrumbLink>
      </Breadcrumb>
    </Breadcrumbs>
  )
}
import { Button } from "@/components/ui/button"
import { Menu, MenuItem, MenuTrigger } from "@/components/ui/menu"
 
...
 
<Breadcrumb>
  <MenuTrigger>
    <Button variant="ghost" className="h-auto p-0">
      Components
    </Button>
    <Menu placement="bottom start">
      <MenuItem>Documentation</MenuItem>
      <MenuItem>Themes</MenuItem>
      <MenuItem>GitHub</MenuItem>
    </Menu>
  </MenuTrigger>
  <BreadcrumbSeparator />
</Breadcrumb>

Collapsed

We provide a <BreadcrumbEllipsis /> component to show a collapsed state when the breadcrumb is too long.

  1. Home
  2. Components
  3. Breadcrumb
import {
  Breadcrumb,
  BreadcrumbEllipsis,
  BreadcrumbLink,
  Breadcrumbs,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"

export function BreadcrumbCollapsed() {
  return (
    <Breadcrumbs>
      <Breadcrumb>
        <BreadcrumbLink href="/">Home</BreadcrumbLink>
        <BreadcrumbSeparator />
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbEllipsis />
        <BreadcrumbSeparator />
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbLink href="/docs/components">Components</BreadcrumbLink>
        <BreadcrumbSeparator />
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbLink>Breadcrumb</BreadcrumbLink>
      </Breadcrumb>
    </Breadcrumbs>
  )
}
import { BreadcrumbEllipsis } from "@/components/ui/breadcrumb"
 
...
 
<Breadcrumbs>
  <Breadcrumb>
    <BreadcrumbEllipsis />
    <BreadcrumbSeparator />
  </Breadcrumb>
</Breadcrumbs>

The <BreadcrumbLink /> component from react-aria-components supports both standard href attributes and client-side routing.

  1. Home
  2. Components
  3. Breadcrumb
import {
  Breadcrumb,
  BreadcrumbLink,
  Breadcrumbs,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"

export function BreadcrumbWithLink() {
  return (
    <Breadcrumbs>
      <Breadcrumb>
        <BreadcrumbLink href="/">Home</BreadcrumbLink>
        <BreadcrumbSeparator />
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbLink href="/components">Components</BreadcrumbLink>
        <BreadcrumbSeparator />
      </Breadcrumb>
      <Breadcrumb>
        <BreadcrumbLink>Breadcrumb</BreadcrumbLink>
      </Breadcrumb>
    </Breadcrumbs>
  )
}
<Breadcrumbs>
  <Breadcrumb>
    <BreadcrumbLink href="/">Home</BreadcrumbLink>
    <BreadcrumbSeparator />
  </Breadcrumb>
  <Breadcrumb>
    <BreadcrumbLink href="/components">Components</BreadcrumbLink>
    <BreadcrumbSeparator />
  </Breadcrumb>
  <Breadcrumb>
    <BreadcrumbLink>Breadcrumb</BreadcrumbLink>
  </Breadcrumb>
</Breadcrumbs>

Responsive

Here's an example of a responsive breadcrumb that composes <Breadcrumb /> with <BreadcrumbEllipsis />, <Menu />, and <Drawer />.

It displays a menu on desktop and a drawer on mobile.

  1. Home
  2. Data Fetching
  3. Caching and Revalidating
"use client"

import * as React from "react"

import { useMediaQuery } from "@/hooks/use-media-query"
import {
  Breadcrumb,
  BreadcrumbEllipsis,
  BreadcrumbLink,
  Breadcrumbs,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Button } from "@/components/ui/button"
import {
  Drawer,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
} from "@/components/ui/drawer"
import { Menu, MenuItem, MenuTrigger } from "@/components/ui/menu"

const items = [
  { href: "#", label: "Home" },
  { href: "#", label: "Documentation" },
  { href: "#", label: "Building Your Application" },
  { href: "#", label: "Data Fetching" },
  { label: "Caching and Revalidating" },
]

const ITEMS_TO_DISPLAY = 3

export function BreadcrumbResponsive() {
  const [open, setOpen] = React.useState(false)
  const isDesktop = useMediaQuery("(min-width: 768px)")

  return (
    <Breadcrumbs>
      <Breadcrumb>
        <BreadcrumbLink href={items[0].href ?? "/"}>
          {items[0].label}
        </BreadcrumbLink>
        <BreadcrumbSeparator />
      </Breadcrumb>
      {items.length > ITEMS_TO_DISPLAY ? (
        <Breadcrumb>
          {isDesktop ? (
            <MenuTrigger isOpen={open} onOpenChange={setOpen}>
              <Button
                variant="ghost"
                className="flex h-auto items-center gap-1 p-0 hover:bg-transparent"
                aria-label="Toggle menu"
              >
                <BreadcrumbEllipsis className="size-4" />
              </Button>
              <Menu placement="bottom start">
                {items.slice(1, -2).map((item, index) => (
                  <MenuItem key={index} href={item.href ? item.href : "#"}>
                    {item.label}
                  </MenuItem>
                ))}
              </Menu>
            </MenuTrigger>
          ) : (
            <Drawer open={open} onOpenChange={setOpen}>
              <DrawerTrigger aria-label="Toggle Menu">
                <BreadcrumbEllipsis className="h-4 w-4" />
              </DrawerTrigger>
              <DrawerContent>
                <DrawerHeader className="text-left">
                  <DrawerTitle>Navigate to</DrawerTitle>
                  <DrawerDescription>
                    Select a page to navigate to.
                  </DrawerDescription>
                </DrawerHeader>
                <div className="grid gap-1 px-4">
                  {items.slice(1, -2).map((item, index) => (
                    <a
                      key={index}
                      href={item.href ? item.href : "#"}
                      className="py-1 text-sm"
                    >
                      {item.label}
                    </a>
                  ))}
                </div>
                <DrawerFooter className="pt-4">
                  <DrawerClose asChild>
                    <Button variant="outline">Close</Button>
                  </DrawerClose>
                </DrawerFooter>
              </DrawerContent>
            </Drawer>
          )}
          <BreadcrumbSeparator />
        </Breadcrumb>
      ) : null}
      {items.slice(-ITEMS_TO_DISPLAY + 1).map((item, index) =>
        item.href ? (
          <Breadcrumb key={index}>
            <BreadcrumbLink
              href={item.href}
              className="max-w-20 truncate md:max-w-none"
            >
              {item.label}
            </BreadcrumbLink>
            <BreadcrumbSeparator />
          </Breadcrumb>
        ) : (
          <Breadcrumb key={index}>
            <BreadcrumbLink className="max-w-20 truncate md:max-w-none">
              {item.label}
            </BreadcrumbLink>
          </Breadcrumb>
        )
      )}
    </Breadcrumbs>
  )
}