ai-chatbot/components/layout/brand-top-bar.tsx

126 lines
3.5 KiB
TypeScript

"use client";
import type { ComponentProps, ReactNode } from "react";
import { Sparkles } from "lucide-react";
import { cn } from "@/lib/utils";
type BrandTopBarProps = {
actions?: ReactNode;
children?: ReactNode;
className?: string;
contentClassName?: string;
logo?: string | null;
offsetTop?: number;
onLogoClick?: () => void;
position?: "fixed" | "sticky" | "static";
showBrand?: boolean;
siteName: string;
};
export function BrandTopBar({
actions,
children,
className,
contentClassName,
logo,
offsetTop = 0,
onLogoClick,
position = "fixed",
showBrand = true,
siteName,
}: BrandTopBarProps) {
const resolvedSiteName = String(siteName || "").trim() || "由壹点AI";
const positionClass =
position === "fixed"
? "fixed left-0 top-0 z-40 w-full"
: position === "sticky"
? "sticky top-0 z-40"
: "relative z-40";
return (
<header
className={cn(
positionClass,
"h-[68px] bg-white/90 backdrop-blur dark:bg-[#0a0a0c]/90",
className
)}
style={position === "fixed" ? { top: offsetTop } : undefined}
>
<div
className={cn(
"flex h-full items-center px-7",
showBrand ? "justify-between" : "justify-end",
contentClassName
)}
>
{showBrand ? (
<button
className="flex items-center gap-2 transition-opacity hover:opacity-80"
onClick={onLogoClick}
type="button"
>
{logo ? (
<img
alt={resolvedSiteName}
className="h-8 w-8 rounded-full object-cover"
src={logo}
/>
) : (
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-black text-white dark:bg-white dark:text-black">
<Sparkles className="h-4 w-4" />
</div>
)}
<span className="text-[20px] font-semibold leading-none tracking-tight dark:text-zinc-100">
{resolvedSiteName}
</span>
</button>
) : null}
<div className="flex items-center gap-2">{actions || children}</div>
</div>
</header>
);
}
type BrandTopBarButtonProps = ComponentProps<"button"> & {
variant?: "default" | "primary";
};
export function BrandTopBarButton({
className,
type = "button",
variant = "default",
...props
}: BrandTopBarButtonProps) {
return (
<button
className={cn(
"inline-flex h-8 items-center justify-center gap-1.5 rounded-[14px] px-3 text-[12px] font-medium shadow-sm transition disabled:cursor-not-allowed disabled:opacity-45",
variant === "primary"
? "bg-[#1c1c1e] text-white hover:bg-black"
: "border border-black/10 bg-white text-black/70 hover:bg-black/5 hover:text-black dark:border-white/10 dark:bg-white/6 dark:text-white/72 dark:hover:bg-white/10 dark:hover:text-white",
className
)}
type={type}
{...props}
/>
);
}
export function BrandTopBarIconButton({
className,
type = "button",
...props
}: ComponentProps<"button">) {
return (
<button
className={cn(
"flex h-8 w-8 items-center justify-center rounded-full border border-black/10 bg-white text-black/65 shadow-sm transition hover:bg-black/5 hover:text-black dark:border-white/10 dark:bg-white/6 dark:text-white/72 dark:hover:bg-white/10 dark:hover:text-white",
className
)}
type={type}
{...props}
/>
);
}