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

126 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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() || "𝗕𝘂𝗬𝗶";
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-14 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-5",
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-7 w-7 rounded-full object-cover"
src={logo}
/>
) : (
<div className="flex h-7 w-7 items-center justify-center rounded-full bg-black text-white dark:bg-white dark:text-black">
<Sparkles className="h-3.5 w-3.5" />
</div>
)}
<span className="text-[17px] font-semibold leading-none 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}
/>
);
}