feat(ui): EYT-80 zentrale Basisdesign-v2-Tokens und deterministisches Kontrastgate - #96
Merged
Merged
Conversation
Reviewer's GuideDie PR zentralisiert die Basisdesign-v2-Farbrollen in Sequence diagram for built token verificationsequenceDiagram
participant Build as WebBuild
participant CSS as CanonicalCSS
participant Page as ProductPage
participant Browser as Chromium
participant Test as ShellSmoke
Build->>CSS: copy basisdesign-v2.css to dist
Build->>Page: bundle globals.css and resolve CSS export
Page->>Browser: serve /, /planung, or /kosten
Browser->>Browser: read custom properties and assign probe color
Browser-->>Test: return parsed and computed RGB values
Test->>Test: compare canonical token colors
Flow diagram for deterministic contrast gatingflowchart TD
CSS[Read canonical token CSS]
PARSE[Parse light and dark declarations]
PAIRS[Evaluate enumerated normal-text pairs]
WCAG[Compute WCAG relative luminance and ratio]
GATE{Ratio >= 4.5:1?}
PASS[Tests pass]
FAIL[Tests fail]
CSS --> PARSE --> PAIRS --> WCAG --> GATE
GATE -->|yes| PASS
GATE -->|no| FAIL
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
DYAI2025
force-pushed
the
feat/eyt-80-basisdesign-tokens
branch
from
August 27, 2026 19:07
6df734c to
08fed37
Compare
…lossen PO-Review PR #96 wies drei Umgehungswege in den NEUEN Waechtern nach; alle drei sind vor der Reparatur als gruen reproduziert und danach als rot belegt: 1. packages/ui: Die Teilung am ersten @media war strukturell unsicher — ein spaeter :root-Block NACH dem Dunkelblock ueberschreibt im echten Browser den Hellmodus, landete im Test aber im DUNKEL-Abschnitt und blieb gruen. Jetzt zerlegt ein deterministischer Klammerzaehler die Datei vollstaendig: genau ein heller :root-Block, genau ein @media (prefers-color-scheme: dark)-Block mit genau einem inneren :root, sonst nichts; jede Abweichung (Zusatzblock, fremder Selektor, Nesting, Doppeldeklaration, Resttext) steht namentlich in STRUKTURFEHLER. 2. packages/ui: Die Deklarations-Regex war selektorblind — Dunkeltokens unter .dunkel statt :root blieben gruen, eine Streudeklaration unter fremdem Selektor wurde stumm Teil der Tokenkarte. HELL/DUNKEL entstehen jetzt NUR aus den beiden korrekt aufgehaengten :root-Koerpern. 3. apps/web: Das Farbliteral-Gate sah nur Hex — rgb()/hsl()/oklch()/ Farbnamen kamen durch. Drei Schichten ohne handgepflegte Farbnamensliste: Hex exakt die zwei Fokusfarben, die geschlossene Menge der CSS- Farbfunktionen verboten, und jedes nackte Wort eines Deklarationswerts gegen den jsdom-CSS-Parser als Farbwort geprueft (mit Selbsttest der Sonde: tomato rot, solid nicht). Zusaetzlich liefert shell-smoke jetzt auch --eyt-action-primary-contrast und --eyt-state-published-text im gebauten Chromium nach. Produkt-CSS unveraendert: packages/ui/src/basisdesign-v2.css und apps/web/app/globals.css sind byte-identisch zu 08fed37. Gegenmutationen ausgefuehrt (je: eingespielt, rot gemessen, revertiert): A spaeter :root-Override nach dem Dunkelblock; B Dunkeltokens unter .dunkel sowie Streudeklaration unter .hinweis; C rgb()-Fassung der verworfenen Penpot-Kombination #6D786F/#F0F4EF sowie Farbname tomato. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Worum es geht
packages/uibesitzt ab jetzt die semantischen Basisdesign-v2-Farbrollen.apps/web/app/globals.cssfuehrt keine eigene Palette mehr, sondern bindet die kanonische Datei mit einem einzigen
@importein. Dazu kommt ein deterministisches Kontrastgate fuer normalen Kleintext.EYT-80 Inkrement 2. Basis:
3f98d76(Merge von PR #95). EYT-80 bleibt „In Arbeit".Was sich geaendert hat und warum
packages/ui/src/basisdesign-v2.cssglobals.cssstand.packages/ui/package.json./basisdesign-v2.css;sideEffectsvonfalseauf["*.css"];buildkopiert die CSS-Datei nachdist(tsc tut das nicht).packages/ui/test/helpers/kontrast.tspackages/ui/test/basisdesign-tokens.test.tsapps/web/app/globals.css--eyt-*-Deklarationen entfernt,@importals erste Anweisung. Alle 58var(--eyt-…)-Verwendungen und jeder Selektor unveraendert.apps/web/test/basisdesign-tokens.test.tsapps/web/e2e/shell-smoke.spec.ts/,/planung,/kosten.Gewaehltes Eigentumsmodell — gemessen, nicht bevorzugt
A: kanonisches CSS in
packages/ui. Vor der Umsetzung als Spike gemessen und wiederzurueckgenommen:
@import "@easytree/ui/basisdesign-v2.css"ueber dieexports-Map auf und inlinedes (
@importim gebauten Chunk: 0).build-web) laeuft ebenfalls durch./,/planung,/kostenmit 200 und tragen dieselbe CSS-Datei.Verworfen:
apps/web. Die Literale blieben physisch inglobals.css; „keine eigene Palette" waere dann eine Ueberwachung statt einer Struktur.packages/ui. Heute gegenstandslos —packages/uienthaeltgemessen null Farbliterale, die Regel haette nichts zu fangen und das Paket besaesse weiter nichts.
Ausgefuehrte Gegenmutationen
Jede wurde eingespielt, gemessen und zurueckgenommen.
1. Drei Rollen verfaelscht (Task 2) — hell
--eyt-text-secondaryauf den von der Baselineverworfenen Penpot-Ton
#6d786f, dunkel--eyt-state-draft-textund--eyt-state-info-textaufihren Hellwert. Ergebnis: genau 7 rote Faelle, Verhaeltnisse 4.18 / 1.92 / 1.77 / 2.26 — exakt
die vorher gerechneten Zahlen.
Der Kern dabei:
hell: --eyt-text-secondary auf --eyt-bg-surfaceblieb gruen bei 4.60:1, waehrendderselbe Vordergrund auf
--eyt-bg-canvasrot wurde. Das Gate misst also das gerenderte Paar undverbietet nicht eine Zeichenkette.
2. Export-Unterpfad geloescht (Task 5) — Ergebnis: der Bau scheitert,
Module not found: Can't resolve '@easytree/ui/basisdesign-v2.css'. Das ist eine Zusage vonbuild-web, nicht von den drei Browserfaellen: die konnten gar nicht laufen, weil es keinen Bauzu bedienen gab. Diese Formulierung ist Absicht und soll nicht staerker gelesen werden.
3. Ausgelieferte CSS-Datei geleert (Task 5, nachgereicht) — die Mutation, die die Browserfaelle
wirklich trifft: Export loest auf, Bau gruen, aber 0 Deklarationen im Chunk (58 Verwendungen
bleiben). Ergebnis: genau die drei neuen Faelle rot (
--eyt-bg-canvas ist nicht deklariert,Received: ""), die uebrigen 24 gruen.Bemerkenswert: beide Dateiwaechter UND alle vier axe-Faelle blieben dabei gruen. Eine vollstaendig
ungestylte Anwendung besteht axe. Genau dafuer gibt es die drei Browserfaelle.
4.
@importausglobals.cssentfernt (Task 4) — derapps/web-Waechter wird rot, genau einFall.
Ein Befund, den erst der Browser gezeigt hat
Der Produktions-Minifier kuerzt
#ffffffzu#fff, undgetComputedStylenormalisiert den Werteiner Custom Property nicht (bis zur Verwendung ist sie ein beliebiges Token). Ein
Zeichenkettenvergleich haette hier den Minifier geprueft, nicht die Farbe.
Betroffen sind nur die sechsstelligen Hexwerte, die sich auf drei kuerzen lassen —
--eyt-bg-surfaceund--eyt-action-primary-contrast; die uebrigen elf Rollen ueberleben bytegleich.Der Browserfall vergleicht deshalb die Farbe: der rohe Wert wird einer Sonde als
colorzugewiesen und von Chromium als
rgb(…)zurueckgelesen. Das ist unabhaengig von Schreibweise undMinifier. Ein zusaetzliches Flag prueft, dass der CSS-Parser den Wert ueberhaupt angenommen hat —
sonst haette eine fehlende Rolle die geerbte Farbe der Sonde gemessen und koennte zufaellig gruen sein.
Beide Dateiwaechter behaupten weiterhin
#ffffffund sind gruen. Sie lesen die Quelle, der Browserliest das Bauergebnis — dazwischen sitzt der Minifier.
Eine beabsichtigte sichtbare Aenderung
.eyt-table__captionbenutztevar(--eyt-color-text-muted, #555). Dieses Token ist nirgendsdeklariert, gerendert wurde also
#555— in beiden Modi. Jetztvar(--eyt-text-secondary), also#5b564ehell und#b0aaa0dunkel. Die Dunkelmodusseite ist damit auch eineBarrierefreiheitsverbesserung, nicht nur ein Farbwechsel.
Sonst aendert sich keine gerenderte Farbe: die 30 verschobenen Werte sind bytegleich, und der
komplette Selektorbestand von
globals.cssist vorher/nachher identisch.Befunde, die dieser Slice bewusst NICHT behebt
apps/web/app/layout.tsxsetztthemeColor: "#166534"— ein Farbliteral in keiner Tokenrolle undungleich
action.primary(#1e5231)..eyt-table__captiontraegt weitervar(--eyt-space-2, 0.5rem)— dasselbe Muster wie das geradebehobene
#555, aber ein Abstandstoken und damit ausserhalb dieses Schnitts.--color-focus(#1d4ed8/#7cc1db) bleibt anwendungseigen: §2.1 kennt keine Fokusfarbe.apps/api/test/architecture/scan.tssind unberuehrt (ausdruecklich ausserhalb).Grenzen der Evidenz
colorScheme: light; dieDunkelwerte haengen an der Quelltextpruefung in
packages/ui.Ausfuehrungsnachweis, kein Beweis.
state.published.textfolgtaction.primary) hat keine Gegenmutation.--eyt-action-primary-contrastund--eyt-state-published-textstehen nicht in derBrowsertabelle — bewusst, sie haengen an den Dateiwaechtern.
color-contrastbleibt inapps/web/test/a11y.test.tsxabgeschaltet. jsdom hat keineLayoutmaschine; dieser Slice ersetzt die Luecke durch eine deterministische Rechnung, statt so zu
tun, als koenne axe sie schliessen. Nicht als „Kontrast vollstaendig durch axe geprueft" lesen.
9.13:1 dunkel, aber nichts haelt das fest.
sideEffects: ["*.css"]ist nicht isoliert als notwendig nachgewiesen. Der Spike lief damit;ob
falseauch gereicht haette, ist ungeprueft.Akzeptanzkriterien
EYT-80 — „Tokens fuer Canvas, Surface, Text, Border, Primary, Published, Draft, Danger und Info
sind zentral versioniert": erfuellt durch
packages/ui/src/basisdesign-v2.cssals alleinige Quelle,abgesichert gegen die Confluence-Tabelle.
EYT-80 — „Kontrasttests verhindern die verworfenen Penpot-Kombinationen
#6D786F/#F0F4EFund#A86B2B/#F6E9D8fuer normalen Kleintext": erfuellt. Zusaetzlich reproduziert die Rechnung die inder Baseline genannten Verhaeltnisse (4,14 und 3,66) — das ist die Gegenprobe fuer die Formel selbst.
EYT-12 — „Kontrasttests sichern die semantischen Hell-/Dunkel-Tokens aus EYT-80 ab": erfuellt fuer
die 24 aufgezaehlten Normaltextpaare in beiden Modi.
Nicht beruehrt (weiter offen an EYT-80):
BottomNavigation, die ZustandsfamilieForbidden/Unauthenticated/Stale/Partial, die Mitarbeiter-Shell, visuelle Regressionen aus realen
Produktseiten.
Historienreparatur 27.08.2026
Der Branch wurde von
3f98d76neu aufgebaut. Der Ausfuehrungsplandocs/plans/2026-08-27-eyt-80-inkrement-2-basisdesign-tokens.mdwar abgeleitetes,nichtkanonisches Arbeitsmaterial und ist weder im Endbaum noch in der Ahnenreihe dieses
Branches enthalten; ein spaeteres
git rmhaette ihn ueber die Historie erreichbar gelassen.Die sieben Produkt- und Testdateien sind bytegleich zum zuvor gereviewten Stand
6df734c(Blobvergleich je Datei: sieben gleich, null Abweichungen). Es wurde kein Produktcode geaendert.
Der Baumvergleich alt gegen neu zeigt genau eine Aenderung: die Loeschung des Plandokuments.
Neuer Kopf:
08fed37906db2d7b67ca2044b8d93290b4655208· CI-Lauf:33106872669(11/11 gruen).Der Abschnitt „Summary by Sourcery" stammt aus dem Lauf gegen den alten Kopf
6df734cundbeschreibt denselben Produktstand; sein Punkt „Documentation" ist entfallen, weil der Diff kein
Dokument mehr enthaelt. Diese PR-Beschreibung fuehrt kein automatisches Review als Nachweis.
Kein Deploy, kein Merge
BLOCKER_ENVIRONMENT_SEPARATIONist unberuehrt. Es wurde nichts deployt und nichts gemergt.EYT-80 bleibt In Arbeit.
Summary by Sourcery
Zentralisiere die Basisdesign-v2-Farbrollen in
packages/uiund sichere ihre Verwendung sowie Auslieferung mit deterministischen Kontrast- und Browserprüfungen ab.New Features:
packages/uiund stelle sie als importierbare CSS-Ressource bereit.Bug Fixes:
Enhancements:
apps/webund binde stattdessen die kanonische UI-Tokenquelle ein.Build:
distverfügbar ist.Tests:
/,/planungund/kosten.Guard-Härtung (PO-Review, 27.08.2026)
Alter reviewter Head:
08fed37906db2d7b67ca2044b8d93290b4655208· Neuer Head:75e7840b57140946785a181de3be8b8df36d9d74. Produkt-CSS und Tokenwerte unverändert —packages/ui/src/basisdesign-v2.cssundapps/web/app/globals.csssind byte-identisch zum alten Head; geändert sind ausschließlich die drei Wächterdateien.Drei Falschgrün-Klassen, jede vor der Reparatur als grün reproduziert und danach per ausgeführter Gegenmutation als rot belegt (eingespielt → rot gemessen → revertiert):
@mediawar strukturell unsicher (packages/ui/test/basisdesign-tokens.test.ts): ein später:root-Block NACH dem Dunkelblock überschreibt im echten Browser den Hellmodus, landete im Test aber im DUNKEL-Abschnitt — 46/46 grün. Jetzt zerlegt ein deterministischer Klammerzähler (kein CSS-Parser als Abhängigkeit) die Datei vollständig: genau ein heller:root-Block, dann genau ein@media (prefers-color-scheme: dark)-Block mit genau einem inneren:root, sonst nichts; Reihenfolge hell → dunkel mitbewacht. Gegenmutation A (später:root-Override von--eyt-action-primary-contrast) → rot: „3 Top-Level-Bloecke statt 2“..dunkelstatt:rootblieben 46/46 grün; eine Streudeklaration unter fremdem Selektor wurde stumm Teil der Tokenkarte.HELL/DUNKELentstehen jetzt nur aus den beiden korrekt aufgehängten:root-Körpern. Gegenmutationen B (.dunkel) → rot „der Medienblock traegt 1 innere Bloecke (.dunkel) statt genau einem :root“ (29 Tests rot); B2 (Streudeklaration unter.hinweis, gleicher Wert) → vorher stumm absorbiert, jetzt rot mit Blocknamen.apps/web/test/basisdesign-tokens.test.ts):rgb()/hsl()/oklch()/Farbnamen kamen durch. Drei Schichten ohne handgepflegte ~148er-Farbnamensliste: Hex exakt die zwei Fokusfarben; geschlossene Menge der CSS-Farbfunktionen verboten; jedes nackte Wort eines Deklarationswerts gegen den jsdom-CSS-Parser als Farbwort geprüft (Sonden-Selbsttest:tomatoerkannt,solidnicht;var()-Fallbacks bleiben sichtbar). Gegenmutation C (rgb(109, 120, 111)/rgb(240, 244, 239)— die verworfene Penpot-Kombination#6D786F/#F0F4EF) → rot mit beiden Werten; Zusatzmutation Farbnametomato→ rot.Zusätzlich misst
shell-smokejetzt auch--eyt-action-primary-contrastund--eyt-state-published-textim gebauten Chromium (15 statt 13 Rollen auf/,/planung,/kosten).Exakt-Head-CI auf
75e7840: siehe Checks dieses PR (alle elf Pflicht-Jobs).