Breadcrumb

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

Installation

Copy and paste the following code into your project.

import { Slot } from '@radix-ui/react-slot';
import clsx from 'clsx';
import { ChevronRight, MoreHorizontal } from 'lucide-react';
import { ComponentProps, ComponentPropsWithoutRef, ReactNode, forwardRef } from 'react';
import styles from './styles.module.scss';
 
const Breadcrumb = forwardRef<
    HTMLElement,
    ComponentPropsWithoutRef<'nav'> & {
        separator?: ReactNode;
    }
>(({ ...props }, ref) => <nav ref={ref} aria-label='breadcrumb' {...props} />);
Breadcrumb.displayName = 'Breadcrumb';
 
const BreadcrumbList = forwardRef<HTMLOListElement, ComponentPropsWithoutRef<'ol'>>(({ className, ...props }, ref) => (
    <ol ref={ref} className={clsx(styles.breadcrumb__list, className)} {...props} />
));
BreadcrumbList.displayName = 'BreadcrumbList';
 
const BreadcrumbItem = forwardRef<HTMLLIElement, ComponentPropsWithoutRef<'li'>>(({ className, ...props }, ref) => (
    <li ref={ref} className={clsx(styles.breadcrumb__item, className)} {...props} />
));
BreadcrumbItem.displayName = 'BreadcrumbItem';
 
const BreadcrumbLink = forwardRef<
    HTMLAnchorElement,
    ComponentPropsWithoutRef<'a'> & {
        asChild?: boolean;
    }
>(({ asChild, className, ...props }, ref) => {
    const Comp = asChild ? Slot : 'a';
 
    return <Comp ref={ref} className={clsx(styles.breadcrumb__link, className)} {...props} />;
});
BreadcrumbLink.displayName = 'BreadcrumbLink';
 
const BreadcrumbPage = forwardRef<HTMLSpanElement, ComponentPropsWithoutRef<'span'>>(({ className, ...props }, ref) => (
    <span
        ref={ref}
        role='link'
        aria-disabled='true'
        aria-current='page'
        className={clsx(styles.breadcrumb__page, className)}
        {...props}
    />
));
BreadcrumbPage.displayName = 'BreadcrumbPage';
 
const BreadcrumbSeparator = ({ children, className, ...props }: ComponentProps<'span'>) => (
    <span role='presentation' aria-hidden='true' className={clsx(styles.breadcrumb__separator, className)} {...props}>
        {children ?? <ChevronRight />}
    </span>
);
BreadcrumbSeparator.displayName = 'BreadcrumbSeparator';
 
const BreadcrumbEllipsis = ({ className, ...props }: ComponentProps<'span'>) => (
    <span role='presentation' aria-hidden='true' className={clsx(styles.breadcrumb__ellipsis, className)} {...props}>
        <MoreHorizontal className={styles.breadcrumb__ellipsis__icon} />
        <span className={styles.sr_only}>More</span>
    </span>
);
BreadcrumbEllipsis.displayName = 'BreadcrumbElipssis';
 
export {
    Breadcrumb,
    BreadcrumbEllipsis,
    BreadcrumbItem,
    BreadcrumbLink,
    BreadcrumbList,
    BreadcrumbPage,
    BreadcrumbSeparator,
};

Update the import paths to match your project setup.

Usage

import {
    Breadcrumb,
    BreadcrumbItem,
    BreadcrumbLink,
    BreadcrumbList,
    BreadcrumbPage,
    BreadcrumbSeparator,
} from '@/components/ui/breadcrumb';
<Breadcrumb>
    <BreadcrumbList>
        <BreadcrumbItem>
            <BreadcrumbLink href='/'>Home</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
            <BreadcrumbLink href='/components'>Components</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
            <BreadcrumbPage>Breadcrumb</BreadcrumbPage>
        </BreadcrumbItem>
    </BreadcrumbList>
</Breadcrumb>

Examples

Custom separator

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

import { Slash } from "lucide-react"
 
...
 
<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink href="/">Home</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator>
      <Slash />
    </BreadcrumbSeparator>
    <BreadcrumbItem>
      <BreadcrumbLink href="/components">Components</BreadcrumbLink>
    </BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>

You can compose <BreadcrumbItem /> with a <DropdownMenu /> to create a dropdown in the breadcrumb.

import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
 
...
 
<BreadcrumbItem>
  <DropdownMenu>
    <DropdownMenuTrigger className="flex items-center gap-1">
      Components
      <ChevronDownIcon />
    </DropdownMenuTrigger>
    <DropdownMenuContent align="start">
      <DropdownMenuItem>Documentation</DropdownMenuItem>
      <DropdownMenuItem>Themes</DropdownMenuItem>
      <DropdownMenuItem>GitHub</DropdownMenuItem>
    </DropdownMenuContent>
  </DropdownMenu>
</BreadcrumbItem>

Collapsed

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

import { BreadcrumbEllipsis } from "@/components/ui/breadcrumb"
 
...
 
<Breadcrumb>
  <BreadcrumbList>
    {/* ... */}
    <BreadcrumbItem>
      <BreadcrumbEllipsis />
    </BreadcrumbItem>
    {/* ... */}
  </BreadcrumbList>
</Breadcrumb>

To use a custom link component from your routing library, you can use the asChild prop on <BreadcrumbLink />.

import { Link } from "next/link"
 
...
 
<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink asChild>
        <Link href="/">Home</Link>
      </BreadcrumbLink>
    </BreadcrumbItem>
    {/* ... */}
  </BreadcrumbList>
</Breadcrumb>

Responsive

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

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