61 lines
2.1 KiB
TypeScript
61 lines
2.1 KiB
TypeScript
'use client';
|
|
|
|
import { AppSwitcher } from './AppSwitcher';
|
|
import { SpaceSwitcher } from './SpaceSwitcher';
|
|
import { UserMenu } from './UserMenu';
|
|
|
|
export interface BreadcrumbItem {
|
|
label: string;
|
|
href?: string;
|
|
}
|
|
|
|
interface HeaderProps {
|
|
/** Which r*App is current (e.g. 'notes', 'vote', 'funds') */
|
|
current?: string;
|
|
/** Breadcrumb trail after the switchers */
|
|
breadcrumbs?: BreadcrumbItem[];
|
|
/** Right-side actions (rendered between breadcrumbs and UserMenu) */
|
|
actions?: React.ReactNode;
|
|
/** Max width class for the inner container */
|
|
maxWidth?: string;
|
|
}
|
|
|
|
export function Header({ current = 'notes', breadcrumbs, actions, maxWidth = 'max-w-6xl' }: HeaderProps) {
|
|
return (
|
|
<nav className="border-b border-slate-800 backdrop-blur-sm bg-slate-900/85 sticky top-0 z-50">
|
|
<div className={`${maxWidth} mx-auto px-4 md:px-6 py-3 flex items-center justify-between gap-2`}>
|
|
{/* Left: App switcher + Space switcher + Breadcrumbs */}
|
|
<div className="flex items-center gap-1 min-w-0">
|
|
<AppSwitcher current={current} />
|
|
<SpaceSwitcher />
|
|
{breadcrumbs && breadcrumbs.length > 0 && (
|
|
<>
|
|
{breadcrumbs.map((crumb, i) => (
|
|
<div key={i} className="flex items-center gap-1 min-w-0">
|
|
<span className="text-slate-600 hidden sm:inline">/</span>
|
|
{crumb.href ? (
|
|
<a
|
|
href={crumb.href}
|
|
className="text-slate-400 hover:text-white transition-colors text-sm hidden sm:inline truncate max-w-[140px]"
|
|
>
|
|
{crumb.label}
|
|
</a>
|
|
) : (
|
|
<span className="text-white text-sm truncate max-w-[140px] md:max-w-[200px]">{crumb.label}</span>
|
|
)}
|
|
</div>
|
|
))}
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
{/* Right: Actions + UserMenu */}
|
|
<div className="flex items-center gap-2 md:gap-3 flex-shrink-0">
|
|
{actions}
|
|
<UserMenu />
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
);
|
|
}
|