Voice / frontend /src /components /layout /Header.tsx
Thang6822
Deploy OmniVoice Docker Space
342571f
Raw
History Blame Contribute Delete
3.48 kB
import React from 'react';
import { Mic, Settings, ShieldAlert, Sparkles, Video } from 'lucide-react';
interface HeaderProps {
activeTab: 'audio' | 'video' | 'post-production' | 'playground';
tabs: Array<{ id: 'audio' | 'video' | 'post-production' | 'playground'; label: string; enabled: boolean }>;
runtimeMode: string;
onSelectTab: (tab: 'audio' | 'video' | 'post-production' | 'playground') => void;
onOpenAccessHelp: () => void;
}
const TAB_ICONS = {
playground: Sparkles,
audio: Mic,
video: Video,
'post-production': Settings,
} as const;
export function Header({ activeTab, tabs, runtimeMode, onSelectTab, onOpenAccessHelp }: HeaderProps) {
return (
<header className="sticky top-0 z-50 border-b border-zinc-900 bg-obsidian-dark shrink-0">
<div className="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between gap-6">
<div className="flex items-center gap-3 min-w-0">
<div className="w-8 h-8 rounded bg-zinc-950 border border-zinc-850 flex items-center justify-center relative overflow-hidden group shrink-0 shadow-inner">
<div className="flex gap-[2px] items-center">
<div className="w-[2px] h-2 bg-amber-cinematic rounded-sm animate-pulse" />
<div className="w-[2px] h-4 bg-amber-glow rounded-sm animate-pulse" style={{ animationDelay: '150ms' }} />
<div className="w-[2px] h-3 bg-zinc-400 rounded-sm animate-pulse" style={{ animationDelay: '300ms' }} />
<div className="w-[2px] h-1 bg-zinc-600 rounded-sm" />
</div>
</div>
<div className="min-w-0">
<h1 className="text-sm font-black uppercase tracking-wider text-white flex items-center gap-1.5 font-sans shrink-0">
OmniVoice <span className="text-amber-cinematic">Studio</span>
</h1>
<p className="text-[9px] uppercase tracking-[0.3em] text-zinc-500">{runtimeMode.replace('_', ' ')}</p>
</div>
</div>
<div className="flex bg-zinc-950 p-0.5 border border-zinc-900 justify-self-center rounded-lg">
{tabs.map((tab) => {
const Icon = TAB_ICONS[tab.id];
const isActive = activeTab === tab.id;
return (
<button
key={tab.id}
onClick={() => onSelectTab(tab.id)}
className={`px-4 py-1.5 text-[10px] font-black uppercase tracking-wider rounded-md transition-all duration-200 flex items-center gap-1.5 cursor-pointer ${
isActive
? 'bg-amber-cinematic text-black shadow-[0_0_10px_rgba(245,158,11,0.3)]'
: 'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-900/40'
} ${!tab.enabled ? 'opacity-70' : ''}`}
>
<Icon className="w-3.5 h-3.5" /> {tab.label}
</button>
);
})}
</div>
<div className="flex items-center gap-3 shrink-0">
<button
onClick={onOpenAccessHelp}
className="hidden sm:flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-zinc-900 hover:bg-zinc-800 border border-zinc-800 hover:border-zinc-700 text-zinc-300 hover:text-white transition-all text-[10px] font-black uppercase tracking-widest cursor-pointer"
>
<ShieldAlert className="w-3.5 h-3.5 text-amber-cinematic animate-pulse" /> Runtime Access
</button>
</div>
</div>
</header>
);
}