105 lines
2.6 KiB
TypeScript
105 lines
2.6 KiB
TypeScript
import Link from "next/link"
|
|
import { ChevronRight, Home } from "lucide-react"
|
|
import { businessConfig } from "@/lib/seo-config"
|
|
|
|
export interface BreadcrumbItem {
|
|
label: string
|
|
href?: string | null
|
|
}
|
|
|
|
interface BreadcrumbsProps {
|
|
items: BreadcrumbItem[]
|
|
className?: string
|
|
}
|
|
|
|
/**
|
|
* Breadcrumb Navigation Component
|
|
* Implements BreadcrumbList schema markup for SEO and navigation clarity
|
|
* Helps search engines understand page hierarchy
|
|
*/
|
|
export function Breadcrumbs({ items, className = "" }: BreadcrumbsProps) {
|
|
// Build breadcrumb list for schema
|
|
const schemaItems = items.reduce<
|
|
Array<{
|
|
"@type": "ListItem"
|
|
position: number
|
|
name: string
|
|
item?: string
|
|
}>
|
|
>((acc, item, index) => {
|
|
const isLast = index === items.length - 1
|
|
|
|
if (!item.href && !isLast) {
|
|
return acc
|
|
}
|
|
|
|
acc.push({
|
|
"@type": "ListItem",
|
|
position: acc.length + 2,
|
|
name: item.label,
|
|
...(item.href
|
|
? {
|
|
item: item.href.startsWith("http")
|
|
? item.href
|
|
: `${businessConfig.website}${item.href}`,
|
|
}
|
|
: {}),
|
|
})
|
|
|
|
return acc
|
|
}, [])
|
|
|
|
const breadcrumbList = {
|
|
"@context": "https://schema.org",
|
|
"@type": "BreadcrumbList",
|
|
itemListElement: [
|
|
{
|
|
"@type": "ListItem",
|
|
position: 1,
|
|
name: "Home",
|
|
item: businessConfig.website,
|
|
},
|
|
...schemaItems,
|
|
],
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbList) }}
|
|
/>
|
|
<nav
|
|
className={`flex items-center gap-2 text-sm text-muted-foreground ${className}`}
|
|
aria-label="Breadcrumb"
|
|
>
|
|
<Link
|
|
href="/"
|
|
className="hover:text-foreground transition-colors flex items-center gap-1"
|
|
aria-label="Home"
|
|
>
|
|
<Home className="h-4 w-4" />
|
|
</Link>
|
|
{items.map((item, index) => (
|
|
<div key={index} className="flex items-center gap-2">
|
|
<ChevronRight className="h-4 w-4" />
|
|
{index === items.length - 1 ? (
|
|
<span className="text-foreground font-medium" aria-current="page">
|
|
{item.label}
|
|
</span>
|
|
) : !item.href ? (
|
|
<span className="text-foreground font-medium">{item.label}</span>
|
|
) : (
|
|
<Link
|
|
href={item.href}
|
|
className="hover:text-foreground transition-colors"
|
|
>
|
|
{item.label}
|
|
</Link>
|
|
)}
|
|
</div>
|
|
))}
|
|
</nav>
|
|
</>
|
|
)
|
|
}
|