Files
moonwell-web/resources/js/moonwell/Nav.jsx
T
2026-04-26 16:09:08 +04:00

119 lines
5.1 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useState } from 'react';
import { Icons, MoonMark, getBootstrap } from './atoms.jsx';
export default function Nav() {
const [scrolled, setScrolled] = useState(false);
const [open, setOpen] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 40);
window.addEventListener('scroll', onScroll, { passive: true });
return () => window.removeEventListener('scroll', onScroll);
}, []);
useEffect(() => {
document.body.style.overflow = open ? 'hidden' : '';
return () => { document.body.style.overflow = ''; };
}, [open]);
const close = () => setOpen(false);
const links = [
{ href: '#about', label: 'О сервере' },
{ href: '#features', label: 'Особенности' },
{ href: '#join', label: 'Регистрация' },
{ href: '#news', label: 'Новости' },
];
const bootstrap = getBootstrap();
const auth = bootstrap.auth || {};
const playUrl = bootstrap.play_url || '#join';
return (
<nav className={`nav ${scrolled ? 'scrolled' : ''}`}>
<div className="wrap nav-inner">
<a href="#" className="nav-logo" onClick={close}>
<span className="nav-logo-mark" style={{ color: 'var(--moon)' }}>
<MoonMark size={32} />
</span>
<span>MoonWell</span>
</a>
<div className="nav-links nav-links-desktop">
{links.map((l) => (
<a key={l.href} href={l.href}>{l.label}</a>
))}
{auth.is_admin && <a href={auth.admin_url}>Админка</a>}
<a
href={auth.authenticated ? auth.cabinet_url : (auth.login_url || '/login')}
className="nav-cta"
>
{auth.authenticated ? 'Личный кабинет' : 'Войти в кабинет'}
<span style={{ color: 'var(--moon)' }}>{Icons.arrow}</span>
</a>
<a href={playUrl} className="nav-cta">
Играть <span style={{ color: 'var(--moon)' }}>{Icons.arrow}</span>
</a>
</div>
<button
className={`nav-burger ${open ? 'is-open' : ''}`}
onClick={() => setOpen((v) => !v)}
aria-label={open ? 'Закрыть меню' : 'Открыть меню'}
aria-expanded={open}
>
<span></span>
<span></span>
<span></span>
</button>
</div>
<div
className={`nav-drawer-backdrop ${open ? 'is-open' : ''}`}
onClick={close}
aria-hidden="true"
/>
<aside className={`nav-drawer ${open ? 'is-open' : ''}`} aria-hidden={!open}>
<div className="nav-drawer-head">
<span className="eyebrow">Навигация</span>
</div>
<div className="nav-drawer-links">
{links.map((l, i) => (
<a
key={l.href}
href={l.href}
onClick={close}
style={{ transitionDelay: `${60 + i * 40}ms` }}
>
<span className="num">{String(i + 1).padStart(2, '0')}</span>
<span className="lbl">{l.label}</span>
<span className="arr">{Icons.arrow}</span>
</a>
))}
<a
href={auth.authenticated ? auth.cabinet_url : (auth.login_url || '/login')}
onClick={close}
>
<span className="num">{String(links.length + 1).padStart(2, '0')}</span>
<span className="lbl">{auth.authenticated ? 'Личный кабинет' : 'Войти в кабинет'}</span>
<span className="arr">{Icons.arrow}</span>
</a>
{auth.is_admin && (
<a href={auth.admin_url} onClick={close}>
<span className="num">{String(links.length + 2).padStart(2, '0')}</span>
<span className="lbl">Админка</span>
<span className="arr">{Icons.arrow}</span>
</a>
)}
</div>
<a href={playUrl} className="btn btn-primary nav-drawer-cta" onClick={close}>
Играть {Icons.arrow}
</a>
<div className="nav-drawer-foot">
<span className="eyebrow" style={{ color: 'var(--text-mute)' }}>moonwell · 3.3.5a</span>
</div>
</aside>
</nav>
);
}