Phase 5: App-Shell mit responsivem Layout, Navigation und Theme

Zwei Layouts aus derselben Zusammensetzung: unter 1000px Tab-Leiste unten,
darueber Seitenleiste links mit Brotkrume statt Zurueck-Pfeil. Navigation
ist wie im alten Panel ein flacher Zustand mit fester ZURUECK-Tabelle statt
eines Router-Pakets - die Verschachtelung ist hoechstens dreistufig.

Theme und Tab-Beschriftung ueberleben einen Neustart (localStorage,
abgesichert fuer den Privatmodus), Startwert folgt der Systemeinstellung.
Symbole aus dem alten Panel uebernommen, damit App und Panel gleich aussehen.

Neun Rendertests belegen die Abnahmekriterien: Layoutwechsel in beide
Richtungen, Zurueck-Ziel ueber die Tabelle, Zahnrad statt Tab-Leiste fuer
die Einstellungen, Theme-Persistenz.
This commit is contained in:
Paul Nothaft
2026-08-11 10:55:10 +02:00
parent 2fe3576682
commit 5c0c2d1898
14 changed files with 1616 additions and 12 deletions
+27 -11
View File
@@ -1,19 +1,35 @@
import { Tile } from "@audi-dash/ui"
import { useCallback, useState } from "react"
import { Shell } from "./Shell"
import type { Route, SeitenName } from "./navigation"
import { useTabBeschriftung, useTheme } from "./theme"
import { Platzhalter } from "./screens/Platzhalter"
import "./stile/rahmen.css"
/**
* Vorläufiger Einstieg — wird in Phase 5 durch die App-Shell ersetzt.
* Das äußerste Element trägt immer `ads-root` und `data-theme`, sonst greifen
* die Design-Tokens nicht (siehe design-system/.design-sync/conventions.md).
* Wurzel der App. Hält den Navigationszustand und das Theme; alles Weitere
* hängt darunter. Das äußerste Element trägt `ads-root` und `data-theme`
* ohne diese Wurzelklasse greifen die Design-Tokens nicht
* (design-system/.design-sync/conventions.md).
*/
export function App() {
const [route, setzeRoute] = useState<Route>({ name: "home" })
const [theme] = useTheme()
const [tabBeschriftung] = useTabBeschriftung()
const geheZu = useCallback((name: SeitenName, id?: string) => {
setzeRoute(id === undefined ? { name } : { name, id })
// Beim Seitenwechsel immer oben anfangen — sonst erbt die neue Seite die
// Scrollposition der alten.
document.querySelector(".dm-inhalt")?.scrollTo({ top: 0 })
}, [])
return (
<div className="ads-root dm-wurzel" data-theme="nacht">
<div className="dm-scroll" style={{ flex: 1, padding: 22 }}>
<span className="ads-eyebrow">DataMetric360</span>
<Tile>
<div style={{ fontWeight: 300, fontSize: 20 }}>Gerüst steht</div>
</Tile>
</div>
<div className="ads-root dm-wurzel" data-theme={theme}>
<Shell route={route} geheZu={geheZu} tabBeschriftung={tabBeschriftung}>
<Platzhalter route={route} geheZu={geheZu} />
</Shell>
</div>
)
}