Displays the path to the current resource using a hierarchy of links.
Installation
npx shadcn@latest add @caprice/breadcrumbpnpm dlx shadcn@latest add @caprice/breadcrumbyarn dlx shadcn@latest add @caprice/breadcrumbbunx shadcn@latest add @caprice/breadcrumbnpm install @caprice-ui/reactpnpm add @caprice-ui/reactyarn add @caprice-ui/reactbun add @caprice-ui/reactInstall the following dependencies:
npm install @base-ui/react lucide-reactpnpm add @base-ui/react lucide-reactyarn add @base-ui/react lucide-reactbun add @base-ui/react lucide-reactAdd a cn helper
import { defineConfig, getSchema, type VariantProps } from 'cva';
import { twMerge } from 'tailwind-merge';
export const { cva, cx: cn } = defineConfig({
hooks: {
onComplete: (className: string) => twMerge(className),
},
});
export type { VariantProps };
export { getSchema };
Copy and paste the following code into your project.
import { mergeProps, useRender } from '@base-ui/react';
import { ChevronRight, MoreHorizontal } from 'lucide-react';
import { cn } from '@/lib/utils';
/**
* A navigation component that displays the user's current location in the site hierarchy.
* Renders a `<nav>` element.
*
* Documentation: [Caprice UI Breadcrumb](https://caprice-ui.com/docs/components/breadcrumb)
*/
export namespace Root {
export type Props = useRender.ComponentProps<'nav'>;
}
export function Root({ className, render, ...props }: Root.Props) {
const defaultProps: useRender.ElementProps<'nav'> & { 'data-slot'?: string } = {
'data-slot': 'breadcrumb',
'aria-label': 'breadcrumb',
className: cn(className),
};
return useRender({
defaultTagName: 'nav',
render,
props: mergeProps<'nav'>(defaultProps, props),
});
}
/**
* An ordered list that contains the breadcrumb items.
* Renders an `<ol>` element.
*
* Documentation: [Caprice UI Breadcrumb](https://caprice-ui.com/docs/components/breadcrumb)
*/
export namespace List {
export type Props = useRender.ComponentProps<'ol'>;
}
export function List({ className, render, ...props }: List.Props) {
const defaultProps: useRender.ElementProps<'ol'> & { 'data-slot'?: string } = {
'data-slot': 'breadcrumb-list',
className: cn(
'wrap-break-word flex flex-wrap items-center gap-1.5 text-muted-foreground text-sm sm:gap-2.5',
className
),
};
return useRender({
defaultTagName: 'ol',
render,
props: mergeProps<'ol'>(defaultProps, props),
});
}
/**
* A list item that contains a link or page indicator.
* Renders an `<li>` element.
*
* Documentation: [Caprice UI Breadcrumb](https://caprice-ui.com/docs/components/breadcrumb)
*/
export namespace Item {
export type Props = useRender.ComponentProps<'li'>;
}
export function Item({ className, render, ...props }: Item.Props) {
const defaultProps: useRender.ElementProps<'li'> & { 'data-slot'?: string } = {
'data-slot': 'breadcrumb-item',
className: cn('inline-flex items-center gap-1.5', className),
};
return useRender({
defaultTagName: 'li',
render,
props: mergeProps<'li'>(defaultProps, props),
});
}
/**
* A navigational link within the breadcrumb trail.
* Renders an `<a>` element.
*
* Documentation: [Caprice UI Breadcrumb](https://caprice-ui.com/docs/components/breadcrumb)
*/
export namespace Link {
export type Props = useRender.ComponentProps<'a'>;
}
export function Link({ className, render, ...props }: Link.Props) {
const defaultProps: useRender.ElementProps<'a'> & { 'data-slot'?: string } = {
'data-slot': 'breadcrumb-link',
className: cn('transition-colors hover:text-foreground', className),
};
return useRender({
defaultTagName: 'a',
render,
props: mergeProps<'a'>(defaultProps, props),
});
}
/**
* Indicates the current page in the breadcrumb trail.
* Renders a `<span>` element.
*
* Documentation: [Caprice UI Breadcrumb](https://caprice-ui.com/docs/components/breadcrumb)
*/
export namespace Page {
export type Props = useRender.ComponentProps<'span'>;
}
export function Page({ className, render, ...props }: Page.Props) {
const defaultProps: useRender.ElementProps<'span'> & { 'data-slot'?: string } = {
'data-slot': 'breadcrumb-page',
role: 'link',
'aria-current': 'page',
'aria-disabled': true,
className: cn('font-normal text-foreground', className),
};
return useRender({
defaultTagName: 'span',
render,
props: mergeProps<'span'>(defaultProps, props),
});
}
/**
* A visual separator between breadcrumb items.
* Renders an `<li>` element.
*
* Documentation: [Caprice UI Breadcrumb](https://caprice-ui.com/docs/components/breadcrumb)
*/
export namespace Separator {
export type Props = useRender.ComponentProps<'li'>;
}
export function Separator({
children = <ChevronRight />,
className,
render,
...props
}: Separator.Props) {
const defaultProps: useRender.ElementProps<'li'> & { 'data-slot'?: string } = {
'data-slot': 'breadcrumb-separator',
role: 'presentation',
'aria-hidden': true,
className: cn('[&>svg]:size-3.5', className),
};
return useRender({
defaultTagName: 'li',
render,
props: mergeProps<'li'>(defaultProps, props),
});
}
/**
* An indicator for collapsed breadcrumb items when the trail is too long.
* Renders a `<span>` element.
*
* Documentation: [Caprice UI Breadcrumb](https://caprice-ui.com/docs/components/breadcrumb)
*/
export namespace Ellipsis {
export type Props = useRender.ComponentProps<'span'>;
}
export function Ellipsis({ className, render, ...props }: Ellipsis.Props) {
const defaultProps: useRender.ElementProps<'span'> & { 'data-slot'?: string } = {
'data-slot': 'breadcrumb-ellipsis',
role: 'presentation',
'aria-hidden': true,
children: (
<>
<MoreHorizontal className="size-4" />
<span className="sr-only">More</span>
</>
),
className: cn('flex size-9 items-center justify-center', className),
};
return useRender({
defaultTagName: 'span',
render,
props: mergeProps<'span'>(defaultProps, props),
});
}
Update the import paths to match your project setup.
Usage
import * as Breadcrumb from "@/components/caprice-ui/breadcrumb"import * as Breadcrumb from "@caprice-ui/react/breadcrumb"Examples
Differences with shadcn/ui
If you're familiar with shadcn/ui, most patterns will carry over. This guide points out the differences so you can start using Caprice UI without surprises.
Key changes
| Feature | shadcn/ui | Caprice UI |
|---|---|---|
| Component API | Flat exports (BreadcrumbLink) | Namespace exports (Breadcrumb.Link) |
| Composition | asChild prop (Link only) | render prop (all components) |
| Primitive | Native HTML + Radix Slot | Base UI useRender |
| Props type | React.ComponentProps<'element'> | useRender.ComponentProps<'element'> |
Comparison Example
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/">Home</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Current</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>import * as Breadcrumb from '@/components/caprice-ui/breadcrumb'
<Breadcrumb.Root>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link render={<Link href="/" />}>Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Page>Current</Breadcrumb.Page>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>Accessibility
This component follows the WAI-ARIA Breadcrumb Pattern:
- The breadcrumb trail is contained within a navigation landmark region (
<nav>). - The landmark region is labelled via
aria-label="breadcrumb". - The current page is marked with
aria-current="page"to indicate it's not a navigable link. - Separators use
role="presentation"andaria-hidden="true"to hide them from assistive technologies. - The ellipsis includes a visually hidden "More" label for screen readers.
Last updated on