Breadcrumbs
Breadcrumbs are used to display the current page's location within a hierarchy and enable easy navigation.
Installation
Add the following Soul components
The breadcrumbs component uses the streamable, skeleton and animated-underline components. Make sure you have added them to your project.
Install the following dependencies
npm install clsx lucide-react
Copy and paste the following code into your project
sections/breadcrumbs/index.tsx
import { clsx } from 'clsx';import { ChevronRight } from 'lucide-react';import Link from 'next/link';import { Stream, Streamable } from '@/vibes/soul/lib/streamable';import { AnimatedUnderline } from '@/vibes/soul/primitives/animated-underline';import * as Skeleton from '@/vibes/soul/primitives/skeleton';export interface Breadcrumb { label: string; href: string;}export interface BreadcrumbsProps { breadcrumbs: Streamable<Breadcrumb[]>; className?: string;}/** * This component supports various CSS variables for theming. Here's a comprehensive list, along * with their default values: * * ```css * :root { * --breadcrumbs-font-family: var(--font-family-body); * --breadcrumbs-primary-text: var(--foreground); * --breadcrumbs-secondary-text: var(--contrast-500); * --breadcrumbs-icon: var(--contrast-500); * --breadcrumbs-hover: var(--primary); * } * ``` */export function Breadcrumbs({ breadcrumbs: streamableBreadcrumbs, className }: BreadcrumbsProps) { return ( <Stream fallback={<BreadcrumbsSkeleton className={className} />} value={streamableBreadcrumbs}> {(breadcrumbs) => { if (breadcrumbs.length === 0) { return <BreadCrumbEmptyState className={className} />; } return ( <nav aria-label="breadcrumb" className={clsx(className)}> <ol className="flex flex-wrap items-center gap-x-1.5 text-sm @xl:text-base"> {breadcrumbs.map(({ label, href }, index) => { if (index < breadcrumbs.length - 1) { return ( <li className="inline-flex items-center gap-x-1.5" key={href}> <Link className="group/underline focus:outline-hidden" href={href}> <AnimatedUnderline className="font-[family-name:var(--breadcrumbs-font-family,var(--font-family-body))] text-(--breadcrumbs-primary-text,var(--foreground)) [background:linear-gradient(0deg,var(--breadcrumbs-hover,var(--primary)),var(--breadcrumbs-hover,var(--primary)))_no-repeat_left_bottom_/_0_2px]"> {label} </AnimatedUnderline> </Link> <ChevronRight aria-hidden="true" className="text-(--breadcrumbs-icon,var(--contrast-500))" size={20} strokeWidth={1} /> </li> ); } return ( <li className="inline-flex items-center font-[family-name:var(--breadcrumbs-font-family,var(--font-family-body))] text-(--breadcrumbs-secondary-text,var(--contrast-500))" key={href} > <span aria-current="page" aria-disabled="true" role="link"> {label} </span> </li> ); })} </ol> </nav> ); }} </Stream> );}export function BreadcrumbsSkeleton({ className }: Pick<BreadcrumbsProps, 'className'>) { return ( <Skeleton.Root className={clsx('group-has-[[data-pending]]/breadcrumbs:animate-pulse', className)} pending > <div className="flex flex-wrap items-center gap-x-1.5 text-sm @xl:text-base"> <Skeleton.Text characterCount={4} className="rounded-sm text-lg" /> <Skeleton.Icon icon={<ChevronRight aria-hidden className="h-5 w-5" strokeWidth={1} />} /> <Skeleton.Text characterCount={6} className="rounded-sm text-lg" /> <Skeleton.Icon icon={<ChevronRight aria-hidden className="h-5 w-5" strokeWidth={1} />} /> <Skeleton.Text characterCount={6} className="rounded-sm text-lg" /> </div> </Skeleton.Root> );}export function BreadCrumbEmptyState({ className }: Pick<BreadcrumbsProps, 'className'>) { return ( <Skeleton.Root className={className}> <div className={clsx('min-h-[1lh]', className)} /> </Skeleton.Root> );}
Usage
import { Breadcrumbs, type Breadcrumb } from '@/vibes/soul/sections/breadcrumbs';function Usage() { const breadcrumbs: Breadcrumb[] = [ { label: 'Home', href: '#1', }, { label: 'Bags', href: '#2', }, { label: 'Handle Bags', href: '#3', }, ]; return ( <Breadcrumbs breadcrumbs={breadcrumbs} /> );}
API Reference
BreadcrumbsProps
Prop | Type | Default |
---|---|---|
breadcrumbs* | ||
className | string |
Breadcrumb
Prop | Type | Default |
---|---|---|
label | string | |
href | string |
CSS Variables
This component supports various CSS variables for theming. Here's a comprehensive list.
:root { --breadcrumbs-font-family: var(--font-family-body); --breadcrumbs-primary-text: var(--foreground); --breadcrumbs-secondary-text: var(--contrast-500); --breadcrumbs-icon: var(--contrast-500); --breadcrumbs-hover: var(--primary);}