diff --git a/web/src/App.jsx b/web/src/App.jsx index 8e904ef..0fa5d20 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -34,6 +34,17 @@ import Konto from "./pages/Konto"; const navClass = ({ isActive }) => (isActive ? "nav-link active" : "nav-link"); +// Die vier Bestandslisten stehen unter einer zuklappbaren Gruppe. Sie sind der +// laengste Block der Leiste und wird im Alltag selten gebraucht – wer einlagert, +// nutzt die Knoepfe darueber. +const LISTEN = [ + { to: "/lebensmittel", icon: "food", label: "Lebensmittel" }, + { to: "/gegenstaende", icon: "package", label: "Gegenstände" }, + { to: "/items", icon: "tag", label: "Einzelstücke" }, + { to: "/chargen", icon: "box", label: "Chargen" }, +]; +const LISTEN_OFFEN_KEY = "nav:listen-offen"; + function NavItem({ to, icon, label, end }) { return ( @@ -46,7 +57,24 @@ function NavItem({ to, icon, label, end }) { function Sidebar() { const { user, isAdmin, logout } = useAuth(); const navigate = useNavigate(); + const { pathname } = useLocation(); const [dashboards, setDashboards] = useState([]); + // Zugeklappt als Vorgabe; der Zustand bleibt im Browser, wie die + // Spalteneinstellungen der Tabellen. + const [listenOffen, setListenOffen] = useState( + () => localStorage.getItem(LISTEN_OFFEN_KEY) === "1", + ); + // Steht man auf einer dieser Seiten, ist die Gruppe offen – ohne den + // gemerkten Zustand zu ueberschreiben. Sonst saehe man nicht, wo man ist. + const aufEinerListe = LISTEN.some((e) => pathname.startsWith(e.to)); + + function klappeListen() { + setListenOffen((alt) => { + const neu = !alt; + localStorage.setItem(LISTEN_OFFEN_KEY, neu ? "1" : "0"); + return neu; + }); + } // Die Dashboards des Benutzers stehen als eigene Eintraege in der Leiste. // Sie aendern sich beim Anlegen und Loeschen, deshalb horcht die Leiste auf @@ -82,10 +110,28 @@ function Sidebar() { ))} - - - - + {/* Auf schmalen Bildschirmen wird die Leiste waagerecht; dort gibt es + keine Abschnitte (styles.css) und die Eintraege stehen flach + nebeneinander – zuklappen loest dort kein Platzproblem. */} + + {LISTEN.map((e) => ( + [ + "nav-link nav-child", + isActive ? "active" : "", + // Nicht ausgehaengt, nur verborgen: auf schmalen Bildschirmen + // blendet die CSS sie wieder ein, dort gibt es keine Gruppe. + listenOffen || aufEinerListe ? "" : "nav-zu", + ].filter(Boolean).join(" ")}> + + {e.label} + + ))} diff --git a/web/src/styles.css b/web/src/styles.css index 0ae2dab..7c726ba 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -1036,6 +1036,15 @@ select.zeitraum:hover { color: var(--text); } .sidebar-brand { padding: var(--sp-3) var(--sp-4); } .sidebar-nav { flex-direction: row; overflow-x: auto; padding: var(--sp-2) var(--sp-3); gap: var(--sp-1); } .nav-section { display: none; } + /* Waagerechte Leiste: Zuklappen loest hier kein Platzproblem, und + untereinander ist ohnehin kein Platz. Die Gruppe verschwindet, ihre + Eintraege stehen flach zwischen den anderen – wie vorher. + Mit `.sidebar` davor, weil die Grundregeln weiter unten in der Datei + stehen: ein Media-Query erhoeht die Spezifitaet nicht, und bei + Gleichstand gewinnt die spaetere Regel. */ + .sidebar .nav-group { display: none; } + .sidebar .nav-link.nav-zu { display: flex; } + .sidebar .nav-link.nav-child { padding-left: 8px; } .nav-link { white-space: nowrap; } .nav-link span.label { display: none; } .nav-link { padding: 8px; } @@ -1088,6 +1097,21 @@ select.zeitraum:hover { color: var(--text); } } .nav-link.sub.active { font-weight: 600; } +/* Zuklappbare Gruppe in der Seitenleiste: sieht aus wie eine + Abschnittsueberschrift, ist aber ein Knopf. */ +.nav-group { + display: flex; align-items: center; gap: var(--sp-2); + width: 100%; background: none; border: none; cursor: pointer; + padding: var(--sp-4) var(--sp-3) var(--sp-1); + font-size: 0.68rem; font-weight: 600; letter-spacing: 0.06em; + text-transform: uppercase; color: var(--muted); opacity: 0.7; + font-family: inherit; text-align: left; +} +.nav-group:hover { opacity: 1; } +/* Eingerueckt wie die Dashboard-Unterpunkte, aber mit Platz fuers Symbol. */ +.nav-link.nav-child { padding-left: 26px; font-size: 0.86rem; } +.nav-link.nav-zu { display: none; } + /* ---- Aktionskarten: Ein- und Auslagern ohne Seitenwechsel ---- */ .aktion-karte { gap: 10px; }