Files
message-inbox-web-frontend-sdk/apps/web/components/nav/Header.tsx
T
2026-07-17 21:48:37 +05:30

101 lines
3.7 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { useFeatureFlags, useSdk, useTheme, useNotifications } from "@lynkd/messaging-inbox-sdk";
import { useUi } from "@/lib/ui-state";
import { Avatar, IconButton } from "@/components/ui/primitives";
import { Search, Sun, Moon, Bell, ChevronDown, PanelLeft } from "lucide-react";
export function Header({
title,
subtitle,
eyebrow,
children,
}: {
title: React.ReactNode;
subtitle?: React.ReactNode;
eyebrow?: string;
children?: React.ReactNode;
}) {
const flags = useFeatureFlags();
const { me } = useSdk();
const { scheme, toggleScheme } = useTheme();
const { setPaletteOpen, setNotifOpen, openProfile, setSidebarOpen, sidebarCollapsed, toggleSidebarCollapsed } = useUi();
const { unread } = useNotifications();
const [mac, setMac] = useState(true);
useEffect(() => {
setMac(/mac|iphone|ipad/i.test(navigator.platform || navigator.userAgent));
}, []);
return (
<header className="flex h-[60px] shrink-0 items-center gap-3 border-b border-border bg-surface/80 px-4 backdrop-blur">
<button
className="focus-ring grid h-9 w-9 place-items-center rounded-control text-muted hover:bg-hover md:hidden"
onClick={() => setSidebarOpen(true)}
aria-label="Open sidebar"
>
<PanelLeft size={18} />
</button>
{sidebarCollapsed && (
<button
className="focus-ring hidden h-9 w-9 place-items-center rounded-control text-muted hover:bg-hover hover:text-ink md:grid"
onClick={toggleSidebarCollapsed}
aria-label="Expand sidebar"
title="Expand sidebar"
>
<PanelLeft size={18} />
</button>
)}
<div className="min-w-0 flex-1">
{eyebrow && <div className="text-[11px] font-semibold uppercase tracking-wide text-dim">{eyebrow}</div>}
<div className="flex items-center gap-2">
<h1 className="truncate text-[17px] font-bold leading-tight">{title}</h1>
</div>
{subtitle && <p className="truncate text-[12.5px] text-muted">{subtitle}</p>}
</div>
<div className="flex items-center gap-1.5">
{children}
{flags.search && (
<button
onClick={() => setPaletteOpen(true)}
className="focus-ring hidden items-center gap-2 rounded-control border border-border bg-panel px-3 py-2 text-[13px] text-muted transition-colors hover:bg-hover hover:text-ink sm:flex"
>
<Search size={15} />
<span>Search</span>
<kbd suppressHydrationWarning className="rounded bg-hover px-1.5 py-0.5 font-mono text-[10px] text-dim">{mac ? "⌘K" : "Ctrl K"}</kbd>
</button>
)}
{flags.themeToggle && (
<IconButton label="Toggle theme" onClick={toggleScheme}>
{scheme === "dark" ? <Sun size={18} /> : <Moon size={18} />}
</IconButton>
)}
{flags.notifications && (
<IconButton label="Notifications" onClick={() => setNotifOpen(true)} badge={unread}>
<Bell size={18} />
</IconButton>
)}
{me && (
<button
onClick={() => openProfile(me.id)}
className="focus-ring ml-1 flex items-center gap-2 rounded-control p-1 pr-2 hover:bg-hover"
>
<Avatar user={me} size={32} showPresence={false} />
<span className="hidden text-left lg:block">
<span className="block text-[13px] font-semibold leading-tight">{me.name}</span>
<span className="block text-[11px] text-muted">{me.title}</span>
</span>
<ChevronDown size={15} className="hidden text-muted lg:block" />
</button>
)}
</div>
</header>
);
}