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:
@@ -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>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user