68c94dfa3a
* docs: define product and design direction * style: establish restrained workbench primitives * refactor: declutter board and task topbars * style: align dockview panel chrome * fix: align task topbar vcs control sizing * refactor: surface integrations navigation * fix: repair integrations and task creation workflow * refactor: include linear in integrations navigation * style: restore familiar workbench tones * fix: add dockview tab breathing room * fix: show configured integration shortcuts * fix: hover open integrations menu * fix: stabilize integrations hover menu * fix: align home and dockview topbars * fix: normalize home topbar controls * fix: compact home topbar height * fix: simplify home chrome and split buttons * fix: move integrations to left chrome * fix: restore home stats shortcut * fix: add dockview tab breathing room * fix: border home stats button * fix: streamline dockview topbar actions * fix: align task split button seam * fix: address review feedback * fix: restore topbar e2e affordances * fix: stabilize workflow e2e isolation * fix: add task topbar action overflow * fix: address PR review feedback
122 lines
3.7 KiB
TypeScript
122 lines
3.7 KiB
TypeScript
import Link from "next/link";
|
|
import { forwardRef } from "react";
|
|
import type { ReactNode } from "react";
|
|
import { IconArrowLeft } from "@tabler/icons-react";
|
|
import {
|
|
Breadcrumb,
|
|
BreadcrumbItem,
|
|
BreadcrumbLink,
|
|
BreadcrumbList,
|
|
BreadcrumbPage,
|
|
BreadcrumbSeparator,
|
|
} from "@kandev/ui/breadcrumb";
|
|
import { cn } from "@kandev/ui/lib/utils";
|
|
|
|
type PageTopbarProps = {
|
|
/** Page title shown in the breadcrumb */
|
|
title: string;
|
|
/** Optional subtitle shown to the right of the title */
|
|
subtitle?: string;
|
|
/** Optional icon rendered before the title */
|
|
icon?: ReactNode;
|
|
/** Where the back link navigates to (default: "/") */
|
|
backHref?: string;
|
|
/** Label for the parent breadcrumb (default: "KanDev") */
|
|
backLabel?: string;
|
|
/** Optional content rendered before the breadcrumb */
|
|
leading?: ReactNode;
|
|
/** Optional content rendered at the visual center of the topbar */
|
|
center?: ReactNode;
|
|
/** Optional content rendered alongside the left orientation label */
|
|
leftActions?: ReactNode;
|
|
/** Optional content rendered on the right side of the topbar */
|
|
actions?: ReactNode;
|
|
variant?: "breadcrumb" | "root";
|
|
className?: string;
|
|
centerClassName?: string;
|
|
actionsClassName?: string;
|
|
};
|
|
|
|
export const PageTopbar = forwardRef<HTMLElement, PageTopbarProps>(function PageTopbar(
|
|
{
|
|
title,
|
|
subtitle,
|
|
icon,
|
|
backHref = "/",
|
|
backLabel = "KanDev",
|
|
leading,
|
|
center,
|
|
leftActions,
|
|
actions,
|
|
variant = "breadcrumb",
|
|
className,
|
|
centerClassName,
|
|
actionsClassName,
|
|
},
|
|
ref,
|
|
) {
|
|
return (
|
|
<header
|
|
ref={ref}
|
|
className={cn("relative flex h-14 shrink-0 items-center gap-3 border-b px-4", className)}
|
|
>
|
|
{leading}
|
|
{variant === "root" ? (
|
|
<div className="relative z-10 flex min-w-0 items-center">
|
|
<span className="truncate text-[15px] font-semibold leading-none">{backLabel}</span>
|
|
</div>
|
|
) : (
|
|
<Breadcrumb className="relative z-10 min-w-0">
|
|
<BreadcrumbList className="flex-nowrap">
|
|
<BreadcrumbItem className="shrink-0">
|
|
<BreadcrumbLink asChild className="flex items-center gap-1.5 cursor-pointer">
|
|
<Link href={backHref}>
|
|
<IconArrowLeft className="h-3.5 w-3.5" />
|
|
{backLabel}
|
|
</Link>
|
|
</BreadcrumbLink>
|
|
</BreadcrumbItem>
|
|
<BreadcrumbSeparator className="shrink-0" />
|
|
<BreadcrumbItem className="min-w-0">
|
|
<BreadcrumbPage className="flex min-w-0 items-center gap-2">
|
|
{icon}
|
|
<span className="truncate text-sm font-semibold">{title}</span>
|
|
{subtitle && (
|
|
<>
|
|
<span className="hidden text-muted-foreground/50 sm:inline">·</span>
|
|
<span className="hidden truncate text-xs text-muted-foreground sm:inline">
|
|
{subtitle}
|
|
</span>
|
|
</>
|
|
)}
|
|
</BreadcrumbPage>
|
|
</BreadcrumbItem>
|
|
</BreadcrumbList>
|
|
</Breadcrumb>
|
|
)}
|
|
{leftActions && (
|
|
<div className="relative z-10 flex shrink-0 items-center gap-1 [&:empty]:hidden">
|
|
{leftActions}
|
|
</div>
|
|
)}
|
|
{center && (
|
|
<div
|
|
className={cn(
|
|
"pointer-events-none absolute left-1/2 top-1/2 z-0 -translate-x-1/2 -translate-y-1/2",
|
|
centerClassName,
|
|
)}
|
|
>
|
|
<div className="pointer-events-auto">{center}</div>
|
|
</div>
|
|
)}
|
|
{actions && (
|
|
<div
|
|
className={cn("relative z-10 ml-auto flex shrink-0 items-center gap-2", actionsClassName)}
|
|
>
|
|
{actions}
|
|
</div>
|
|
)}
|
|
</header>
|
|
);
|
|
});
|