Skip to content

ui: Listen als PDF, Rücktaste löscht, Kopfzeile bricht nicht mehr um (#121–#124) - #125

Merged
larszu merged 2 commits into
mainfrom
claude/av-planner-market-research-39l0mv
Sep 13, 2026
Merged

larszu merged 2 commits into
mainfrom
claude/av-planner-market-research-39l0mv

Conversation

@larszu

@larszu larszu commented Sep 13, 2026

Copy link
Copy Markdown
Owner

Vier gemeldete Punkte, ein Durchgang.


#123 — Die Listen als PDF, gesetzt statt fotografiert

„Man muss Patchlisten und alle anderen, die man aktuell nur als CSV exportieren kann, auch als schön aufbereitete PDF exportieren können."

Neben utils/pdfExport.ts liegt jetzt utils/pdfTable.ts. Die alte kann auch PDF — aber
nur ein Bild je Seite (/DCTDecode). Das ist für den Plan richtig und für eine Liste
falsch: ein Bild einer Tabelle lässt sich nicht durchsuchen, nicht kopieren, und beim
Drucken wird aus scharfem Text ein Raster.

Courier und nicht Helvetica. Die Spaltenbreiten müssen vor dem Setzen feststehen. Bei
einer Proportionalschrift hieße das, die Breite jedes Zeichens zu kennen — eine AFM-Tabelle,
die hier niemand nachschlagen kann. Hätte sie einen falschen Wert, würde nichts scheitern;
die Spalten stünden nur schief, und niemand wüsste warum. Courier hat für jedes Zeichen
600/1000 em, damit ist die Spaltenbreite eine Frage der Zeichenzahl. Für Patch- und
Kabelblätter ist Festbreite ohnehin die übliche Form.

Neun Listen haben jetzt beide Wege — Geräteliste & Patch, Kabelliste, Stückliste,
Farbliste, Gruppenblatt, Bestellliste, Universe-Blatt, Kreisliste, Berichtsblatt. Beide gehen
durch dieselbe Tabellen-Funktion und denselben Stempel (ADR-004): zwei Wege wären zwei
Listen, und die eine, die jemand ausdruckt, wäre irgendwann nicht mehr die, die jemand
auswertet.

Der Wächter hat beim ersten Lauf gleich etwas gefunden: wurde als drei Punkte
ausgegeben, und damit wuchs jede gekürzte Zelle um zwei Zeichen — 167 auf einer Zeile, auf
die 161 passen
. WinAnsi führt das Zeichen bei 0x85; es steht jetzt als \205 da.

#122 — Die Rücktaste löscht

Hier stand nur Delete. Auf einer Mac-Tastatur ohne Zehnerblock gibt es diese Taste nicht;
wer die Rücktaste drückte, sah gar nichts. Sie löscht jetzt mit — mit preventDefault
(sonst blättert der Browser zurück, und die Antwort auf „löschen" wäre das Verlassen der
Seite) und mit der Eingabefeld-Abfrage davor, die jetzt auch contentEditable abdeckt.

#121 — „Auswahl und verschieben" steht nicht mehr in der Leiste

Das Werkzeug gibt es weiter — es ist der Ruhezustand der Fläche, und jeder Zweig in
PlanCanvas, der activeTool === 'select' prüft, bleibt. Was verschwindet, ist sein
Knopf: ein Werkzeug anzubieten, das ohnehin gilt, sobald man kein anderes gewählt hat,
macht aus dem Ruhezustand eine Entscheidung.

#124 — Kopfzeile und Lager-Knopf

Der „Lager"-Knopf saß als position: fixed mit zIndex: 150 unten links und lag damit
über der Zeichenfläche, über dem Dock und über allem, was dort sonst hätte stehen können. Er
steht jetzt unter Werkzeuge → Lager/Bestand.

Die Überlagerung von „2D Plan / 3D / Render" hatte eine Ursache im Raster: .topbar
stand auf 1fr auto 1fr, und 1fr ist minmax(auto, 1fr) — die äußeren Spalten durften
nicht unter ihren Inhalt schrumpfen. Wurde das Fenster schmal, blieb links Logo, Name,
Projektname und fünf Menütitel stehen, und der mittige Umschalter legte sich darüber.

Breite Was passiert
minmax(0, 1fr) erlaubt den äußeren Spalten überhaupt erst zu schrumpfen
< 1180 px der Projektname fällt weg
< 1060 px der Produktname fällt weg
< 980 px der Umschalter zeigt nur noch Sinnbilder (title + aria-label tragen den Text)
< 820 px die Menüleiste rollt — nur waagerecht: eine zweizeilige Kopfzeile schöbe die ganze Anwendung hinunter

Drei Knöpfe weniger rechts: Grundriss-Import, Geräteliste/Patch und Export standen dort
als Knopf und gleichzeitig im Menü — dieselbe Sache zweimal, auf der Seite, die mit dem
Umschalter um den Platz streitet. „Speichern" bleibt: der einzige Griff, den man mehrmals je
Sitzung braucht.


Wächter

scripts/pdf-table-check.ts (neu, sieben Punkte): es ist ein PDF · der Text steht drin statt
eines Bildes · 400 Zeilen ergeben 7 Seiten und die letzte Zeile ist dabei · keine Zeile
läuft über den Rand (gemessen an einer Tabelle mit 300-Zeichen-Zellen) · Klammern und
Gegenschrägstrich sind maskiert, Umlaute stehen als WinAnsi-Oktalfolge · der Stempel steht
auf dem Blatt · neun PDF-Wege in der Oberfläche, mindestens so viele wie CSV-Wege.

Im CI-Workflow verdrahtet; ci:complete zählt jetzt 42 Läufe.

NICHT gemessen: wie das Blatt aussieht. Der Lauf liest Bytes; ob die Spalten im Leser
angenehm stehen, sagt er nicht.

Nachgerechnet

  • eslint — 0 Fehler, Warnung für Warnung wie die Basis
  • tsc --noEmit — Exit 0 · npm run build — ohne Fehler
  • i18n:check — 916 erreichbare Schlüssel, alle mit deutscher Fassung · lang:check grün
  • brand · canvas · slider · kopfzeile · farben · zoom · docs · spec · actions · devport · stamp · identity — je grün

Closes #121, #122, #123, #124

🤖 Generated with Claude Code

https://claude.ai/code/session_016DYtHJAFkg4LUw7afKLMmT


Generated by Claude Code

…mehr um

Vier gemeldete Punkte, ein Durchgang.

#123 — DIE LISTEN ALS PDF, GESETZT STATT FOTOGRAFIERT

„Man muss Patchlisten und alle anderen, die man aktuell nur als CSV
exportieren kann, auch als schoen aufbereitete PDF exportieren koennen."

Neben `utils/pdfExport.ts` liegt jetzt `utils/pdfTable.ts`. Die alte kann
auch PDF, aber nur EIN Bild je Seite (/DCTDecode) — richtig fuer den
Plan, falsch fuer eine Liste: ein Bild einer Tabelle laesst sich nicht
durchsuchen, nicht kopieren, und beim Drucken wird aus scharfem Text ein
Raster.

Courier und nicht Helvetica: die Spaltenbreiten muessen VOR dem Setzen
feststehen. Bei einer Proportionalschrift hiesse das, die Breite jedes
Zeichens zu kennen — eine AFM-Tabelle, die hier niemand nachschlagen
kann. Haette sie einen falschen Wert, wuerde nichts scheitern; die
Spalten staenden nur schief, und niemand wuesste warum. Courier hat fuer
jedes Zeichen 600/1000 em, damit ist die Spaltenbreite eine Frage der
Zeichenzahl. Fuer Patch- und Kabelblaetter ist Festbreite ausserdem die
uebliche Form.

Neun Listen haben jetzt beide Wege, und beide gehen durch DIESELBE
Tabellen-Funktion und denselben Stempel (ADR-004). Zwei Wege waeren zwei
Listen — und die eine, die jemand ausdruckt, waere irgendwann nicht mehr
die, die jemand auswertet.

Der Waechter hat gleich etwas gefunden: „…" wurde als drei Punkte
ausgegeben, und damit wuchs jede gekuerzte Zelle um zwei Zeichen — 167
auf einer Zeile, auf die 161 passen. WinAnsi fuehrt das Zeichen bei 0x85;
es steht jetzt als \205 da.

#122 — DIE RUECKTASTE LOESCHT

Hier stand nur `Delete`. Auf einer Mac-Tastatur ohne Zehnerblock gibt es
diese Taste nicht; wer die Ruecktaste drueckte, sah gar nichts. Sie
loescht jetzt mit, mit `preventDefault` (sonst blaettert der Browser
zurueck — die Antwort auf „loeschen" waere das Verlassen der Seite) und
mit der Eingabefeld-Abfrage davor, die jetzt auch `contentEditable`
abdeckt.

#121 — „AUSWAHL UND VERSCHIEBEN" IST KEIN WERKZEUG MEHR IN DER LEISTE

Das Werkzeug GIBT ES WEITER — es ist der Ruhezustand der Flaeche, und
jeder Zweig in `PlanCanvas` bleibt. Was verschwindet, ist sein Knopf: ein
Werkzeug anzubieten, das ohnehin gilt, sobald man kein anderes gewaehlt
hat, macht aus dem Ruhezustand eine Entscheidung.

#124 — DIE KOPFZEILE UEBERLAGERT SICH NICHT MEHR, UND DAS LAGER IST EIN
MENUEPUNKT

Der „Lager"-Knopf sass als `position: fixed` mit `zIndex: 150` unten
links und lag damit ueber der Zeichenflaeche, ueber dem Dock und ueber
allem, was dort sonst haette stehen koennen. Er steht jetzt unter
Werkzeuge > Lager/Bestand.

Die Ueberlagerung von „2D Plan / 3D / Render" hatte eine Ursache im
Raster: `.topbar` stand auf `1fr auto 1fr`, und `1fr` ist
`minmax(auto, 1fr)` — die aeusseren Spalten durften NICHT unter ihren
Inhalt schrumpfen. Wurde das Fenster schmal, blieb links Logo, Name,
Projektname und fuenf Menuetitel stehen, und der mittige Umschalter legte
sich darueber. Jetzt `minmax(0, 1fr)` plus drei Stufen: unter 1180 px
faellt der Projektname, unter 1060 der Produktname, unter 980 zeigt der
Umschalter nur noch seine Sinnbilder (title und aria-label tragen den
Text weiter). Erst unter 820 px rollt die Menueleiste, und nur
waagerecht: eine zweizeilige Kopfzeile schoebe die ganze Anwendung
hinunter.

Und drei Knoepfe weniger rechts: Grundriss-Import, Geraeteliste/Patch und
Export standen dort ALS KNOPF und gleichzeitig IM MENUE — dieselbe Sache
zweimal, auf der Seite, die mit dem Umschalter um den Platz streitet.
„Speichern" bleibt: der einzige Griff, den man mehrmals je Sitzung
braucht.

WAECHTER

scripts/pdf-table-check.ts (neu, sieben Punkte): es ist ein PDF · der
Text steht drin statt eines Bildes · 400 Zeilen ergeben 7 Seiten und die
letzte Zeile ist dabei · keine Zeile laeuft ueber den Rand (gemessen an
einer Tabelle mit 300-Zeichen-Zellen) · Klammern und Gegenschraegstrich
sind maskiert, Umlaute stehen als WinAnsi-Oktalfolge · der Stempel steht
auf dem Blatt · neun PDF-Wege in der Oberflaeche, mindestens so viele wie
CSV-Wege. Im CI-Workflow verdrahtet; `ci:complete` zaehlt jetzt 42 Laeufe.

NICHT gemessen: wie das Blatt AUSSIEHT. Der Lauf liest Bytes; ob die
Spalten im Leser angenehm stehen, sagt er nicht.

Nachgerechnet: eslint 0 Fehler und Warnung fuer Warnung wie die Basis,
tsc --noEmit Exit 0, Build ohne Fehler, i18n:check 916 Schluessel mit
deutscher Fassung, lang:check gruen, dazu brand/canvas/slider/kopfzeile/
farben/zoom/docs/spec/actions/devport/stamp/identity je gruen.

Closes #121, #122, #123, #124
`ascii:check` hat den neuen Dateinamen beim ersten CI-Lauf gemeldet, und
das ist die richtige Beweislast: der Lauf kennt eine kurze Liste von
Ausgabe-Dateinamen, in denen „ae" kein Umlaut-Ersatz ist, sondern Teil
einer Kennung — ein Umlaut im Dateinamen laeuft ueber drei
Betriebssysteme unterschiedlich.

`geraeteliste.pdf` ist dieselbe Liste wie `geraeteliste.csv`, nur ein
anderes Format, und heisst deshalb gleich. Sie wird eingetragen, nicht
stillschweigend mitgenommen.

Alle 42 Pruef-Laeufe lokal gruen.
@larszu
larszu marked this pull request as ready for review September 13, 2026 02:10
@larszu
larszu merged commit 56d1eab into main Sep 13, 2026
1 check passed
larszu pushed a commit that referenced this pull request Sep 13, 2026
Sechs Befunde aus einer Messung im echten Browser (2026-09-13, Chromium
gegen den gebauten dist/, 390/768/1440 px; Sonde ist scripts/bedienbar.mjs
aus av-planner-suite, Backlog-Eintrag B-77). Vier davon sind Regresse aus
#124/#125 — sie sahen im Quelltext richtig aus und waren es im Layout
nicht.

1. KEIN MENUE GING MEHR AUF. #125 gab .tb-menubar ein `overflow: hidden`,
   damit die Kopfzeile nicht umbricht. Die Klappe ist ein absolute-Kind
   genau dieser Leiste — also schnitt dasselbe hidden sie mit ab. Gemessen
   bei 1440 px: Datei-Klappe 250 x 505 px gross, davon 250 x 0 px sichtbar.
   Dasselbe hidden verschluckte „Hilfe", den letzten Menuetitel.

   Die Klappe haengt jetzt am FENSTER (position: fixed, Koordinaten aus dem
   Rechteck des Titels, nach dem Einhaengen an den Rand geklemmt). Damit
   darf die Leiste rollen, klemmen oder schrumpfen, ohne dass das Menue
   etwas davon merkt. Sie bleibt ein Kind der Leiste und kein Portal — der
   Klick-daneben-Waechter prueft `contains`.

   Die Titel geben ausserdem als LETZTE nach (flex: none); zuerst
   schrumpft der Projektname, der dafuer schon ellipsis traegt.

2. DER @media-BLOCK AUS #124 HAT NIE GEWIRKT. Er stand VOR der Grundregel
   `.tb-modeswitch button { font-size: 13px }`. Gleiches Gewicht (0,1,1),
   und bei Gleichstand gewinnt die spaetere. Die Zusage „unter 980 px nur
   noch Sinnbilder" ist nie eingetreten: der 2D-Plan-Knopf war im
   390-px-Fenster 111 px breit statt 36. Der Block steht jetzt hinter den
   Grundregeln.

3. DIE APP PASSTE NICHT AUF EIN TELEFON. .app-body fuehrt vier Spalten
   (56 + 264 + Arbeitsflaeche + 308) — 628 px, bevor die Arbeitsflaeche
   ein Pixel bekommt. Bei 390 px ragten acht Elemente bis 628 px hinaus
   und lagen ausserhalb des Fensters.

   Unter 820 px stehen beide Spalten jetzt eingeklappt (32 px, der
   vorhandene Zustand) und legen sich beim Oeffnen UEBER die
   Arbeitsflaeche, statt ihr Breite wegzunehmen. Die Wahl wird in dieser
   Breite nicht gespeichert: wer auf dem Telefon kurz die Bibliothek
   aufmacht, hat damit nichts ueber seinen Schreibtisch gesagt.

   Dazu kam eine Zeile, die alles andere erst wirksam macht: .app hatte
   keine grid-template-columns, die implizite Spalte ist `auto` = so breit
   wie der Inhalt. Sie wuchs auf 597 px, die Kopfzeile bekam 597 px
   zugewiesen und sah nie zu wenig Platz — jedes flex-shrink und jedes
   min-width: 0 darin lief ins Leere. Jetzt minmax(0, 1fr).

   Die Kopfzeile ist unter 820 px eine Reihe statt drei Spalten (die Mitte
   gibt ihre Mitte auf), und die Statusleiste rollt waagerecht, statt im
   Render-Modus 27 px hinauszuragen.

4. 24 BEDIENPUNKTE UNTER 32 PX, in allen drei Breiten dieselben:
   Menuetitel 25, Umschalter 27, Spalte-einklappen 24 x 24, Suchfeld 28,
   dreizehn Gruppenkoepfe 28. Eine globale Regel statt 24 einzelner
   Nachzieher — die Hoehen entstehen aus Polsterung, nicht aus einer
   Hoehen-Angabe, und die 25. Stelle faellt sonst morgen wieder durch.
   32 px ist dieselbe Zahl wie --ziel im inventory- und facility-planner.
   Ausgenommen: Kaestchen, Auswahlknoepfe, Schieberegler.

5. DAS SUCHFELD HATTE KEINEN NAMEN. Nur ein placeholder, und der
   verschwindet beim Tippen.

6. DIE VORGABE WAR DEUTSCH (E-28). uiStore machte aus allem ausser einem
   ausdruecklichen 'en' ein 'de' — eine frische Installation lief auf
   Deutsch, als einziges Repo der Suite. Und die Bibliothek stand auch auf
   Englisch auf Deutsch: Sidebar rief `fixtureCategory.*`, in de.ts heisst
   dieselbe Sache `fx.cat.*`. Zwei Schluesselfamilien, eine davon leer,
   also immer der deutsche Fallback.

   lang:check sah das nicht: er liest den Fallback als LITERAL am Aufruf.
   Stand dort ein Ausdruck (CATEGORY_LABELS[cat]), mass er nichts — und
   meldete „0 deutsch" ueber fuenfzehn deutsche Beschriftungen. Jetzt ein
   translate-Aufruf je Kategorie mit englischem Quelltext daneben; die
   Wiederholung ist der Punkt, jede Zeile ist eine, die der Waechter
   zaehlen kann. Acht fehlende deutsche Formen in de.ts nachgetragen.

Nachgemessen nach der Aenderung, dieselbe Sonde, dieselben drei Breiten:
nichts ragt aus dem Fenster, kein Bedienpunkt unter 32 px, kein Feld ohne
Namen, die Datei-Klappe 250 x 486 px sichtbar. Alle 52 Waechter des Repos
gruen.
larszu pushed a commit that referenced this pull request Sep 13, 2026
Zwei Nachtraege aus dem Waechter-Lauf in der Suite (`bedienbar:check`), der
seit B-77 alle vier Planer misst. Beide sind Folgen der Aenderung von
gestern und wurden erst sichtbar, als eine Sonde jeden Menuetitel
tatsaechlich anklickt.

1. DIE KLAPPE SCHLOSS SICH BEIM ROLLEN, statt ihrem Titel zu folgen. Der
   erste Anlauf schloss sie bei `resize` UND bei `scroll` — die Ueberlegung
   war, dass eine Klappe, die stehenbleibt, auf einen Titel zeigt, der nicht
   mehr dort ist.

   Gemessen (im `multicam-planner` mit derselben Bauart, 390 px): liegt ein
   Titel ausserhalb der rollenden Leiste, rollt ein Klick sie erst dorthin —
   und das Rollereignis kommt NACH dem Klick. Die Klappe ging auf und sofort
   wieder zu. Wer den Titel antippt, den er sieht, merkt davon nichts; wer
   ihn ueber die Tastatur oder einen Rollbefehl erreicht, oeffnet ins Leere.

   Jetzt fuehrt die Klappe beim Rollen nach (neues Rechteck vom Titel) und
   schliesst nur noch, wenn sich die Fenstergroesse aendert. Das ist
   ausserdem das bessere Verhalten: sie bleibt an ihrem Titel, statt bei
   jeder Rollbewegung zu verschwinden.

2. DIE RECHTE GRUPPE DER KOPFZEILE GIBT NACH UND ROLLT. Mit `flex: none`
   nahm sie sich ihre volle Breite und drueckte die Menuetitel auf null —
   in der Suite-Fassung, wo zwei Knoepfe mehr darin stehen (Geraeteliste,
   Export; hier sind sie seit #125 Menuepunkte), sprengte sie die Zeile in
   einem 390-px-Fenster auf 448 px. Eine Gruppe, die rollt, bleibt
   erreichbar; eine, die andere hinausdrueckt, nimmt zwei Dinge auf einmal
   weg.

   Dazu gilt die Beschriftungs-Regel unter 820 px jetzt fuer JEDEN `.tb-btn`
   und nicht nur den primaeren — sonst blieben in der Suite-Fassung zwei
   Knoepfe mit Text stehen, waehrend der dritte schon nur sein Sinnbild
   zeigt.

Alle 52 Waechter des Repos gruen; `bedienbar:check` in der Suite meldet fuer
alle vier Planer 69 Ansichten, 1242 Bedienpunkte und 42 Menue-Klappen ohne
Befund.
larszu added a commit that referenced this pull request Sep 13, 2026
…als Vorgabe (#126)

Sechs Befunde aus einer Messung im echten Browser (2026-09-13, Chromium
gegen den gebauten dist/, 390/768/1440 px). Vier davon sind Regresse aus
#124/#125 — sie sahen im Quelltext richtig aus und waren es im Layout
nicht.

1. KEIN MENUE GING MEHR AUF. #125 gab .tb-menubar ein `overflow: hidden`;
   die Klappe ist ein absolute-Kind genau dieser Leiste. Gemessen bei
   1440 px: Datei-Klappe 250 x 505 px gross, davon 0 px sichtbar. Sie
   haengt jetzt am Fenster.

2. Der @media-Block aus #124 stand vor der Grundregel und hat nie
   gewirkt — der 2D-Plan-Knopf war bei 390 px 111 px breit statt 36.

3. .app-body brauchte 628 px, bevor die Arbeitsflaeche ein Pixel bekam.
   Unter 820 px stehen beide Spalten eingeklappt und legen sich beim
   Oeffnen ueber die Flaeche. Dazu: .app hatte keine
   grid-template-columns, die implizite Spalte wuchs auf 597 px — jedes
   flex-shrink darin lief ins Leere.

4. 24 Bedienpunkte unter 32 px, jetzt eine globale Regel.

5. Das Suchfeld hatte keinen Namen.

6. Die Vorgabe war Deutsch (E-28), und die Bibliothek stand auch auf
   Englisch auf Deutsch: zwei Schluesselfamilien, eine davon leer.
</commit_message>
</invoke>
@larszu larszu mentioned this pull request Sep 19, 2026
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.

Unnötiger Menüpunkt

2 participants