fix(web): wire responsive sidebar — add toggle to AppShell, open prop on Sidebar, CSS !important overrides
This commit is contained in:
parent
e362f2aefe
commit
89edf59a4e
@ -239,22 +239,31 @@ button:active:not(:disabled), [role="button"]:active:not(:disabled) {
|
||||
/* Responsive sidebar */
|
||||
@media (max-width: 768px) {
|
||||
.app-sidebar {
|
||||
position: fixed;
|
||||
left: -260px;
|
||||
top: 0;
|
||||
position: fixed !important;
|
||||
left: -280px !important;
|
||||
top: 0 !important;
|
||||
z-index: 40;
|
||||
width: 240px;
|
||||
height: 100vh;
|
||||
width: 260px !important;
|
||||
height: 100vh !important;
|
||||
transition: left 0.2s ease;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.app-sidebar.open { left: 0; }
|
||||
.app-sidebar.open { left: 0 !important; }
|
||||
.sidebar-overlay { display: none; position: fixed; inset: 0; z-index: 39; background: rgba(0,0,0,0.5); }
|
||||
.sidebar-overlay.open { display: block; }
|
||||
.sidebar-toggle { display: flex; }
|
||||
.sidebar-toggle {
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
position: fixed; top: 12px; left: 12px; z-index: 38;
|
||||
width: 40px; height: 40px; border-radius: 8px;
|
||||
border: 1px solid var(--nl-border-default, #2a2a4a);
|
||||
background: var(--nl-bg-elevated, #12151c);
|
||||
color: var(--nl-text-primary, #fff);
|
||||
cursor: pointer; font-size: 20px; line-height: 1;
|
||||
}
|
||||
}
|
||||
@media (min-width: 769px) {
|
||||
.sidebar-toggle { display: none; }
|
||||
.sidebar-overlay { display: none; }
|
||||
.sidebar-toggle { display: none !important; }
|
||||
.sidebar-overlay { display: none !important; }
|
||||
}
|
||||
|
||||
/* Respect user motion preference */
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
import type { ReactNode } from "react";
|
||||
"use client";
|
||||
|
||||
import { type ReactNode, useState, useCallback, useEffect } from "react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { Sidebar } from "@/components/Sidebar";
|
||||
|
||||
export function AppShell({
|
||||
@ -12,12 +15,35 @@ export function AppShell({
|
||||
actions?: ReactNode;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const pathname = usePathname();
|
||||
|
||||
useEffect(() => {
|
||||
setSidebarOpen(false);
|
||||
}, [pathname]);
|
||||
|
||||
const toggle = useCallback(() => setSidebarOpen((o) => !o), []);
|
||||
const close = useCallback(() => setSidebarOpen(false), []);
|
||||
|
||||
return (
|
||||
<div className="app-shell">
|
||||
<a href="#main-content" className="skip-link">
|
||||
Skip to main content
|
||||
</a>
|
||||
<Sidebar />
|
||||
<button
|
||||
className="sidebar-toggle"
|
||||
onClick={toggle}
|
||||
aria-label={sidebarOpen ? "Close menu" : "Open menu"}
|
||||
type="button"
|
||||
>
|
||||
{sidebarOpen ? "\u2715" : "\u2630"}
|
||||
</button>
|
||||
<div
|
||||
className={`sidebar-overlay${sidebarOpen ? " open" : ""}`}
|
||||
onClick={close}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<Sidebar open={sidebarOpen} />
|
||||
<main id="main-content" className="main-panel" tabIndex={-1} aria-labelledby="page-title">
|
||||
<div className="page-grid">
|
||||
<header
|
||||
|
||||
@ -14,11 +14,11 @@ const navItems: { href: string; label: string; icon: typeof House; flag?: string
|
||||
{ href: "/settings", label: "Settings", icon: Settings },
|
||||
];
|
||||
|
||||
export function Sidebar() {
|
||||
export function Sidebar({ open }: { open?: boolean }) {
|
||||
const pathname = usePathname() ?? "";
|
||||
|
||||
return (
|
||||
<aside className="sidebar" style={{ padding: "var(--nl-space-6)" }} aria-label="Primary">
|
||||
<aside className={`sidebar app-sidebar${open ? ' open' : ''}`} style={{ padding: "var(--nl-space-6)" }} aria-label="Primary">
|
||||
<div style={{ display: "grid", gap: "var(--nl-space-6)" }}>
|
||||
<div className="surface-card" style={{ padding: "var(--nl-space-5)", display: "grid", gap: "var(--nl-space-3)" }}>
|
||||
<div className="badge" style={{ width: "fit-content" }}>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user