feat(ui): EYT-80 Werkbank-Foundation — domaenenfreier AppShell und DateRangeControl auf /planung - #95
Merged
Merged
Conversation
…fraeumen nachziehen
…Luecken
Acht Befunde aus zwei Reviewrunden, jeder mit ausgefuehrter Gegenmutation.
F1 Emitterseite: `.eyt-app-shell__footer` war von nichts gehalten — sie
umzubenennen liess packages/ui bei 3/31 und apps/web bei 30/376. Ein Fall in
`packages/ui/test/app-shell.test.tsx` prueft jetzt alle SECHS Klassennamen.
F2 Stylesheetseite: `toContain(".eyt-app-shell__brand")` war von
`.eyt-app-shell__brandX` erfuellt; die Sprunganker-Pruefung las ueber
`.exec(...)` nur den ERSTEN Block und uebersah einen angehaengten
Ueberschreiber. Jetzt grenzgebundene Regelsuche auf kommentarfreiem CSS und
Auswertung ALLER Bloecke ueber die zuletzt gewinnende Deklaration.
F3 Die Messangabe im shell-smoke-Kommentar war um eins daneben (vier
Fokussonden, nicht drei) und das Kommando ohne `-E` unbrauchbar.
F4 Der Kommentar zu `css.length > 1000` nannte einen unmoeglichen Fehlerfall —
ein falscher Pfad wirft ENOENT auf Modulebene. Auf das echte Risiko gefasst.
F5 „Kopfleiste ist EINE Zeile" pruefte nur ein Links/Rechts-Verhaeltnis und
blieb bei dreizeiligem Umbruch gruen. Zusicherung auf gleiche vertikale Mitte
ergaenzt (Mutation: Marke=31, Anmelden=122, Kopfhoehe=159).
F6 Der Beruehrziel-Fall misst nur `.app-login-link`; `.app-logout` wird in
`web-smoke` nie gerendert. Kommentar darauf eingegrenzt, Fall umbenannt.
F7 Ein Fall verglich zwei Werte, die das Primitive aus EINER Variablen
rendert — bauartbedingt wahr, ersatzlos entfallen. Die beiden verbleibenden
tragen jetzt ihre benannte Gegenmutation.
F8 `sessionArea` als benannter Wert vor dem `return` statt als 38-zeiliger
Ausdruck an der Prop; Verhalten unveraendert.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…-Element Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Die Darstellung der Bedienleiste liegt jetzt im domaenenfreien Primitive;
was hier bleibt, ist die Uebersetzung des Wochenmodells in dessen Props —
Beschriftungen, die sechs `data-testid`-Werte und der Link-Adapter. Es kommt
keine Rechnung dazu und es faellt keine weg: jeder Wert ist ein Literal oder
ein direkter Feldzugriff auf `modell`.
Der Adapter `WochenLink` statt `linkComponent={Link}` direkt, weil
`next/link` mit `href: Url` weiter ist als der Vertrag `DateRangeLinkProps`
mit `href: string` — die direkte Zuweisung waere eine Wette auf die Varianz
der Prop-Typen, die sich erst im typecheck zeigt.
Ein Boolean speist zwei Knoepfe: `modell.istAktuelleWoche` setzt sowohl
`currentMarker` als auch `reset.current`, im Primitive zwei getrennte
Eingaenge. Beide Haelften sichert der unveraenderte Abnahmevertrag in
derselben Zusicherung.
CSS: fuenf Selektoren `.wochennavigation*` -> `.eyt-date-range*`, inklusive
`min-height: 2.5rem` auf `.eyt-date-range__action`. Danach 0 Treffer fuer
`wochennavigation` in globals.css.
Beide Haelften der Namenskopplung sind bewacht, jede mit ausgefuehrter
Gegenmutation (Umbenennung `__marker` -> `__markerX`):
- Stylesheetseite, KLASSEN in `app-shell-styles.test.ts` von sechs auf elf:
Mutation in globals.css macht apps/web rot (1 failed | 12 passed) und
packages/ui bleibt gruen (13 passed).
- Emitterseite, `date-range-control.test.tsx` nannte bereits alle sieben
Klassen und blieb unveraendert: Mutation im Primitive plus Neubau macht
packages/ui rot (1 failed | 12 passed) und apps/web bleibt gruen
(13 passed).
Neu vermessen wird auch die Geometrie: `min-height: 2.5rem` auf den
Wochenwegen hielt bisher nichts fest — die vier Geometriefaelle in
shell-smoke besuchen alle `/`, wo es keine Wochenleiste gibt. Ein Fall auf
`/planung?weekKey=2026-W32` prueft die Hoehe von "Naechste Woche"; die
ausgefuehrte Gegenmutation (Zeile entfernen, neu bauen) misst 24 px.
Zahlen nach der Aenderung: apps/web 30 Dateien / 380 Tests (+5 durch die
fuenf neuen KLASSEN-Eintraege), packages/ui 4 / 45 unveraendert,
architecture `files=339 imports=1353 modules=5 rules=10 violations=0` bei 29
Tests, shell-smoke 20 passed (vorher 19), planungswerkbank 4 passed.
`apps/web/test/wochen-navigation.test.tsx`, `test/wochennavigation.test.tsx`,
`lib/wochennavigation.ts` und `packages/ui/src` sind unveraendert (leerer
`git diff`).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reviewer's GuideExtracts a reusable, domain-free AppShell and DateRangeControl into @easytree/ui, adapts the real /planung route without changing week-navigation behavior or application policy, and backs the architectural boundary with allowlist enforcement plus focused unit, accessibility, stylesheet, and browser-layout tests. Sequence diagram for adapting /planung to DateRangeControlsequenceDiagram
participant Route as /planung
participant Navigation as WochenNavigation
participant Model as wochennavigation.ts
participant Control as DateRangeControl
participant NextLinkParticipant as NextLink
Route->>Model: build Wochenmodell
Model-->>Navigation: return URLs and labels
Navigation->>Control: render DateRangeControl
Navigation->>NextLinkParticipant: provide WochenLink adapter
Control->>NextLinkParticipant: render previous/reset/next hrefs
NextLinkParticipant-->>Route: navigate to supplied URL
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
EYT-80 Increment 1 — die Werkbank-Grundlage aus Basisdesign v2.0 als domaenenfreie Bausteine in
@easytree/ui, bewiesen auf der echten Route/planung, ohne eine einzige Verhaltensaenderung.Basis:
9bebb1186ecc7e6c8338887f5831c1f31d79b1a9(Merge von #94), beim Abzweigen und erneut vor dem Push geprueft. Keine konkurrierende offene PR auf derselben Flaeche.Was entsteht
Zwei Primitives in
packages/ui, beide ohne Sitzung, Rechte, Router oder Fachbegriff:AppShell— Sprunganker, Kopfleiste, Hauptbereich, optionale Fusszeile.apps/web/components/app-shell.tsxkomponiert ihn jetzt und behaelt jede Politik:useSession, die Rechtefilterung ueberhatRecht, Organisationswahl, Abmelden,next/link,next/navigation.DateRangeControl— Bereichswechsel mit injiziertem Link-Element.apps/web/components/wochen-navigation.tsxkomponiert ihn und uebersetzt nur noch das Wochenmodell in Beschriftungen, Adressen unddata-testid-Werte.Die Wochenrechnung bleibt vollstaendig in
apps/web/lib/wochennavigation.ts(Europe/Berlin,@easytree/domain+@easytree/contracts). Das Primitive rechnet nichts — der Grund ist nicht Geschmack: eine zweite Wochenregel liefe genau an den Jahresgrenzen auseinander, an denenisoWeek ± 1falsch ist.apps/web/test/wochen-navigation.test.tsxundwochennavigation.test.tsxsind seitmasterbyte-identisch. Sie sind der Abnahmevertrag; haette der Umbau eine Zeile darin gebraucht, waere der Umbau falsch gewesen.Die Grenze ist ausfuehrbar, nicht behauptet
Vor diesem Slice stand „domaenenfrei" als Zusage in einem Dateikopf und sonst nirgends. Neu: die Regel
ui-dependency-allowlistim Pflichtjobunit-testslaesst unterpackages/ui/src/ausschliesslichreactund paketinterne relative Pfade zu — als Allowlist, weil ein universelles Verbot sich nicht durch eine endliche Sperrliste ausdruecken laesst.Dazu eine Zusicherung, die den Geltungsbereich festnagelt. Ohne sie liess sich der Waechter lautlos abruesten: eine Verengung auf
packages/ui/src/bbewachte 1 von 11 Dateien, und beide Suiten blieben vollstaendig gruen. Jetzt wird der Geltungsbereich bei jedem Lauf gegen die tatsaechlich eingesammelten Dateien verglichen.Ausgefuehrte Gegenmutationen
Jede wurde eingespielt, gemessen und zurueckgenommen — keine ist ausgedacht.
@easytree/domaininpackages/ui/src/button.tsxviolations=1, benennt Datei und Zeilenext/linkindate-range-control.tsxviolations=1mit der vollen Abhilfe im Textpackages/ui/src/bverengtmainIdexpected '#hauptinhalt' to be '#inhalt-feld'=== undefinedverengtnull/false-Faelle.eyt-app-shell__skip-link-Positionierung entferntSprunganker steht ohne Fokus im Bild (bottom=40)Bloecke ohne Pseudoklasse: 2hatRecht-Riegel entferntglobals.cssumbenanntexpected '/planung?weekKey=SENTINEL-SCHLUESSEL' to be '/x?k=SENTINEL-NACH'min-heightder Wochenschaltflaechen entferntNächste Woche ist 24 px hochmin-heightdes Sitzungszugangs entferntAnmelden ist 38 px hoch.app-nav-list { min-width: 1200px }Kopfleiste umbricht: Marke=31, Anmelden=122, Kopfhoehe=159Die beiden Slotwaechter-Mutationen klammern die Regel von beiden Seiten ein: zu eng faellt an den Abwesenheitsformen, zu weit am Leerstring. Nur die Drei-Formen-Fassung besteht beides.
Der Waechter fuer Klassennamen ist zweiseitig. Gemessen: eine Umbenennung von
eyt-app-shell__footerim Primitive liessapps/webbei 30 Dateien / 376 Tests undpackages/uibei 3 / 31 — identisch zum ungemuteten Lauf — waehrend die Fusszeile still Polsterung und Oberkante verlor. Jede Haelfte hat jetzt ihre eigene Gegenmutation, und jede roetet genau eine Haelfte.Barrierefreiheit
Fuenf Aussagen ueber Lage und Groesse, die es im Repository vorher gar nicht gab — die einzigen Geometriesonden waren vier Fokuspruefungen. Neu gemessen im echten Browser: Sprunganker ausserhalb des Bildes bis zum Fokus, Kopfleiste als eine Zeile mit rechtsstehendem Sitzungsbereich, begrenzte und mittige Hauptspalte, 40-px-Beruehrziele. Dazu unveraendert: axe auf vier Routen mit aktiviertem Kontrast, genau eine
main-Landmark, vollstaendiger Tab-Zyklus in DOM-Reihenfolge.Gates (lokal,
Cached: 0durchgehend)Die 95 Uebersprungenen sind die Tenant-/DB-Suiten im Modus
localohne Supabase-Stack.db-gatesin CI faehrt sierequired— das bleibt die hoehere Evidenzstufe. Keine Migration, kein Vertrag, keine RLS-, Rechte- oder Domainaenderung;package.jsonund Lockfile sind unveraendert.Was hier bewusst NICHT behauptet wird
Bewiesen ist: gewoehnliche Quelldateien unter
packages/ui/srcduerfen keine Domain, keine Vertraege und keinen Router importieren. Nicht bewiesen ist „packages/uiist nachweislich domaenenfrei". Sechs vorbestehende Luecken inapps/api/test/architecture/scan.tsunterlaufen alle zehn Regeln, nicht nur die neue — unter anderem wird/// <reference path=…>nie zu einemImportRef, ein praeparierter Kommentar verschluckt den naechsten Import,SKIP_DIRSgreift auf jeder Tiefe, und Symlinks untersrc/werden vom Walker verworfen, vontscaber mitgebaut. Alle acht Befunde sind gemessen und im Planungsdokument aufgelistet; keiner ist in dieser PR mitbehoben — sie brauchen je eine eigene Gegenmutation pro Regel.Offen bleibt ausserdem:
.app-logoutwird von keinem Job vermessen (web-smokelaeuft abgemeldet), und die drei Wochenschaltflaechen teilen sich eine Regel, von der nur „Nächste Woche" gemessen wird. Beides steht als Kommentar an der jeweiligen Zusicherung, nicht nur hier.Evidenzstufe
CI auf genau diesem Head ist gemessen. Lauf #361 (ID
33046937186), Head15de359939a27eee40fa793f5e55cbc4bbced7d5,status=completed,conclusion=success, 11 von 11 Jobs gruen —db-gatesundauth-journeyeingeschlossen, ebensoread-through.Die Zahlen im Abschnitt Gates daneben bleiben ein lokaler Lauf und damit die niedrigere Evidenzstufe.
Nicht Teil dieses Inkrements:
BottomNavigation, die Feld-Shell, EYT-113/81/82/147/148. Sie bekommen ihre Bausteine, wenn es eine echte konsumierende Flaeche gibt.Summary by Sourcery
Extract reusable, domain-free application-shell and date-range controls into the shared UI package while preserving planning-route behavior and enforcing their architectural boundaries.
New Features:
Bug Fixes:
Enhancements:
Tests: