Implement breadcrumbs

This commit is contained in:
2025-07-03 21:02:16 +02:00
parent 5dc9c77c25
commit 287ef67c37
2 changed files with 82 additions and 33 deletions

View File

@ -1,30 +1,75 @@
"use client";
"use client"
import { ChevronRight, HomeIcon } from "lucide-react";
import Link from "next/link";
import {
FolderIcon,
FolderOpenIcon,
HomeIcon,
ImageIcon,
InfoIcon,
LayersIcon,
TagIcon,
UserIcon,
} from "lucide-react"
import Link from "next/link"
import { usePathname } from "next/navigation"
import { Fragment, JSX } from "react"
export function Breadcrumbs({
items,
}: {
items: { name: string; href?: string }[];
}) {
return (
<nav className="flex items-center text-sm mb-4 text-muted-foreground">
<Link href="/" className="flex items-center gap-1 hover:text-foreground">
<HomeIcon size={16} />
</Link>
{items.map((item, idx) => (
<span key={idx} className="flex items-center">
<ChevronRight size={16} className="mx-1" />
{item.href ? (
<Link href={item.href} className="hover:text-foreground">
{item.name}
</Link>
) : (
<span className="text-foreground">{item.name}</span>
)}
</span>
))}
</nav>
);
const iconMap: Record<string, JSX.Element> = {
"about": <InfoIcon className="w-4 h-4" />,
"artists": <UserIcon className="w-4 h-4" />,
"categories": <LayersIcon className="w-4 h-4" />,
"tags": <TagIcon className="w-4 h-4" />,
"gallery": <FolderIcon className="w-4 h-4" />,
"album": <FolderOpenIcon className="w-4 h-4" />,
"image": <ImageIcon className="w-4 h-4" />,
}
export default function Breadcrumbs() {
const pathname = usePathname()
const rawSegments = pathname.split("/").filter(Boolean)
// If path is just "/", return nothing
if (rawSegments.length === 0) return null
// Special handling: remove "galleries" from breadcrumb trail
const segments = rawSegments.filter((seg, index) =>
!(seg === "galleries" && index === 0)
)
return (
<div className="text-sm px-1 text-muted-foreground flex items-center flex-wrap gap-1">
<Link href="/" className="inline-flex items-center gap-1 hover:underline font-medium text-foreground">
<HomeIcon className="w-4 h-4" />
Home
</Link>
{segments.length > 0 && <span>{">"}</span>}
{segments.map((seg, i) => {
const href = "/" + rawSegments.slice(0, rawSegments.indexOf(seg) + 1).join("/")
const isLast = i === segments.length - 1
const icon = iconMap[rawSegments[0]] || null
return (
<Fragment key={href}>
{i > 0 && <span>{">"}</span>}
{isLast ? (
<span className="inline-flex items-center gap-1 font-medium text-foreground">
{i === 0 && icon}
{decodeURIComponent(seg)}
</span>
) : (
<Link
href={href}
className="inline-flex items-center gap-1 hover:underline"
>
{i === 0 && icon}
{decodeURIComponent(seg)}
</Link>
)}
</Fragment>
)
})}
</div>
)
}

View File

@ -1,10 +1,12 @@
import AnimateToggle from "./AnimateToggle";
import Breadcrumbs from "./Breadcrumbs";
import ModeToggle from "./ModeToggle";
import NSFWToggle from "./NSFWToggle";
import TopNav from "./TopNav";
export default function Header() {
return (
<div className="flex flex-col gap-4">
<div className="flex items-center justify-between">
<TopNav />
<div className="flex gap-4">
@ -13,5 +15,7 @@ export default function Header() {
<ModeToggle />
</div>
</div>
<Breadcrumbs />
</div>
);
}