Gesamtgraph: Box auf Viewport-Höhe begrenzen — Mausrad-Zoom scrollt die Seite mit #131

Closed
opened 2026-07-15 14:34:44 +02:00 by fable-5 · 2 comments
Collaborator

Bug/UI (Stefans Feedback zum v0.7.0-Prod-Test, Follow-up zu #123)

Beim Gesamtgraphen (/p/:pond/graph) ist die Graph-Box so hoch, dass die Seite einen Scrollbalken bekommt — beim Zoomen mit dem Mausrad wird deshalb gleichzeitig mitgescrollt. Die Box soll so groß wie möglich sein, ohne dass die Seite scrollen muss (Viewport-füllend unterhalb von Header/Reglern/Legende).

Ursachen (verifiziert):

  1. .force-graph { width: 100%; height: auto } + festes viewBox 800×560 → das SVG skaliert auf Containerbreite und die Höhe folgt dem 800:560-Seitenverhältnis. Auf breiten Fenstern wird der Graph höher als der Viewport → Seiten-Scrollbalken.
  2. Der Zoom hängt an Reacts onWheel — React registriert Wheel-Listener am Root passiv, preventDefault() könnte das Scrollen dort gar nicht verhindern (aktuell wird es nicht mal versucht). Solange die Seite scrollbar ist, scrollt jedes Zoomen mit.

Lösungsskizze:

  • graph-page als Flex-Spalte über die verfügbare Höhe der Main-Column; graph-page__canvas bekommt flex: 1; min-height: 0, das SVG height: 100% — Breite/Höhe des Containers messen (ResizeObserver) und als width/height-Props an ForceGraph geben, statt der festen 800×560-Defaults (LocalGraphPanel behält seine festen Maße).
  • Wheel-Zoom auf einen nativen, non-passiven Listener umstellen (svg.addEventListener('wheel', handler, { passive: false }) via Ref + preventDefault()), damit auch in anderen Scroll-Kontexten (z. B. kleine Fenster) nie mitgescrollt wird. Bonus: Zoom dabei auf den Mauszeiger zentrieren statt auf die Mitte.
  • e2e: graph-Pack muss unverändert grün bleiben (testids/Klassen bleiben); ggf. Assertion, dass die Seite keinen vertikalen Scrollbalken hat.
**Bug/UI** (Stefans Feedback zum v0.7.0-Prod-Test, Follow-up zu #123) Beim **Gesamtgraphen** (`/p/:pond/graph`) ist die Graph-Box so hoch, dass die Seite einen **Scrollbalken** bekommt — beim Zoomen mit dem Mausrad wird deshalb gleichzeitig **mitgescrollt**. Die Box soll so groß wie möglich sein, **ohne dass die Seite scrollen muss** (Viewport-füllend unterhalb von Header/Reglern/Legende). **Ursachen (verifiziert):** 1. `.force-graph { width: 100%; height: auto }` + festes `viewBox` 800×560 → das SVG skaliert auf Containerbreite und die Höhe folgt dem 800:560-Seitenverhältnis. Auf breiten Fenstern wird der Graph höher als der Viewport → Seiten-Scrollbalken. 2. Der Zoom hängt an Reacts `onWheel` — React registriert Wheel-Listener am Root **passiv**, `preventDefault()` könnte das Scrollen dort gar nicht verhindern (aktuell wird es nicht mal versucht). Solange die Seite scrollbar ist, scrollt jedes Zoomen mit. **Lösungsskizze:** - `graph-page` als Flex-Spalte über die verfügbare Höhe der Main-Column; `graph-page__canvas` bekommt `flex: 1; min-height: 0`, das SVG `height: 100%` — Breite/Höhe des Containers messen (ResizeObserver) und als width/height-Props an `ForceGraph` geben, statt der festen 800×560-Defaults (LocalGraphPanel behält seine festen Maße). - Wheel-Zoom auf einen **nativen, non-passiven** Listener umstellen (`svg.addEventListener('wheel', handler, { passive: false })` via Ref + `preventDefault()`), damit auch in anderen Scroll-Kontexten (z. B. kleine Fenster) nie mitgescrollt wird. Bonus: Zoom dabei auf den Mauszeiger zentrieren statt auf die Mitte. - e2e: graph-Pack muss unverändert grün bleiben (testids/Klassen bleiben); ggf. Assertion, dass die Seite keinen vertikalen Scrollbalken hat.
fable-5 added this to the M16 — Papierkorb: Mehrfachauswahl milestone 2026-07-15 14:34:44 +02:00
fable-5 added the
frontend
label 2026-07-15 14:34:44 +02:00
Author
Collaborator

Scope-Anpassung (Stefan, per Chat 15.07.): Wenn Punkt 1 (Box passt in den Viewport, kein Seiten-Scrollbalken) umgesetzt ist, braucht das Scrollen beim Zoomen nicht mehr separat verhindert zu werden — die Seitengröße passt dann ja.

→ Umsetzung beschränkt sich auf die Layout-Lösung (Flex-Spalte, Canvas füllt die verfügbare Höhe, Containermaße via ResizeObserver als Props). Der native non-passive wheel-Listener aus Punkt 2 entfällt; bei der Verifikation prüfen wir lediglich, dass nach dem Layout-Fix tatsächlich kein vertikaler Scrollbalken mehr auftritt (auch bei kleineren Fenstern). Der Bonus „Zoom auf den Mauszeiger zentrieren" bleibt optional.

**Scope-Anpassung (Stefan, per Chat 15.07.):** Wenn Punkt 1 (Box passt in den Viewport, kein Seiten-Scrollbalken) umgesetzt ist, braucht das Scrollen beim Zoomen nicht mehr separat verhindert zu werden — die Seitengröße passt dann ja. → Umsetzung beschränkt sich auf die **Layout-Lösung** (Flex-Spalte, Canvas füllt die verfügbare Höhe, Containermaße via ResizeObserver als Props). Der native non-passive wheel-Listener aus Punkt 2 entfällt; bei der Verifikation prüfen wir lediglich, dass nach dem Layout-Fix tatsächlich kein vertikaler Scrollbalken mehr auftritt (auch bei kleineren Fenstern). Der Bonus „Zoom auf den Mauszeiger zentrieren" bleibt optional.
Author
Collaborator

Umgesetzt in d23e5dc, Scope wie in Kommentar 1187 reduziert (nur Layout): .graph-page ist eine Flex-Spalte mit height: 100% in der Main-Column, .graph-page__canvas bekommt flex: 1; min-height: 0; ein ResizeObserver misst den Canvas und gibt die Maße als width/height-Props an ForceGraph (statt der festen 800×560 — der Graph rendert erst nach der ersten Messung). .graph-page__canvas .force-graph { height: 100% }; LocalGraphPanel behält seine festen Maße. Der non-passive wheel-Listener entfiel wie besprochen — ohne Scrollbalken scrollt das Mausrad nichts mit.

Verifiziert: kein vertikaler Overflow bei 1600×900 und 900×600 (main.scrollHeight - main.clientHeight == 0); graph.spec assertet das jetzt dauerhaft. CI grün auf 4f79a81.

Umgesetzt in `d23e5dc`, Scope wie in Kommentar 1187 reduziert (nur Layout): `.graph-page` ist eine Flex-Spalte mit `height: 100%` in der Main-Column, `.graph-page__canvas` bekommt `flex: 1; min-height: 0`; ein ResizeObserver misst den Canvas und gibt die Maße als width/height-Props an `ForceGraph` (statt der festen 800×560 — der Graph rendert erst nach der ersten Messung). `.graph-page__canvas .force-graph { height: 100% }`; `LocalGraphPanel` behält seine festen Maße. Der non-passive wheel-Listener entfiel wie besprochen — ohne Scrollbalken scrollt das Mausrad nichts mit. Verifiziert: kein vertikaler Overflow bei 1600×900 und 900×600 (`main.scrollHeight - main.clientHeight == 0`); graph.spec assertet das jetzt dauerhaft. CI grün auf `4f79a81`.
Sign in to join this conversation.
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#131
No description provided.