Skip to content

fix(dashboard): KPI-Kachel-Layout — Einheit-Umbruch, Grundlinien-Versatz, Sub-Label-Ellipsis#217

Merged
TillQuandel merged 1 commit into
masterfrom
fix/213-kpi-layout
Jul 12, 2026
Merged

fix(dashboard): KPI-Kachel-Layout — Einheit-Umbruch, Grundlinien-Versatz, Sub-Label-Ellipsis#217
TillQuandel merged 1 commit into
masterfrom
fix/213-kpi-layout

Conversation

@TillQuandel

@TillQuandel TillQuandel commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Die 3 Probleme

  1. Einheit-Überlauf: Breite Werte (z.B. 100,0 bei n=1 oder echten 100%-Läufen) liefen mit ihrem %-Zeichen aus der Kachel in die Nachbar-Kachel — die vw-basierte clamp()-Schriftgröße war auf typische 2-stellige Werte getunt, nicht auf 3-stellige.
  2. Grundlinien-Versatz in der Qualitäts-KPI-Reihe: Das Label „AUTOMATISCH AKZEPTIERT" ist mit 22 Zeichen länger als „FEHLERQUOTE"/„BELEGRATE" und bricht — besonders mit Delta-Chip — zweizeilig um. Da der Großwert direkt unter dem Label sitzt, schob das nur die eigene Wert-Zeile nach unten; die Kachel-Reihe verlor ihre gemeinsame Grundlinie.
  3. Sub-Label-Ellipsis: Die VERSIONEN-Kachel schnitt ihr Sub-Label (v0.1.0–v0.3.140) bei exakt 1200px per text-overflow:ellipsis ab — bei 900px (4-Spalten-Reflow) und 1440px war genug Platz.

Identifikationsweg Problem 2

Zunächst vermutet: der Delta-Chip verdrängt den Großwert. Per Playwright-Messung widerlegt — der eigentliche Auslöser ist der Label-Zeilenumbruch selbst (Chip macht es nur wahrscheinlicher, da er zusätzlichen horizontalen Platz beansprucht). Nachweis: .top's Höhe unterscheidet sich zwischen 1-zeiligen und 2-zeiligen Labels um ~15px, was 1:1 den gemessenen value-row-Versatz erklärt.

Fix pro Problem

  1. .kpi bekommt container-type: inline-size; .v/.u (Wert + Einheit) skalieren per cqw (Container-relative Einheit) statt vw — Schriftgröße richtet sich nach der tatsächlichen Kachel-Breite, nicht der Viewport-Breite. white-space: nowrap auf .value-row zusätzlich als Schutz.
  2. .kpi .top bekommt min-height: 30px — fester Zwei-Zeilen-Slot für das Label, unabhängig davon ob es ein- oder zweizeilig rendert. Kein Label-Text wurde geschrumpft.
  3. .strip .cell .sub verliert white-space:nowrap; overflow:hidden; text-overflow:ellipsis — Inhalt bricht bei Platzmangel um statt abgeschnitten zu werden (bei allen 3 Breiten vollständig lesbar).

RED-Beweis (vor dem Fix, Playwright + Firefox)

[FAIL] value-row einzeilig, kein Ueberlauf in Nachbar-Kachel (forcierter Breitwert 100,0 % + n-Tag + Delta-Chip) -- sameLine=true, overflowPx=21.20px
[FAIL] Grundlinie: value-row-Oberkanten aller KPI-Kacheln < 2px Differenz -- maxDiff=15.00px
[FAIL] VERSIONEN-Sub-Label vollstaendig lesbar @w1200 -- scrollWidth=89, clientWidth=86, text="v0.1.0–v0.3.140"

Repro für Check 1 (dokumentiert): #kpi-accept .v/.u per JS auf "100,0"/"%" gesetzt, n-Tag (n=1) + Delta-Chip ↓ 17,2 sichergestellt — reproduziert den in #213 belegten Screenshot-Zustand (C:/tmp/v211-final.png) programmatisch.

GRÜN nach dem Fix

[PASS] value-row einzeilig, kein Ueberlauf in Nachbar-Kachel -- overflowPx=-52.20px
[PASS] Grundlinie: value-row-Oberkanten aller KPI-Kacheln < 2px Differenz -- maxDiff=0.00px
[PASS] VERSIONEN-Sub-Label vollstaendig lesbar @w1440/w1200/w900

Zusätzlich manuell verifiziert: Klick-Drilldown auf KPI-Kachel öffnet weiterhin korrekt den Versions-Trend-Spark, Theme-Tristate (System/Hell/Dunkel) funktioniert unverändert.

Screenshots (Vorher/Nachher, hell+dunkel × 1440/1200/900)

  • Vorher: C:/tmp/sweep-213/ (u.a. section-overview-hell-w1440.png, kpi-row-dunkel-clip.png, overview-hell-w1200.png vs. overview-hell-w900.png, Referenz C:/tmp/v204-kpi-row.png, Repro C:/tmp/v211-final.png)
  • Nachher: C:/tmp/verify-213/ (overview-{hell,dunkel}-w{1440,1200,900}.png, kpi-row-{hell,dunkel}-clip.png, post2-1-forced-value-row-kpiclip.png = geforcter 100,0%-Fall, post2-3-versions-w1200.png = Sub-Label jetzt zweizeilig statt abgeschnitten)

Suite / Lint

  • pytest generative lib/decision_engine/tests shared/tests -q: 5693 passed, 3 skipped, 4 deselected (unverändert ggü. vor dem Fix — reine CSS-Änderung ohne Python-Berührung)
  • ruff format --check .: 246 files already formatted
  • ruff check .: All checks passed

Cross-Model-Review (Mistral magistral-medium-latest)

Ergebnis: Änderungen als „insgesamt sicher und zielgerichtet" bewertet, keine Blocker. 4 Funde, alle low/medium, selbst verifiziert:

  • Container-Queries-Browserkompatibilität (medium, laut Mistral): container-type/cqw brauchen Chrome 105+/Firefox 110+/Safari 16+ (seit 2023 verfügbar). Verifiziert: internal/dashboard/eval_dashboard.html ist ein internes Maintainer-Tool (Gegenstück zur externen GUI unter gui/app.py; Einordnung via README/Erst-Lauf-Vertrauensbruch: jeder Run (auch --dry-run) mutiert config.py + startet undokumentierten Server :8051 #156 — ein expliziter Kommentar dazu in eval_dashboard_server.py existiert entgegen der ursprünglichen Formulierung hier nicht), kein Bestandteil des an Studierende ausgelieferten Produkts (AGENTS.md „Für wen") — läuft nachweislich in der getesteten Firefox-Build. Kein Fix nötig.
  • 3× low severity (Label >2 Zeilen, sehr lange Sub-Labels, extrem lange Werte) — theoretische Edge-Cases außerhalb der tatsächlichen Datendomäne (7 feste KPI-Labels, Prozent-/Token-/Kosten-Werte). Kein Fix nötig.

Keine „korrigierter Code"-Vorschläge im Review — nichts zu verwerfen.

Closes #213

TillQuandel pushed a commit that referenced this pull request Jul 12, 2026
…nden-Randfaelle (#204 Nachbesserung)

Externes Review (Fable + Qwen) an PR #221 fand 5 Nachbesserungspunkte:

1. loadAndRender(): catch-Block entfernte .refreshing bisher unbedingt,
   obwohl der Erfolgspfad per seq-Guard vor Stale-Renders schuetzt — bei
   ueberlappenden Requests (schneller Filterwechsel) riss ein fehlschlagender
   AELTERER Request die Dimmung fuer einen noch laufenden NEUEREN weg.
   Entfernung jetzt an denselben seq-Guard gebunden.
2. Refresh-Dimmung (pointer-events:none auf .main) sperrte kurzzeitig auch
   die Filterbar beim automatischen 15s-Poll. loadAndRender(manual=true)
   -Parameter; Poll ruft loadAndRender(false) — dimmt nur bei manuellem
   Filterwechsel.
3. ch8-Achse erzeugte bei kleinen Datenstaenden (kumulierte Laufzeit <60s,
   Onboarding-Szenario) fraktionale Ticks mit voller Float-Praezision.
   ticks.precision:1 + Ausgabe ueber bestehendes _fmtDE (Komma, 1 Dezimale).
4. ch3-Legende gruppierte schon ab >5 Keys statt wie Vorbild ch2 ab >6
   (t.enc.length) — bei exakt 6 PDFs erschien unnoetig "Weitere (1 PDFs)"
   inkl. Singular-Fehler. Schwelle angeglichen, Label pluralisiert korrekt.
5. renderKpis: bei gleichzeitigem n<20 UND abweichender Stichprobenbasis
   erklaerte der title nur die n<20-Bedeutung, der Asterisk blieb
   unerklaert. title kombiniert jetzt beide Bedeutungen.

Test-Assertion in test_dashboard_quick_wins.py an den neuen
setInterval(() => loadAndRender(false), 15000)-Aufruf angepasst.

PR-Body von PR #221 korrigiert: "#217 keine Ueberschneidung" war falsch
(.kpi.no-spark kollidiert mit #217s mehrzeiligem .top-Block), #219-Konflikt-
liste war unvollstaendig (renderStrip-cell()-Aufrufe fehlten, Tokens-Zelle).

Suite: pytest generative lib/decision_engine/tests shared/tests -q
-> 5695 passed, 3 skipped, 4 deselected, 0 failed. ruff format/check clean.
@TillQuandel TillQuandel merged commit 11646a6 into master Jul 12, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard: zwei visuelle Probleme — KPI-Wert bricht um (%-Einheit eigene Zeile); zweites Problem zu identifizieren

2 participants