nova-test / components /Navbar.tsx
Leon4gr45's picture
Upload folder using huggingface_hub
4fdaf19 verified
Raw
History Blame Contribute Delete
5.21 kB
import React, { useState } from 'react';
import { Menu, X } from 'lucide-react';
import Button from './ui/Button';
export interface NavbarProps {
currentTab: string;
onTabChange: (tab: 'usersync' | 'nova-act' | 'datahub' | 'oasis' | 'graph' | 'dev') => void;
onLogin?: () => void;
onLogout?: () => void;
user?: any;
}
export const TABS = [
{ id: 'usersync', name: 'UserSync', desc: 'Simulations & content' },
{ id: 'nova-act', name: 'Nova Act', desc: 'Browser agents & QA' },
{ id: 'datahub', name: 'DataHub', desc: 'Extraction & warehouse' },
{ id: 'oasis', name: 'Oasis', desc: 'Network & trust' },
{ id: 'graph', name: 'Graph', desc: 'Topology & signals' },
{ id: 'dev', name: 'Dev', desc: 'API docs & status' },
] as const;
const Navbar: React.FC<NavbarProps> = ({ currentTab, onTabChange, onLogin, onLogout, user }) => {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
return (
<nav className="sticky top-0 left-0 right-0 z-50 bg-[#0a0a0a]/90 backdrop-blur-md py-2 border-b border-gray-800">
<div className="max-w-[1600px] mx-auto px-4 flex items-center justify-between">
{/* Logo and Brand */}
<div className="flex items-center gap-2 cursor-pointer" onClick={() => onTabChange('usersync')}>
<div className="w-7 h-7 flex items-center justify-center font-bold text-sm text-white">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" className="w-full h-full">
<path d="M12 2L2 22h20L12 2z" className="text-teal-500" />
<path d="M12 6L6 20h12L12 6z" className="text-white fill-white" />
</svg>
</div>
<span className="font-bold text-base tracking-tight text-white hidden xl:inline">UserSync</span>
</div>
{/* Tab Links (Tabs 1-10) */}
<div className="hidden lg:flex items-center gap-1 xl:gap-2">
{TABS.map((tab) => {
const isActive = currentTab === tab.id;
return (
<button
key={tab.id}
onClick={() => onTabChange(tab.id)}
className={`px-2.5 py-1.5 rounded-lg text-xs font-semibold transition-all duration-150 flex flex-col items-center ${
isActive
? 'bg-teal-500/10 text-teal-400 border border-teal-500/20'
: 'text-gray-400 hover:text-white border border-transparent hover:bg-gray-900/50'
}`}
title={tab.desc}
>
<span>{tab.name}</span>
<span className="text-[8px] opacity-60 font-medium hidden xl:inline">{tab.desc}</span>
</button>
);
})}
</div>
{/* Auth Controls */}
<div className="flex items-center gap-2">
{user ? (
<div className="flex items-center gap-2 bg-gray-900/50 border border-gray-800 rounded-full pl-2 pr-3 py-1">
{user.avatarUrl && <img src={user.avatarUrl} alt={user.preferred_username} className="w-5 h-5 rounded-full" />}
<span className="text-xs font-medium text-gray-300 max-w-[80px] truncate">{user.preferred_username}</span>
<button onClick={onLogout} className="text-[10px] text-gray-500 hover:text-red-400 font-semibold ml-1">Out</button>
</div>
) : (
<Button variant="outline" size="sm" onClick={onLogin} className="py-1 text-xs">Sign in with HF</Button>
)}
{/* Mobile Menu Button */}
<button
className="lg:hidden text-gray-300 hover:text-white p-1.5 rounded-lg hover:bg-gray-900"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
>
{isMobileMenuOpen ? <X size={20} /> : <Menu size={20} />}
</button>
</div>
</div>
{/* Mobile Menu */}
{isMobileMenuOpen && (
<div className="lg:hidden bg-black border-t border-gray-800 p-4 absolute top-full left-0 right-0 max-h-[80vh] overflow-y-auto">
<div className="flex flex-col gap-1">
<span className="text-[10px] text-gray-500 font-bold uppercase tracking-wider mb-2 px-2">Main tabs</span>
{TABS.map((tab) => {
const isActive = currentTab === tab.id;
return (
<button
key={tab.id}
className={`flex items-center justify-between p-2.5 rounded-lg text-left text-sm font-medium ${
isActive ? 'bg-teal-500/10 text-teal-400 border border-teal-500/20' : 'text-gray-300 hover:bg-gray-900/50'
}`}
onClick={() => {
onTabChange(tab.id);
setIsMobileMenuOpen(false);
}}
>
<div>
<div className="font-bold">{tab.name}</div>
<div className="text-[10px] opacity-60">{tab.desc}</div>
</div>
<span className="text-xs opacity-40 font-mono">{tab.id}</span>
</button>
);
})}
</div>
</div>
)}
</nav>
);
};
export default Navbar;