Breadcrumbs
The trail above a detail page: where the record lives, and the record itself.
import { BreadcrumbItem, Breadcrumbs } from '@/components/breadcrumbs'
export default function Example() {
return (
<Breadcrumbs>
<BreadcrumbItem href="/customers">Customers</BreadcrumbItem>
<BreadcrumbItem>Mariam Keita</BreadcrumbItem>
</Breadcrumbs>
)
}<script setup lang="ts">
import BreadcrumbItem from '@/components/breadcrumb-item.vue'
import Breadcrumbs from '@/components/breadcrumbs.vue'
</script>
<template>
<Breadcrumbs>
<BreadcrumbItem href="/customers">Customers</BreadcrumbItem>
<BreadcrumbItem>Mariam Keita</BreadcrumbItem>
</Breadcrumbs>
</template>Installation
Copy these files into the folder where you keep your components. They import each other with relative paths, so the folder can live anywhere. The packages they rely on are listed on the Installation page.
import { ChevronRightIcon } from '@heroicons/react/16/solid'
import clsx from 'clsx'
import type React from 'react'
import { Link } from './link'
export function Breadcrumbs({ className, children, ...props }: React.ComponentPropsWithoutRef<'nav'>) {
return (
<nav aria-label="Breadcrumb" {...props} className={className}>
<ol role="list" className="flex items-center gap-1.5">
{children}
</ol>
</nav>
)
}
export function BreadcrumbItem({
href,
className,
children,
...props
}: {
href?: string
} & Omit<React.ComponentPropsWithoutRef<'li'>, 'children'> & { children: React.ReactNode }) {
return (
<li {...props} className={clsx(className, 'flex min-w-0 items-center gap-1.5')}>
<ChevronRightIcon className="size-3.5 shrink-0 fill-zinc-400 [li:first-child>&]:hidden dark:fill-zinc-500" />
{href ? (
<Link
href={href}
className="truncate text-base/6 font-medium text-zinc-500 hover:text-zinc-950 sm:text-sm/6 dark:text-zinc-400 dark:hover:text-white"
>
{children}
</Link>
) : (
<span aria-current="page" className="truncate text-base/6 text-zinc-950 sm:text-sm/6 dark:text-white">
{children}
</span>
)}
</li>
)
}<script setup lang="ts">
</script>
<template>
<nav aria-label="Breadcrumb">
<ol role="list" class="flex items-center gap-1.5">
<slot />
</ol>
</nav>
</template>Component API
| Prop | Default | Description |
|---|---|---|
Breadcrumbsrenders a <nav> element | ||
| This component does not expose any component-specific props. | ||
BreadcrumbItemrenders a <li> element | ||
href | - | Links the item, in grey, darkening on hover. Leave it out on the last item: it is the current page, in the text color, marked `aria-current`. |
| Prop | Default | Description |
|---|---|---|
Breadcrumbsrenders a <nav> element | ||
| This component does not expose any component-specific props. | ||
BreadcrumbItemrenders a <li> element | ||
href | - | Links the item, in grey, darkening on hover. Leave it out on the last item: it is the current page, in the text color, marked `aria-current`. |
Examples
Basic example
Parents take an href, the last item does not. The separator draws itself between items:
import { BreadcrumbItem, Breadcrumbs } from '@/components/breadcrumbs'
export default function Example() {
return (
<Breadcrumbs>
<BreadcrumbItem href="/customers">Customers</BreadcrumbItem>
<BreadcrumbItem>Mariam Keita</BreadcrumbItem>
</Breadcrumbs>
)
}<script setup lang="ts">
import BreadcrumbItem from '@/components/breadcrumb-item.vue'
import Breadcrumbs from '@/components/breadcrumbs.vue'
</script>
<template>
<Breadcrumbs>
<BreadcrumbItem href="/customers">Customers</BreadcrumbItem>
<BreadcrumbItem>Mariam Keita</BreadcrumbItem>
</Breadcrumbs>
</template>Above a heading
The trail carries no margin of its own. Put mt-4 on the heading or the header that follows it:
Plans
<Breadcrumbs>
<BreadcrumbItem href="/settings">Settings</BreadcrumbItem>
<BreadcrumbItem href="/settings/billing">Billing</BreadcrumbItem>
</Breadcrumbs>
<Heading className="mt-4">Plans</Heading><template>
<Breadcrumbs>
<BreadcrumbItem href="/settings">Settings</BreadcrumbItem>
<BreadcrumbItem href="/settings/billing">Billing</BreadcrumbItem>
</Breadcrumbs>
<Heading class="mt-4">Plans</Heading>
</template>Identifiers
An identifier as the last item reads better in monospace:
<Breadcrumbs>
<BreadcrumbItem href="/payments">Payments</BreadcrumbItem>
<BreadcrumbItem className="font-mono">pay_W49414L4SATP</BreadcrumbItem>
</Breadcrumbs><template>
<Breadcrumbs>
<BreadcrumbItem href="/payments">Payments</BreadcrumbItem>
<BreadcrumbItem class="font-mono">pay_W49414L4SATP</BreadcrumbItem>
</Breadcrumbs>
</template>Long names
Items truncate rather than wrap, so a long customer name never pushes the trail to two lines:
<div className="w-64">
<Breadcrumbs>
<BreadcrumbItem href="/customers">Customers</BreadcrumbItem>
<BreadcrumbItem>Alexandra Konstantinopoulou-Whitfield</BreadcrumbItem>
</Breadcrumbs>
</div><template>
<div class="w-64">
<Breadcrumbs>
<BreadcrumbItem href="/customers">Customers</BreadcrumbItem>
<BreadcrumbItem>Alexandra Konstantinopoulou-Whitfield</BreadcrumbItem>
</Breadcrumbs>
</div>
</template>