78 lines
2.4 KiB
TypeScript
78 lines
2.4 KiB
TypeScript
"use client"
|
|
|
|
import type { ComponentProps, ReactNode } from "react"
|
|
|
|
import { Button } from "@/components/ui/button"
|
|
import { Separator } from "@/components/ui/separator"
|
|
import { SidebarTrigger } from "@/components/ui/sidebar"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
interface SiteHeaderProps {
|
|
title: string
|
|
lead?: string
|
|
primaryAction?: ReactNode
|
|
secondaryAction?: ReactNode
|
|
primaryAlignment?: "right" | "center"
|
|
}
|
|
|
|
function SiteHeaderBase({
|
|
title,
|
|
lead,
|
|
primaryAction,
|
|
secondaryAction,
|
|
primaryAlignment = "right",
|
|
}: SiteHeaderProps) {
|
|
const actionsClassName =
|
|
primaryAlignment === "center" && !secondaryAction
|
|
? "flex w-full flex-col items-stretch gap-2 sm:w-full sm:flex-row sm:items-center sm:justify-center"
|
|
: "flex w-full flex-col items-stretch gap-2 sm:w-auto sm:flex-row sm:items-center"
|
|
|
|
return (
|
|
<header className="flex h-auto shrink-0 flex-wrap items-start gap-3 border-b bg-background/80 px-4 py-3 backdrop-blur supports-[backdrop-filter]:bg-background/60 transition-[width,height] ease-linear sm:h-(--header-height) sm:flex-nowrap sm:items-center sm:px-6 lg:px-8 sm:group-has-data-[collapsible=icon]/sidebar-wrapper:h-(--header-height)">
|
|
<SidebarTrigger className="-ml-1" />
|
|
<Separator orientation="vertical" className="mx-3 hidden h-6 sm:block" />
|
|
<div className="flex flex-1 flex-col gap-1">
|
|
{lead ? <span className="text-sm text-muted-foreground">{lead}</span> : null}
|
|
<h1 className="text-lg font-semibold">{title}</h1>
|
|
</div>
|
|
<div className={actionsClassName}>
|
|
{secondaryAction}
|
|
{primaryAction}
|
|
</div>
|
|
</header>
|
|
)
|
|
}
|
|
|
|
export function SiteHeaderPrimaryButton({
|
|
children,
|
|
className,
|
|
...props
|
|
}: ComponentProps<typeof Button>) {
|
|
return (
|
|
<Button size="sm" className={cn("w-full sm:w-auto", className)} {...props}>
|
|
{children}
|
|
</Button>
|
|
)
|
|
}
|
|
|
|
export function SiteHeaderSecondaryButton({
|
|
children,
|
|
className,
|
|
...props
|
|
}: ComponentProps<typeof Button>) {
|
|
return (
|
|
<Button size="sm" variant="outline" className={cn("w-full sm:w-auto", className)} {...props}>
|
|
{children}
|
|
</Button>
|
|
)
|
|
}
|
|
|
|
type SiteHeaderComponent = ((props: SiteHeaderProps) => JSX.Element) & {
|
|
PrimaryButton: typeof SiteHeaderPrimaryButton
|
|
SecondaryButton: typeof SiteHeaderSecondaryButton
|
|
}
|
|
|
|
export const SiteHeader: SiteHeaderComponent = Object.assign(SiteHeaderBase, {
|
|
PrimaryButton: SiteHeaderPrimaryButton,
|
|
SecondaryButton: SiteHeaderSecondaryButton,
|
|
})
|