Sync shared components — sidebar scrollbar, Layout, AuthGate updates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a3b458abca
commit
79eba484e0
2 changed files with 40 additions and 11 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
import { NavLink } from 'react-router-dom'
|
import { useState, useEffect } from 'react'
|
||||||
import { Wrench, ClipboardList, History, Boxes, HardHat, Repeat, MapPin, Settings } from 'lucide-react'
|
import { NavLink, useLocation } from 'react-router-dom'
|
||||||
|
import { Wrench, ClipboardList, History, Boxes, HardHat, Repeat, MapPin, Settings, Menu } from 'lucide-react'
|
||||||
import { useAuth } from './AuthGate'
|
import { useAuth } from './AuthGate'
|
||||||
import { can } from '../types'
|
import { can } from '../types'
|
||||||
|
|
||||||
|
|
@ -18,9 +19,13 @@ const NAV = [
|
||||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
const { user } = useAuth()
|
const { user } = useAuth()
|
||||||
const items = NAV.filter(n => can(user, n.cap))
|
const items = NAV.filter(n => can(user, n.cap))
|
||||||
|
const location = useLocation()
|
||||||
|
const [menuOpen, setMenuOpen] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => { setMenuOpen(false) }, [location.pathname])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="app-shell">
|
<div className={`app-shell${menuOpen ? ' menu-open' : ''}`}>
|
||||||
<aside className="sidebar">
|
<aside className="sidebar">
|
||||||
<div className="sidebar-logo">
|
<div className="sidebar-logo">
|
||||||
<Wrench size={18} strokeWidth={1.75} />
|
<Wrench size={18} strokeWidth={1.75} />
|
||||||
|
|
@ -37,16 +42,14 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
<div className="sidebar-user">{user.name}</div>
|
<div className="sidebar-user">{user.name}</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
|
{menuOpen && <div className="menu-backdrop" onClick={() => setMenuOpen(false)} />}
|
||||||
|
|
||||||
<header className="top-bar">
|
<header className="top-bar">
|
||||||
|
<button className="top-bar-burger" onClick={() => setMenuOpen(o => !o)}>
|
||||||
|
<Menu size={20} strokeWidth={1.75} />
|
||||||
|
</button>
|
||||||
<Wrench size={18} strokeWidth={1.75} color="var(--gold)" />
|
<Wrench size={18} strokeWidth={1.75} color="var(--gold)" />
|
||||||
<span className="top-bar-title">Maintenance</span>
|
<span className="top-bar-title">Maintenance</span>
|
||||||
<nav className="top-bar-nav">
|
|
||||||
{items.map(({ to, label }) => (
|
|
||||||
<NavLink key={to} to={to} className={({ isActive }) => isActive ? 'active' : ''}>
|
|
||||||
{label}
|
|
||||||
</NavLink>
|
|
||||||
))}
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main className="page-content">
|
<main className="page-content">
|
||||||
|
|
|
||||||
|
|
@ -124,9 +124,35 @@ html, body, #root { height: 100%; margin: 0; font-size: 14px; }
|
||||||
.page-content { flex: 1; overflow-y: auto; display: flex; flex-direction: column; }
|
.page-content { flex: 1; overflow-y: auto; display: flex; flex-direction: column; }
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.sidebar { display: none; }
|
.sidebar {
|
||||||
|
position: fixed;
|
||||||
|
top: 0; left: 0; bottom: 0;
|
||||||
|
z-index: 200;
|
||||||
|
transform: translateX(calc(-1 * var(--sidebar-w)));
|
||||||
|
transition: transform 0.25s ease;
|
||||||
|
}
|
||||||
|
.app-shell.menu-open .sidebar { transform: translateX(0); }
|
||||||
.top-bar { display: flex; }
|
.top-bar { display: flex; }
|
||||||
.app-shell { flex-direction: column; }
|
.app-shell { flex-direction: column; }
|
||||||
|
.field-row { flex-direction: column; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
z-index: 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar-burger {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: var(--text);
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Page chrome ───────────────────────────────────────────── */
|
/* ── Page chrome ───────────────────────────────────────────── */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue