Add burger menu to mobile top-bar — sidebar slides in with backdrop overlay
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
552c11864d
commit
7cf6f14aeb
2 changed files with 37 additions and 4 deletions
|
|
@ -386,13 +386,38 @@ html, body, #root {
|
||||||
|
|
||||||
/* ── Mobile ─────────────────────────────────────────────────────── */
|
/* ── Mobile ─────────────────────────────────────────────────────── */
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
.sidebar { display: none; }
|
.app-shell { flex-direction: column; }
|
||||||
.page-content { flex-direction: column; }
|
.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; }
|
||||||
.report-view { padding: 16px; }
|
.report-view { padding: 16px; }
|
||||||
.report-controls { gap: 8px; }
|
.report-controls { gap: 8px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
z-index: 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar-burger {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Sidebar scrollbar */
|
/* Sidebar scrollbar */
|
||||||
.nav-scroll::-webkit-scrollbar,
|
.nav-scroll::-webkit-scrollbar,
|
||||||
.sidebar::-webkit-scrollbar,
|
.sidebar::-webkit-scrollbar,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { useEffect, useState, useCallback } from 'react'
|
||||||
import {
|
import {
|
||||||
BarChart2, Building2, UtensilsCrossed, ShoppingCart, Database,
|
BarChart2, Building2, UtensilsCrossed, ShoppingCart, Database,
|
||||||
ChevronRight, ChevronDown, Play, Download, Loader2, AlertCircle,
|
ChevronRight, ChevronDown, Play, Download, Loader2, AlertCircle,
|
||||||
FileBarChart, TrendingUp, Settings,
|
FileBarChart, TrendingUp, Settings, Menu,
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
import { useAuth } from '../components/AuthGate'
|
import { useAuth } from '../components/AuthGate'
|
||||||
import { fetchReports, runReport } from '../api'
|
import { fetchReports, runReport } from '../api'
|
||||||
|
|
@ -276,6 +276,7 @@ export default function ReportsPage() {
|
||||||
const [reports, setReports] = useState<ReportMeta[]>([])
|
const [reports, setReports] = useState<ReportMeta[]>([])
|
||||||
const [selected, setSelected] = useState<ReportMeta | null>(null)
|
const [selected, setSelected] = useState<ReportMeta | null>(null)
|
||||||
const [showSettings, setShowSettings] = useState(false)
|
const [showSettings, setShowSettings] = useState(false)
|
||||||
|
const [menuOpen, setMenuOpen] = useState(false)
|
||||||
const [dateFrom, setDateFrom] = useState(daysAgo(7))
|
const [dateFrom, setDateFrom] = useState(daysAgo(7))
|
||||||
const [dateTo, setDateTo] = useState(today())
|
const [dateTo, setDateTo] = useState(today())
|
||||||
const [result, setResult] = useState<ReportResult | null>(null)
|
const [result, setResult] = useState<ReportResult | null>(null)
|
||||||
|
|
@ -291,6 +292,7 @@ export default function ReportsPage() {
|
||||||
const handleSelect = useCallback((r: ReportMeta) => {
|
const handleSelect = useCallback((r: ReportMeta) => {
|
||||||
setSelected(r)
|
setSelected(r)
|
||||||
setShowSettings(false)
|
setShowSettings(false)
|
||||||
|
setMenuOpen(false)
|
||||||
setResult(null)
|
setResult(null)
|
||||||
setError(null)
|
setError(null)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
@ -298,6 +300,7 @@ export default function ReportsPage() {
|
||||||
const handleSettings = useCallback(() => {
|
const handleSettings = useCallback(() => {
|
||||||
setShowSettings(true)
|
setShowSettings(true)
|
||||||
setSelected(null)
|
setSelected(null)
|
||||||
|
setMenuOpen(false)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleRun = async () => {
|
const handleRun = async () => {
|
||||||
|
|
@ -316,11 +319,16 @@ export default function ReportsPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="app-shell">
|
<div className={`app-shell${menuOpen ? ' menu-open' : ''}`}>
|
||||||
<Sidebar tree={tree} selectedId={showSettings ? '__settings__' : (selected?.id ?? null)} onSelect={handleSelect} onSettings={handleSettings} />
|
<Sidebar tree={tree} selectedId={showSettings ? '__settings__' : (selected?.id ?? null)} onSelect={handleSelect} onSettings={handleSettings} />
|
||||||
|
|
||||||
|
{menuOpen && <div className="menu-backdrop" onClick={() => setMenuOpen(false)} />}
|
||||||
|
|
||||||
{/* Mobile top bar */}
|
{/* Mobile top bar */}
|
||||||
<div className="top-bar">
|
<div className="top-bar">
|
||||||
|
<button className="top-bar-burger" onClick={() => setMenuOpen(o => !o)}>
|
||||||
|
<Menu size={20} strokeWidth={1.75} />
|
||||||
|
</button>
|
||||||
<BarChart2 size={18} strokeWidth={1.75} color="var(--gold)" />
|
<BarChart2 size={18} strokeWidth={1.75} color="var(--gold)" />
|
||||||
<span className="top-bar-title">Reports</span>
|
<span className="top-bar-title">Reports</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue