<nav aria-label="Breadcrumb" class="flex items-center space-x-2 text-xs text-muted-foreground">
<a href="#" class="hover:text-foreground transition-colors flex items-center gap-1">
<svg class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>
<span>Home</span>
</a>
<span class="text-muted-foreground/50">/</span>
<a href="#" class="hover:text-foreground transition-colors">Components</a>
<span class="text-muted-foreground/50">/</span>
<span class="font-semibold text-foreground" aria-current="page">Breadcrumb</span>
</nav>
import React from "react";
export function Breadcrumb({ items = [{ label: "Home", href: "/" }, { label: "Docs", href: "/docs" }, { label: "Components" }] }: { items?: { label: string; href?: string }[] }) {
return (
<nav aria-label="Breadcrumb" className="flex items-center space-x-2 text-xs text-muted-foreground">
{items.map((item, idx) => (
<React.Fragment key={idx}>
{idx > 0 && <span>/</span>}
{item.href ? (
<a href={item.href} className="hover:text-foreground transition-colors">{item.label}</a>
) : (
<span className="font-semibold text-foreground" aria-current="page">{item.label}</span>
)}
</React.Fragment>
))}
</nav>
);
}
"use client";
import React from "react";
export interface BreadcrumbItem {
label: string;
href?: string;
}
const defaultItems: BreadcrumbItem[] = [
{ label: "Home", href: "/" },
{ label: "Design System", href: "/docs" },
{ label: "Navigation", href: "/components" },
{ label: "Breadcrumb" },
];
export interface BreadcrumbProps {
items?: BreadcrumbItem[];
separator?: "slash" | "chevron";
}
export default function Breadcrumb({
items = defaultItems,
separator = "chevron",
}: BreadcrumbProps) {
return (
<nav aria-label="Breadcrumbs" className="w-full max-w-md p-3.5 rounded-xl border border-border bg-card shadow-2xs">
<ol className="flex items-center space-x-1.5 sm:space-x-2 text-xs">
{items.map((item, idx) => {
const isLast = idx === items.length - 1;
return (
<li key={idx} className="flex items-center space-x-1.5 sm:space-x-2">
{idx > 0 && (
<span className="text-muted-foreground/50 select-none">
{separator === "chevron" ? (
<svg className="h-3 w-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<polyline points="9 18 15 12 9 6" />
</svg>
) : (
"/"
)}
</span>
)}
{isLast ? (
<span
aria-current="page"
className="font-semibold text-foreground truncate max-w-[140px]"
>
{item.label}
</span>
) : (
<a
href={item.href || "#"}
className="text-muted-foreground hover:text-foreground transition-colors font-medium truncate max-w-[120px]"
>
{item.label}
</a>
)}
</li>
);
})}
</ol>
</nav>
);
}
"use client";
import React from "react";
import { motion } from "framer-motion";
import { ChevronRight, Home } from "lucide-react";
const pathSteps = [
{ label: "Overview", icon: Home },
{ label: "Settings" },
{ label: "Billing & Plans" },
];
export default function AnimatedBreadcrumb() {
return (
<nav aria-label="Breadcrumb" className="p-4 rounded-2xl border border-border bg-card/70 backdrop-blur-md shadow-xs">
<ol className="flex items-center gap-2 text-xs">
{pathSteps.map((step, idx) => {
const isLast = idx === pathSteps.length - 1;
const Icon = step.icon;
return (
<React.Fragment key={idx}>
{idx > 0 && (
<ChevronRight className="h-3 w-3 text-muted-foreground/60 shrink-0" />
)}
<motion.li
whileHover={!isLast ? { y: -1 } : {}}
className={`flex items-center gap-1.5 ${
isLast
? "font-bold text-foreground"
: "text-muted-foreground hover:text-foreground cursor-pointer transition-colors"
}`}
>
{Icon && <Icon className="h-3.5 w-3.5" />}
<span>{step.label}</span>
</motion.li>
</React.Fragment>
);
})}
</ol>
</nav>
);
}