Navigation

Breadcrumbs

Compact navigation trail built on react-aria-components. Intermediate crumbs are muted brand-teal links; the current page is white and semibold, with a chevron or slash separator.

navigationbreadcrumbstraillinks

Default

Chevron-separated trail. The last crumb is the current page.

  1. Catalog
  2. Devices
  3. iPhone 15 Pro Max

Slash separator

Use separator="slash" for narrower trails or beside a page title.

  1. Plans/
  2. Flex 50/
  3. Pricing

With icon

A leading icon (data-slot="icon") inherits the crumb's color.

Two levels

A short trail with a single parent.

  1. Dashboard
  2. Billing

Source

Copy this into your project. Resolve its dependencies from the registryDependencies in the component's API entry.

"use client"

import { createContext, use } from "react"
import type { BreadcrumbProps, BreadcrumbsProps, LinkProps } from "react-aria-components"
import { Breadcrumb, Breadcrumbs as BreadcrumbsPrimitive } from "react-aria-components"
import { Link } from "@/components/link"
import { cn } from "@/lib/utils"

/**
 * Breadcrumbs — quebi design system
 *
 * Compact navigation trail. Intermediate crumbs render as brand-teal links
 * dimmed to text-quebi-fg-muted; the current crumb is text-white and
 * semibold. The separator glyph (chevron or slash) is subtle. Built on
 * react-aria-components for the accessibility baseline.
 */

type BreadcrumbsContextProps = { separator?: "chevron" | "slash" | boolean }
const BreadcrumbsProvider = createContext<BreadcrumbsContextProps>({
  separator: "chevron",
})

const Breadcrumbs = <T extends object>({
  className,
  ...props
}: BreadcrumbsProps<T> & BreadcrumbsContextProps) => {
  return (
    <BreadcrumbsProvider value={{ separator: props.separator }}>
      <BreadcrumbsPrimitive
        {...props}
        className={cn("flex items-center gap-2 font-sans text-sm", className)}
      />
    </BreadcrumbsProvider>
  )
}

interface BreadcrumbsItemProps extends BreadcrumbProps, BreadcrumbsContextProps {
  href?: string
}

const BreadcrumbsItem = ({
  href,
  separator = true,
  className,
  ...props
}: BreadcrumbsItemProps & Partial<Omit<LinkProps, "className">>) => {
  const { separator: contextSeparator } = use(BreadcrumbsProvider)
  separator = contextSeparator ?? separator
  const separatorValue = separator === true ? "chevron" : separator

  return (
    <Breadcrumb
      className={cn("flex items-center gap-2 text-quebi-fg-muted", className)}
      data-slot="breadcrumb-item"
      {...props}
    >
      {({ isCurrent }) => (
        <>
          <Link
            className={cn(
              "no-underline",
              "has-data-[slot=icon]:inline-flex has-data-[slot=icon]:items-center has-data-[slot=icon]:gap-x-2",
              "*:data-[slot=icon]:size-4",
              isCurrent
                ? "cursor-default font-semibold text-white hover:text-white hover:no-underline"
                : "font-normal text-quebi-fg-muted hover:text-white hover:no-underline *:data-[slot=icon]:text-quebi-fg-muted hover:*:data-[slot=icon]:text-white",
            )}
            href={href}
            {...props}
          />
          {!isCurrent && separator !== false && <Separator separator={separatorValue} />}
        </>
      )}
    </Breadcrumb>
  )
}

const ChevronRightIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 20 20"
    fill="currentColor"
    aria-hidden="true"
    data-slot="icon"
  >
    <path
      fillRule="evenodd"
      d="M7.21 14.77a.75.75 0 0 1 .02-1.06L11.168 10 7.23 6.29a.75.75 0 1 1 1.04-1.08l4.5 4.25a.75.75 0 0 1 0 1.08l-4.5 4.25a.75.75 0 0 1-1.06-.02Z"
      clipRule="evenodd"
    />
  </svg>
)

const Separator = ({
  separator = "chevron",
}: {
  separator?: BreadcrumbsItemProps["separator"]
}) => {
  return (
    <span className="*:shrink-0 *:text-quebi-fg-subtle *:data-[slot=icon]:size-3.5">
      {separator === "chevron" && <ChevronRightIcon />}
      {separator === "slash" && <span className="text-quebi-fg-subtle">/</span>}
    </span>
  )
}

Breadcrumbs.Item = BreadcrumbsItem

export type { BreadcrumbsItemProps, BreadcrumbsProps }
export { Breadcrumbs, BreadcrumbsItem }