119 lines
3.4 KiB
TypeScript
119 lines
3.4 KiB
TypeScript
import * as React from 'react';
|
|
import { cn, Button, Input, Search } from '@tree-e2e-1770175251/ui';
|
|
import { Bell, Menu } from 'lucide-react';
|
|
|
|
export interface HeaderProps {
|
|
/** Title to display in the header */
|
|
title?: string;
|
|
/** Breadcrumb or secondary navigation element */
|
|
breadcrumb?: React.ReactNode;
|
|
/** Whether to show the search input */
|
|
showSearch?: boolean;
|
|
/** Placeholder text for search input */
|
|
searchPlaceholder?: string;
|
|
/** Search input change handler */
|
|
onSearch?: (value: string) => void;
|
|
/** Custom actions to display on the right side */
|
|
actions?: React.ReactNode;
|
|
/** User menu or avatar element */
|
|
userMenu?: React.ReactNode;
|
|
/** Mobile menu toggle handler */
|
|
onMenuToggle?: () => void;
|
|
/** Whether to show the menu toggle button (for mobile) */
|
|
showMenuToggle?: boolean;
|
|
/** Additional class names */
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* Header provides the top navigation bar for dashboard applications.
|
|
* Supports title, breadcrumbs, search, notifications, and user menu.
|
|
*
|
|
* @example
|
|
* <Header
|
|
* title="Dashboard"
|
|
* showSearch
|
|
* onSearch={(value) => console.log(value)}
|
|
* userMenu={<UserDropdown />}
|
|
* />
|
|
*/
|
|
export function Header({
|
|
title,
|
|
breadcrumb,
|
|
showSearch = false,
|
|
searchPlaceholder = 'Search...',
|
|
onSearch,
|
|
actions,
|
|
userMenu,
|
|
onMenuToggle,
|
|
showMenuToggle = false,
|
|
className,
|
|
}: HeaderProps) {
|
|
const [searchValue, setSearchValue] = React.useState('');
|
|
|
|
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
setSearchValue(e.target.value);
|
|
onSearch?.(e.target.value);
|
|
};
|
|
|
|
return (
|
|
<div className={cn('flex items-center justify-between w-full px-6', className)}>
|
|
{/* Left section */}
|
|
<div className="flex items-center gap-4">
|
|
{showMenuToggle && (
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
onClick={onMenuToggle}
|
|
className="lg:hidden"
|
|
>
|
|
<Menu className="h-5 w-5" />
|
|
<span className="sr-only">Toggle menu</span>
|
|
</Button>
|
|
)}
|
|
|
|
{breadcrumb ? (
|
|
<div className="flex items-center">{breadcrumb}</div>
|
|
) : title ? (
|
|
<h1 className="text-lg font-semibold">{title}</h1>
|
|
) : null}
|
|
</div>
|
|
|
|
{/* Center section - Search */}
|
|
{showSearch && (
|
|
<div className="hidden md:flex flex-1 max-w-md mx-8">
|
|
<div className="relative w-full">
|
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-[var(--text-muted)]" />
|
|
<Input
|
|
type="search"
|
|
placeholder={searchPlaceholder}
|
|
value={searchValue}
|
|
onChange={handleSearchChange}
|
|
className="pl-9 bg-[var(--surface-50)] border-[var(--border-muted)]"
|
|
/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Right section */}
|
|
<div className="flex items-center gap-2">
|
|
{actions}
|
|
|
|
{/* Notifications */}
|
|
<Button variant="ghost" size="icon" className="relative">
|
|
<Bell className="h-5 w-5" />
|
|
<span className="absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-[var(--error)]" />
|
|
<span className="sr-only">Notifications</span>
|
|
</Button>
|
|
|
|
{/* User menu */}
|
|
{userMenu && (
|
|
<div className="ml-2 border-l border-[var(--border-muted)] pl-4">
|
|
{userMenu}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|