Spaces:
Running
Running
File size: 5,010 Bytes
7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b 911f32b 7a7972b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | 'use client';
import { motion, AnimatePresence } from 'framer-motion';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { LayoutGrid, MessageSquare, Search, Box, Sparkles, FolderOpen } from 'lucide-react';
import './globals.css';
const queryClient = new QueryClient();
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en" className="dark">
<body className="antialiased selection:bg-cyan-500/30">
<QueryClientProvider client={queryClient}>
{/* Ambient Backgrounds */}
<div className="bg-aurora" />
<div className="bg-grain" />
<div className="min-h-screen flex text-slate-200 font-sans">
<Sidebar />
<main className="flex-1 flex flex-col relative z-10 overflow-hidden">
<AnimatePresence mode="wait">
<motion.div
key="content"
initial={{ opacity: 0, filter: 'blur(10px)' }}
animate={{ opacity: 1, filter: 'blur(0px)' }}
exit={{ opacity: 0, filter: 'blur(10px)' }}
transition={{ duration: 0.4, ease: [0.22, 1, 0.36, 1] }}
className="flex-1 flex flex-col"
>
{children}
</motion.div>
</AnimatePresence>
</main>
</div>
</QueryClientProvider>
</body>
</html>
);
}
function Sidebar() {
const pathname = usePathname();
return (
<motion.aside
initial={{ x: -20, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
className="w-[280px] glass h-screen sticky top-0 flex flex-col border-r border-white/5 z-20"
>
{/* Brand */}
<div className="p-8">
<div className="flex items-center gap-3">
<div className="relative">
<div className="w-10 h-10 rounded-xl bg-gradient-to-tr from-cyan-500 to-violet-600 flex items-center justify-center shadow-lg shadow-cyan-500/20">
<span className="text-xl">🦅</span>
</div>
<div className="absolute inset-0 bg-cyan-400 blur-lg opacity-40 animate-pulse" />
</div>
<div>
<h1 className="font-bold text-lg text-white tracking-tight font-display">
CodeFalcon
</h1>
<p className="text-[10px] uppercase tracking-widest text-cyan-400 font-semibold">
Agent V2.0
</p>
</div>
</div>
</div>
{/* Nav */}
<nav className="flex-1 px-4 space-y-2">
<NavItem href="/" icon={<LayoutGrid size={20} />} label="Overview" active={pathname === '/'} />
<NavItem href="/chat" icon={<MessageSquare size={20} />} label="Agent Chat" active={pathname === '/chat'} />
<NavItem href="/search" icon={<Search size={20} />} label="Deep Search" active={pathname === '/search'} />
<nav className="mt-8 px-4 text-xs font-semibold text-slate-500 uppercase tracking-wider">
Tools
</nav>
<NavItem href="/refactor" icon={<Box size={20} />} label="Refactor" active={pathname === '/refactor'} />
<NavItem href="/generate" icon={<Sparkles size={20} />} label="Generate" active={pathname === '/generate'} />
</nav>
{/* Footer */}
<div className="p-6 border-t border-white/5">
<div className="flex items-center gap-3 p-3 rounded-lg bg-white/5 border border-white/5">
<div className="w-8 h-8 rounded-full bg-gradient-to-r from-slate-700 to-slate-600 flex items-center justify-center text-xs">
JD
</div>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-white truncate">Connected</p>
<p className="text-xs text-emerald-400">● Online</p>
</div>
</div>
</div>
</motion.aside>
);
}
function NavItem({ href, icon, label, active }: { href: string; icon: React.ReactNode; label: string; active: boolean }) {
return (
<Link href={href}>
<div className="relative group">
{active && (
<motion.div
layoutId="activeNav"
className="absolute inset-0 bg-gradient-to-r from-cyan-500/10 to-violet-500/10 rounded-xl border border-cyan-500/20"
transition={{ type: "spring", stiffness: 300, damping: 30 }}
/>
)}
<div className={`
relative flex items-center gap-3 px-4 py-3 rounded-xl transition-all duration-300
${active ? 'text-cyan-400' : 'text-slate-400 group-hover:text-slate-200 group-hover:bg-white/5'}
`}>
{icon}
<span className="font-medium">{label}</span>
{active && (
<div className="ml-auto w-1.5 h-1.5 rounded-full bg-cyan-400 shadow-[0_0_8px_rgba(34,211,238,0.8)]" />
)}
</div>
</div>
</Link>
);
}
|