refactor(breadcrumbs): use handler & match pattern

This commit is contained in:
Nicolas Meienberger
2025-11-13 22:28:53 +01:00
parent 6d3d3c38f9
commit 6e6becec3b
14 changed files with 89 additions and 98 deletions

View File

@@ -1,4 +1,4 @@
import { Link } from "react-router";
import { Link, useMatches, type UIMatch } from "react-router";
import {
Breadcrumb,
BreadcrumbItem,
@@ -7,14 +7,38 @@ import {
BreadcrumbPage,
BreadcrumbSeparator,
} from "~/client/components/ui/breadcrumb";
import { useBreadcrumbs } from "~/client/lib/breadcrumbs";
export interface BreadcrumbItemData {
label: string;
href?: string;
}
interface RouteHandle {
breadcrumb?: (match: UIMatch) => BreadcrumbItemData[] | null;
}
export function AppBreadcrumb() {
const breadcrumbs = useBreadcrumbs();
const matches = useMatches();
// Find the last match with a breadcrumb handler
const lastMatchWithBreadcrumb = [...matches].reverse().find((match) => {
const handle = match.handle as RouteHandle | undefined;
return handle?.breadcrumb;
});
if (!lastMatchWithBreadcrumb) {
return null;
}
const handle = lastMatchWithBreadcrumb.handle as RouteHandle;
const breadcrumbs = handle.breadcrumb?.(lastMatchWithBreadcrumb);
if (!breadcrumbs || breadcrumbs.length === 0) {
return null;
}
return (
<Breadcrumb>
<BreadcrumbLink asChild></BreadcrumbLink>
<BreadcrumbList>
{breadcrumbs.map((breadcrumb, index) => {
const isLast = index === breadcrumbs.length - 1;
@@ -22,14 +46,12 @@ export function AppBreadcrumb() {
return (
<div key={`${breadcrumb.label}-${index}`} className="contents">
<BreadcrumbItem>
{isLast || breadcrumb.isCurrentPage ? (
{isLast || !breadcrumb.href ? (
<BreadcrumbPage>{breadcrumb.label}</BreadcrumbPage>
) : breadcrumb.href ? (
) : (
<BreadcrumbLink asChild>
<Link to={breadcrumb.href}>{breadcrumb.label}</Link>
</BreadcrumbLink>
) : (
<BreadcrumbPage>{breadcrumb.label}</BreadcrumbPage>
)}
</BreadcrumbItem>
{!isLast && <BreadcrumbSeparator />}