Import source: cshare-app/src/components/Navbar

Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
arsam
2026-09-18 23:14:11 +03:30
parent e8dca5e8f3
commit bbd93de4c6
+165
View File
@@ -0,0 +1,165 @@
import { useState, useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { MenuIcon, XIcon } from './Icons';
export default function Navbar() {
const navigate = useNavigate();
const { pathname } = useLocation();
const [mobileOpen, setMobileOpen] = useState(false);
const [scrolled, setScrolled] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 20);
window.addEventListener('scroll', onScroll, { passive: true });
return () => window.removeEventListener('scroll', onScroll);
}, []);
const links = [
{ path: '/', label: 'Home' },
{ path: '/upload', label: 'Upload' },
{ path: '/dashboard', label: 'Dashboard' },
{ path: '/preview', label: 'Preview' },
];
const extraLinks = [
{
label: 'Features',
action: () => {
navigate('/');
setTimeout(() => document.getElementById('features')?.scrollIntoView({ behavior: 'smooth' }), 150);
},
},
{
label: 'How it Works',
action: () => {
navigate('/');
setTimeout(() => document.getElementById('how-it-works')?.scrollIntoView({ behavior: 'smooth' }), 150);
},
},
{ label: 'Pricing', action: () => go('/pricing') },
{ label: 'Docs', action: () => go('/docs') },
];
const go = (path) => {
navigate(path);
setMobileOpen(false);
window.scrollTo({ top: 0, behavior: 'smooth' });
};
return (
<>
<nav
className="navbar"
style={{
boxShadow: scrolled ? '0 1px 20px rgba(0,0,0,0.3)' : 'none',
borderBottomColor: scrolled ? 'var(--border)' : 'var(--border-subtle)',
transition: 'all var(--transition-base)',
}}
>
<div className="navbar-logo" onClick={() => go('/')}>
<div
className="logo-mark"
style={{ transition: 'all var(--transition-base)' }}
onMouseEnter={(e) => {
e.currentTarget.style.boxShadow = '0 0 16px rgba(74, 144, 255, 0.4)';
e.currentTarget.style.transform = 'scale(1.05)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.boxShadow = 'none';
e.currentTarget.style.transform = 'scale(1)';
}}
>
C
</div>
CShare
</div>
{/* Desktop nav */}
<div className="navbar-links">
{links.map((link) => (
<button
type="button"
key={link.path}
className={`navbar-link ${pathname === link.path ? 'active' : ''}`}
onClick={() => go(link.path)}
style={{ position: 'relative' }}
>
{link.label}
{pathname === link.path && (
<span style={{
position: 'absolute',
bottom: '-2px',
left: '50%',
transform: 'translateX(-50%)',
width: '16px',
height: '2px',
borderRadius: '1px',
background: 'var(--accent)',
boxShadow: '0 0 6px rgba(74, 144, 255, 0.5)',
}} />
)}
</button>
))}
{extraLinks.map((link, i) => (
<button type="button" key={i} className="navbar-link" onClick={link.action}>
{link.label}
</button>
))}
<button
type="button"
className="btn btn-primary btn-sm"
style={{ marginLeft: '12px' }}
onClick={() => go('/upload')}
>
Share Files
</button>
</div>
{/* Mobile hamburger */}
<button
type="button"
className="btn btn-ghost btn-icon mobile-menu-btn"
aria-label={mobileOpen ? 'Close navigation menu' : 'Open navigation menu'}
aria-controls="mobile-navigation"
aria-expanded={mobileOpen}
onClick={() => setMobileOpen((open) => !open)}
>
{mobileOpen ? <XIcon size={20} /> : <MenuIcon size={20} />}
</button>
</nav>
{mobileOpen && (
<div id="mobile-navigation" className="mobile-menu-panel">
<div className="mobile-menu-list">
{links.map((link) => (
<button
type="button"
key={link.path}
className={`mobile-menu-link ${pathname === link.path ? 'active' : ''}`}
onClick={() => go(link.path)}
>
{link.label}
</button>
))}
{extraLinks.map((link, i) => (
<button
type="button"
key={i}
className="mobile-menu-link"
onClick={() => { link.action(); setMobileOpen(false); }}
>
{link.label}
</button>
))}
<button
type="button"
className="btn btn-primary btn-lg mobile-menu-cta"
onClick={() => go('/upload')}
>
Share Files
</button>
</div>
</div>
)}
</>
);
}