gbclient/app/client-nav.tsx

443 lines
11 KiB
TypeScript
Raw Normal View History

"use client";
import { usePathname, useRouter } from 'next/navigation';
import { Button } from '../src/components/ui/button';
import Image from 'next/image';
import { useRef, useEffect } from 'react';
const examples = [
{ name: "Chat", href: "/chat" },
{ name: "Dashboard", href: "/dashboard" },
{ name: "Mail", href: "/mail" },
{ name: "Tree", href: "/tree" },
{ name: "Editor", href: "/editor" },
{ name: "Tables", href: "/table" },
{ name: "Meet", href: "/meet" },
{ name: "Videos", href: "/videos" },
{ name: "Music", href: "/music" },
{ name: "Templates", href: "/templates" },
{ name: "Settings", href: "/settings" },
];
export function Nav() {
const pathname = usePathname();
const router = useRouter();
const scrollContainerRef = useRef<HTMLDivElement>(null);
const navItemsRefs = useRef<(HTMLButtonElement | null)[]>([]);
// Enhanced URL matching to handle sub-routes
const isActive = (href: string) => {
if (href === '/') return pathname === href;
return pathname.startsWith(href);
};
useEffect(() => {
// Load GSAP from CDN
const script = document.createElement('script');
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js';
script.onload = () => {
const gsap = window.gsap;
// Animate navigation items on mount
gsap.fromTo('.nav-item',
{
opacity: 0,
y: -10,
scale: 0.9
},
{
opacity: 1,
y: 0,
scale: 1,
duration: 0.6,
stagger: 0.1,
ease: "back.out(1.7)"
}
);
// Add hover animations
navItemsRefs.current.forEach((item, index) => {
if (item) {
item.addEventListener('mouseenter', () => {
gsap.to(item, {
scale: 1.05,
duration: 0.3,
ease: "power2.out"
});
});
item.addEventListener('mouseleave', () => {
gsap.to(item, {
scale: 1,
duration: 0.3,
ease: "power2.out"
});
});
item.addEventListener('click', () => {
gsap.to(item, {
scale: 0.95,
duration: 0.1,
yoyo: true,
repeat: 1,
ease: "power2.inOut"
});
});
}
});
// Animate logo
gsap.fromTo('.logo',
{
opacity: 0,
x: -20,
rotate: -10
},
{
opacity: 1,
x: 0,
rotate: 0,
duration: 0.8,
ease: "elastic.out(1, 0.5)"
}
);
};
document.head.appendChild(script);
return () => {
if (document.head.contains(script)) {
document.head.removeChild(script);
}
};
}, []);
// Smooth scroll functions for mobile
const scrollLeft = () => {
if (scrollContainerRef.current) {
scrollContainerRef.current.scrollBy({
left: -150,
behavior: 'smooth'
});
}
};
const scrollRight = () => {
if (scrollContainerRef.current) {
scrollContainerRef.current.scrollBy({
left: 150,
behavior: 'smooth'
});
}
};
return (
<>
<div className="nav-container">
<div className="nav-inner">
<div className="nav-content">
<div className="logo-container">
<Image
src="/images/generalbots-logo.svg"
alt="Logo"
width={64}
height={24}
className="logo"
/>
</div>
<button className="scroll-btn scroll-left" onClick={scrollLeft} aria-label="Scroll left">
&#8249;
</button>
<div
ref={scrollContainerRef}
className="nav-scroll"
>
<div className="nav-items">
{examples.map((example, index) => {
const active = isActive(example.href);
return (
<button
key={example.href}
ref={el => navItemsRefs.current[index] = el}
onClick={() => router.push(example.href)}
className={`nav-item ${active ? 'active' : ''}`}
>
{example.name}
<div className="neon-glow"></div>
</button>
);
})}
</div>
</div>
<button className="scroll-btn scroll-right" onClick={scrollRight} aria-label="Scroll right">
&#8250;
</button>
</div>
</div>
</div>
<div className="nav-spacer"></div>
<style jsx>{`
.nav-container {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 50;
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%);
border-bottom: 1px solid #333;
height: 40px;
box-shadow: 0 2px 20px rgba(0, 255, 255, 0.1);
}
.nav-inner {
max-width: 100%;
margin: 0 auto;
padding: 0 16px;
height: 100%;
}
.nav-content {
display: flex;
align-items: center;
height: 100%;
gap: 8px;
}
.logo-container {
flex-shrink: 0;
padding: 4px;
border-radius: 6px;
background: rgba(0, 255, 255, 0.1);
box-shadow: 0 0 10px rgba(0, 255, 255, 0.3);
}
.logo {
height: 20px;
width: auto;
filter: drop-shadow(0 0 5px rgba(0, 255, 255, 0.5));
}
.scroll-btn {
display: none;
background: rgba(0, 255, 255, 0.2);
border: 1px solid rgba(0, 255, 255, 0.3);
color: #00ffff;
width: 32px;
height: 32px;
border-radius: 50%;
cursor: pointer;
font-size: 18px;
font-weight: bold;
transition: all 0.3s ease;
flex-shrink: 0;
z-index: 10;
}
.scroll-btn:hover {
background: rgba(0, 255, 255, 0.3);
box-shadow: 0 0 15px rgba(0, 255, 255, 0.5);
transform: scale(1.1);
}
.scroll-btn:active {
transform: scale(0.95);
}
.nav-scroll {
flex: 1;
overflow-x: auto;
overflow-y: hidden;
height: 100%;
-ms-overflow-style: none;
scrollbar-width: none;
scroll-behavior: smooth;
position: relative;
}
.nav-scroll::-webkit-scrollbar {
display: none;
}
.nav-items {
display: flex;
align-items: center;
height: 100%;
white-space: nowrap;
gap: 3px;
padding: 0 8px;
}
.nav-item {
position: relative;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(0, 255, 255, 0.2);
color: #e0e0e0;
font-size: 13px;
font-weight: 500;
padding: 6px 14px;
cursor: pointer;
border-radius: 6px;
height: 32px;
display: inline-flex;
align-items: center;
justify-content: center;
text-decoration: none;
white-space: nowrap;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
overflow: hidden;
}
.nav-item::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(0, 255, 255, 0.2), transparent);
transition: left 0.5s;
}
.nav-item:hover::before {
left: 100%;
}
.nav-item:hover {
background: rgba(0, 255, 255, 0.1);
border-color: rgba(0, 255, 255, 0.4);
color: #00ffff;
box-shadow: 0 0 15px rgba(0, 255, 255, 0.3);
text-shadow: 0 0 8px rgba(0, 255, 255, 0.6);
}
.nav-item.active {
background: linear-gradient(135deg, rgba(0, 255, 255, 0.2), rgba(0, 200, 255, 0.3));
border-color: #00ffff;
color: #ffffff;
box-shadow:
0 0 20px rgba(0, 255, 255, 0.4),
inset 0 0 10px rgba(0, 255, 255, 0.1);
text-shadow: 0 0 10px rgba(0, 255, 255, 0.8);
}
.nav-item.active:hover {
background: linear-gradient(135deg, rgba(0, 255, 255, 0.3), rgba(0, 200, 255, 0.4));
box-shadow:
0 0 25px rgba(0, 255, 255, 0.6),
inset 0 0 15px rgba(0, 255, 255, 0.2);
}
.neon-glow {
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(45deg, transparent, rgba(0, 255, 255, 0.3), transparent);
border-radius: 8px;
opacity: 0;
transition: opacity 0.3s ease;
z-index: -1;
}
.nav-item:hover .neon-glow,
.nav-item.active .neon-glow {
opacity: 1;
}
.nav-spacer {
height: 40px;
}
@media (max-width: 768px) {
.nav-container {
height: 36px;
}
.nav-spacer {
height: 36px;
}
.nav-inner {
padding: 0 8px;
}
.nav-content {
gap: 6px;
}
.scroll-btn {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
font-size: 16px;
}
.logo {
height: 16px;
}
.nav-item {
font-size: 12px;
padding: 4px 12px;
height: 28px;
}
}
@media (max-width: 480px) {
.nav-container {
height: 32px;
}
.nav-spacer {
height: 32px;
}
.nav-inner {
padding: 0 6px;
}
.nav-content {
gap: 4px;
}
.scroll-btn {
width: 24px;
height: 24px;
font-size: 14px;
}
.logo {
height: 14px;
}
.nav-item {
font-size: 11px;
padding: 3px 10px;
height: 24px;
}
}
/* Touch-friendly scrolling for mobile */
@media (hover: none) and (pointer: coarse) {
.nav-scroll {
-webkit-overflow-scrolling: touch;
scroll-snap-type: x mandatory;
}
.nav-item {
scroll-snap-align: start;
}
}
`}</style>
</>
);
}