Menue schiebt statt zu ueberlappen, Karte schmaler mit Seitenpfeilen, Zeitachse neu, Cash inline
Deploy App / deploy (push) Successful in 1m9s

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 22:07:44 +02:00
parent ff862ed030
commit 5842a84b20
5 changed files with 265 additions and 153 deletions
+21 -10
View File
@@ -113,10 +113,14 @@ function AppShellInner({ username }: { username: string }) {
// Erhoehen erzwingt ein Neuladen der Szenario-Liste (bleibt bei einer Loeschung montiert).
const [scenarioListKey, setScenarioListKey] = useState(0);
// Menueleiste links: eingeklappt auf eine Icon-Schiene (56 px) statt 256 px. Angepinnt
// bleibt sie breit und schiebt den Inhalt; nicht angepinnt faehrt sie beim Ueberfahren als
// Overlay aus und legt sich UEBER den Inhalt -- so kostet sie im Ruhezustand nichts.
// Die Wahl gehoert zum Benutzer, nicht zum Plan, und ueberlebt deshalb die Sitzung.
// Menueleiste links: eingeklappt auf eine Icon-Schiene (56 px) statt 240 px.
//
// Beim Ueberfahren faehrt sie aus und SCHIEBT den Inhalt -- sie legt sich nicht darueber.
// Der erste Anlauf (0.42) liess sie als Overlay ausfahren, um im Ruhezustand keinen Platz
// zu kosten; dabei verschwand aber jedes Mal ein Streifen des Inhalts, und das las sich wie
// ein Fehler. Aufgeklappt sieht es damit genau so aus wie angepinnt, und das Anpinnen
// entscheidet nur noch, ob es so BLEIBT. Die Wahl gehoert zum Benutzer und ueberlebt die
// Sitzung.
const [railPinned, setRailPinned] = useState(false);
const [railHover, setRailHover] = useState(false);
const [planMenuOpen, setPlanMenuOpen] = useState(false);
@@ -354,7 +358,7 @@ function AppShellInner({ username }: { username: string }) {
hat sich falsch angefuehlt. */}
<div
className="relative hidden shrink-0 lg:block"
style={{ width: railPinned ? "15rem" : "3.5rem" }}
style={{ width: railWide ? "15rem" : "3.5rem", transition: "width 200ms" }}
onMouseEnter={() => setRailHover(true)}
onMouseLeave={() => {
setRailHover(false);
@@ -1136,10 +1140,13 @@ function Rail({
className={`${
mobile ? "relative h-full w-full" : "absolute inset-y-0 left-0 z-40"
} flex flex-col overflow-hidden border-r border-border bg-surface transition-[width] duration-200 ${
mobile ? "" : wide ? "w-60 shadow-xl" : "w-14"
} ${pinned && !mobile ? "shadow-none" : ""}`}
mobile ? "" : wide ? "w-60" : "w-14"
}`}
>
<div className="flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto py-3">
{/* Klebt am oberen Bildschirmrand: Die Leiste ist so hoch wie die SEITE, und mit einer
aufgeklappten Karte wird die sehr lang -- ohne sticky waeren die Knoepfe nach ein
wenig Scrollen ausserhalb des Blickfelds. */}
<div className="sticky top-0 flex max-h-screen flex-col gap-0.5 overflow-y-auto py-3">
<RailRow wide={wide} icon={<PiggyBank className="h-[18px] w-[18px] text-accent-fg" />} iconBox="bg-accent" label="FPT" />
<div className="my-1 h-px w-6 self-center bg-border" />
@@ -1282,9 +1289,13 @@ function Rail({
onClick={onParams}
icon={<SlidersHorizontal className="h-[18px] w-[18px]" />}
/>
</div>
<div className="border-t border-border py-1.5">
{/* Suchen und Anpinnen stehen DIREKT hier, nicht am unteren Rand. Die Leiste ist so
hoch wie die Seite -- und mit einer aufgeklappten Karte wird die sehr lang. Am Fuss
waeren die beiden dann ausserhalb des Blickfelds, obwohl sie zu den am haeufigsten
gebrauchten Knoepfen gehoeren. */}
<div className="my-1 h-px w-6 self-center bg-border" />
<RailRow
wide={wide}
label="Suchen und springen (Ctrl+K)"