Merge pull request #912 from gsxdsm/feat/plugin-breadcumb-slot

Add global toolbar slots to BreadcrumbBar component
This commit is contained in:
Dotta
2026-03-14 16:28:56 -05:00
committed by GitHub

View File

@@ -2,6 +2,7 @@ import { Link } from "@/lib/router";
import { Menu } from "lucide-react";
import { useBreadcrumbs } from "../context/BreadcrumbContext";
import { useSidebar } from "../context/SidebarContext";
import { useCompany } from "../context/CompanyContext";
import { Button } from "@/components/ui/button";
import {
Breadcrumb,
@@ -11,13 +12,37 @@ import {
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { Fragment } from "react";
import { Fragment, useMemo } from "react";
import { PluginSlotOutlet } from "@/plugins/slots";
export function BreadcrumbBar() {
const { breadcrumbs } = useBreadcrumbs();
const { toggleSidebar, isMobile } = useSidebar();
const { selectedCompanyId, selectedCompany } = useCompany();
if (breadcrumbs.length === 0) return null;
const globalToolbarSlotContext = useMemo(
() => ({
companyId: selectedCompanyId ?? null,
companyPrefix: selectedCompany?.issuePrefix ?? null,
}),
[selectedCompanyId, selectedCompany?.issuePrefix],
);
const globalToolbarSlots = (
<PluginSlotOutlet
slotTypes={["toolbarButton"]}
context={globalToolbarSlotContext}
className="flex items-center gap-1 ml-auto shrink-0 pl-2"
/>
);
if (breadcrumbs.length === 0) {
return (
<div className="border-b border-border px-4 md:px-6 h-12 shrink-0 flex items-center justify-end">
{globalToolbarSlots}
</div>
);
}
const menuButton = isMobile && (
<Button
@@ -34,40 +59,46 @@ export function BreadcrumbBar() {
// Single breadcrumb = page title (uppercase)
if (breadcrumbs.length === 1) {
return (
<div className="border-b border-border px-4 md:px-6 h-12 shrink-0 flex items-center min-w-0 overflow-hidden">
<div className="border-b border-border px-4 md:px-6 h-12 shrink-0 flex items-center">
{menuButton}
<h1 className="text-sm font-semibold uppercase tracking-wider truncate">
{breadcrumbs[0].label}
</h1>
<div className="min-w-0 overflow-hidden flex-1">
<h1 className="text-sm font-semibold uppercase tracking-wider truncate">
{breadcrumbs[0].label}
</h1>
</div>
{globalToolbarSlots}
</div>
);
}
// Multiple breadcrumbs = breadcrumb trail
return (
<div className="border-b border-border px-4 md:px-6 h-12 shrink-0 flex items-center min-w-0 overflow-hidden">
<div className="border-b border-border px-4 md:px-6 h-12 shrink-0 flex items-center">
{menuButton}
<Breadcrumb className="min-w-0 overflow-hidden">
<BreadcrumbList className="flex-nowrap">
{breadcrumbs.map((crumb, i) => {
const isLast = i === breadcrumbs.length - 1;
return (
<Fragment key={i}>
{i > 0 && <BreadcrumbSeparator />}
<BreadcrumbItem className={isLast ? "min-w-0" : "shrink-0"}>
{isLast || !crumb.href ? (
<BreadcrumbPage className="truncate">{crumb.label}</BreadcrumbPage>
) : (
<BreadcrumbLink asChild>
<Link to={crumb.href}>{crumb.label}</Link>
</BreadcrumbLink>
)}
</BreadcrumbItem>
</Fragment>
);
})}
</BreadcrumbList>
</Breadcrumb>
<div className="min-w-0 overflow-hidden flex-1">
<Breadcrumb className="min-w-0 overflow-hidden">
<BreadcrumbList className="flex-nowrap">
{breadcrumbs.map((crumb, i) => {
const isLast = i === breadcrumbs.length - 1;
return (
<Fragment key={i}>
{i > 0 && <BreadcrumbSeparator />}
<BreadcrumbItem className={isLast ? "min-w-0" : "shrink-0"}>
{isLast || !crumb.href ? (
<BreadcrumbPage className="truncate">{crumb.label}</BreadcrumbPage>
) : (
<BreadcrumbLink asChild>
<Link to={crumb.href}>{crumb.label}</Link>
</BreadcrumbLink>
)}
</BreadcrumbItem>
</Fragment>
);
})}
</BreadcrumbList>
</Breadcrumb>
</div>
{globalToolbarSlots}
</div>
);
}