M2 investigate chart dimension and plot-area control
Problem
Chart layout tuning exposed a gap between dashboard container sizing and actual chart drawing-area behavior. In the M1 structure lab, charts can sit inside correctly sized row/col blocks yet still leave substantial unused interior space because Vega-Lite and Dataface renderer internals reserve title, axis, legend, and padding space in ways that are hard to predict or control from the face YAML. Research and define how dimension ownership should work across dashboard layout, chart renderer defaults, and plot-area fill behavior so future structure tuning can intentionally control whether charts hug their rows, how tall sparse vs dense charts should be, and what API/config surface should exist for explicit chart sizing. Include examples from the M1 bars-and-lines lab, note the distinction between container height and usable plot height, and propose a path for better per-chart or per-structure dimension control without turning every dashboard into manual pixel work.
Context
Background: - This issue surfaced while using the focused M1 structure playground: m1-structure-bars-lines-lab.yml - The lab is intentionally wired to isolated candidate files rather than system defaults: m1-candidate.yml m1-candidate.yml - During tuning, temporary red wrapper outlines were added around chart blocks to distinguish dashboard/container layout from the inner chart rendering area.
Note:
- The M1 playground and candidate theme/structure files above came from the
parallel codex/m1-structure-lab branch during the March 26, 2026 session. If
they are not on main yet when this task starts, treat them as historical repro
context and recreate the setup in a fresh lab surface.
Observed symptoms from the March 26, 2026 design session: - charts can sit inside correctly sized row/col blocks yet still leave large unused interior space - rightmost charts can fall near or beyond the effective canvas edge when rows are tightly packed - horizontal bars can feel overly indented on the left even when their wrapper width is generous - multiple charts do not visually fill the height of their assigned row, even after wrapper padding is removed - container sizing control and actual plot-area sizing are currently easy to confuse
Relevant code surfaces: - dashboard/face layout sizing: sizing.py - face rendering and nested-face wrappers: faces.py - chart rendering orchestration: renderer.py - theme and structure config surfaces: theme_types.py config.py
Relevant design/docs references: - board/layout implementation guide: implementation.md - contributor architecture guide for the layout engine: layout-engine.md
Evidence note: - the March 26 thread included screenshots showing red-outlined chart wrappers with charts leaving significant unused interior space; those screenshots should be preserved or re-captured during task execution if durable file assets are needed
Possible Solutions
-
Tighten only the lab/dashboard layout wrappers. Trade-off: useful for immediate experimentation, but it does not solve the underlying ambiguity between wrapper height and usable chart plot height.
-
Add clearer chart-sizing controls at the structure/theme level without changing renderer internals much. Trade-off: lower implementation risk, but may still leave opaque Vega-Lite internal padding/title/legend behavior that prevents predictable plot fill.
-
Recommended: define explicit dimension ownership across dashboard container sizing, chart renderer defaults, and inner plot-area behavior, then expose a minimal control surface for predictable chart fill. This should distinguish: - outer block/container size - chart frame size - usable plot area after title, axes, legends, and reserved padding - when sparse charts should intentionally hug their rows vs preserve breathing room Trade-off: requires deeper investigation across sizing + rendering layers, but it directly addresses the real system problem uncovered during structure tuning.
-
Push chart dimensions toward fully manual per-chart pixel control. Trade-off: maximum control, but likely too brittle and too labor-intensive for ordinary dashboard authoring.
Plan
Selected approach: - pursue solution 3 and use the M1 bars-and-lines lab as the primary repro surface
Investigation steps: 1. reproduce the issue in the M1 structure lab and capture durable screenshots/assets if needed 2. trace how row/col wrapper dimensions become chart dimensions through sizing and face rendering 3. identify how much height/width is consumed by title, legend, axes, and Vega-Lite internal layout 4. document the current dimension-ownership model and where it breaks user expectations 5. propose a better API/config split for: - wrapper/container sizing - chart frame sizing - plot-area fill behavior - optional sparse/dense heuristics by chart family 6. recommend whether fixes belong in structure presets, theme defaults, renderer logic, or a new explicit chart-sizing surface
Implementation Progress
QA Exploration
- [ ] QA exploration completed (or N/A for non-UI tasks)
Review Feedback
- [ ] Review cleared