Investigate structure-level axis visibility config not applying in standard charts
Problem
Document why vega.config.axisX.labels=false is emitted but standard charts still render x-axis labels, including evidence from the M1 structure lab and likely mismatch between top-level config.axisX and concrete encoding axis objects.
Context
This issue surfaced while using the M1 structure lab as a design surface:
examples/playground/faces/labs/m1-structure-bars-lines-lab.yml- theme:
dataface/core/compile/chart_themes/m1-candidate.yml - structure:
dataface/core/compile/chart_structures/m1-candidate.yml
These lab artifacts 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 is picked
up, treat them as historical repro context and recreate the same settings in a
fresh lab surface.
The immediate design goal was simple: turn off x-axis labels from the candidate structure so the lab could be judged without them.
The authored structure currently contains:
dataface/core/compile/chart_structures/m1-candidate.yml:31vega.config.axisX.labels: false
Evidence gathered during investigation:
- The authored YAML is loaded correctly.
- The resolved structure config extracted by
extract_structure_vega_config()containsaxisX: { labels: false }. - The final rendered Vega-Lite spec for a standard bar chart also contains
config.axisX.labels = false. - Despite that, x-axis labels still render in the browser.
Important related code paths:
dataface/core/compile/config.pyextract_structure_vega_config()lifts raw structure keys likeaxisXinto Vega config.dataface/core/render/chart/standard_renderer.py:144standard charts build an explicitencoding.x.axisobject.dataface/core/render/chart/standard_renderer.py:161chart-authoredsettings.x_axisis merged directly onto that concrete axis object.docs/docs/reference/single-chart-property-catalog.md:539Dataface’s documented axis passthrough surface issettings.x_axis/settings.y_axis, i.e. concrete axis objects.
One especially important clue:
- If a chart is authored with
settings.x_axis.labels: false, the generatedencoding.x.axisdoes containlabels: false. - If the same intent is authored through structure as
vega.config.axisX.labels: false, the generated spec only carries it on top-levelconfig.axisX, and the labels still render.
That strongly suggests a mismatch between:
- top-level structure/theme Vega config surfaces like
config.axisX - and the explicit concrete axis objects Dataface generates on
encoding.x.axis
Constraints:
- The user explicitly does not want another manual workaround here.
- This needs to be understood as a systems problem, not papered over in the lab.
- The task should explain whether this is a Vega-Lite config limitation, a Dataface merge/placement bug, or a precedence bug where generated axis objects effectively override structure-level visibility intent.
Current working conclusion:
- This does not look like a missing Vega-Lite capability.
- It looks like a broken or incomplete Dataface-to-Vega-Lite mapping/application path.
- Dataface is currently accepting a Vega-Lite-shaped structure property, but not applying it at the layer where standard charts appear to actually honor axis visibility behavior.
That broader architectural concern matters beyond this one bug:
- Dataface currently exposes multiple surfaces that appear Vega-Lite-compatible:
- theme/structure
vega.config.* - chart-authored
settings.x_axis/settings.y_axis - When the same conceptual property behaves differently across those surfaces, authors cannot trust which layer is authoritative.
- Follow-on work should aim to reduce these broken links between DFT and Vega-Lite by defining which properties are:
- true global config defaults,
- true generated-axis behavior flags,
- or unsupported/translated aliases that must be promoted onto concrete axis objects.
Possible Solutions
-
Recommended: Treat axis visibility settings like
labels,ticks, anddomainas behavior flags that must be applied onto generated concrete axis objects during standard-chart spec assembly. This matches how Dataface already treats chart-authoredsettings.x_axisandsettings.y_axis. It would make structure defaults and authored chart overrides converge on the same effective surface. -
Investigate whether
config.axisX.labelsis unsupported or only partially supported by Vega-Lite in the way Dataface is currently using it. If Vega-Lite does not honorlabelsreliably from top-levelconfig.axisX, then Dataface should stop exposing or relying on that path for visibility controls. -
Add an explicit translation step in the standard renderer that promotes selected structure-level axis flags from
config.axisX/config.axisYintoencoding.x.axis/encoding.y.axis. This is similar to option 1 but narrower: translate only the problematic visibility keys instead of redefining the whole precedence model. -
Tighten the documented contract. If structure-level
axisX.labelsis not a valid or supported path for Dataface, the docs and structure patterns should stop implying it is available. -
Add a broader DFT/Vega-Lite contract pass for axis properties. Review visibility, posture, and grid/domain flags across: - structure
vega.config.axis*- theme defaults - chart-authoredsettings.x_axis/settings.y_axis- generated axis objects so the same conceptual property is not silently broken at one layer and working at another.
Trade-offs:
- A renderer-level fix is likely the cleanest user experience, but it introduces more explicit precedence logic between global config and generated axis objects.
- A docs-only fix would be fast but would leave an obvious design-system gap: structure cannot reliably express axis visibility defaults.
- A narrow promotion of
labelsalone might solve this task quickly, but similar flags liketicks,domain, ortitlemay fail the same way later.
Plan
- Verify the exact failure boundary with a minimal standard-chart spec:
confirm that
config.axisX.labels = falseis present while rendered labels still appear. - Compare that against the chart-authored axis path:
confirm that
settings.x_axis.labels: falselands onencoding.x.axis.labels. - Check Vega-Lite config expectations and local Dataface docs to determine whether
labelsbelongs on top-level config, concrete axis objects, or both. - Decide and document the preferred Dataface rule: structure-level axis visibility defaults should either: - be promoted onto generated axis objects, or - be declared unsupported from top-level structure config.
- Capture the broader architectural implication: DFT needs a clearer, less fragile mapping contract between Vega-Lite config-shaped surfaces and the concrete chart objects it generates.
- If a fix is chosen later, update the standard renderer and catalog/docs together so authored behavior, structure defaults, and docs all match.
Implementation Progress
- 2026-03-26: Confirmed the authored structure contains
axisX.labels: false. - 2026-03-26: Confirmed the final standard-chart spec also contains
config.axisX.labels = false. - 2026-03-26: Confirmed x-axis labels still render in the browser despite that.
- 2026-03-26: Confirmed chart-authored
settings.x_axis.labels: falselands on the concreteencoding.x.axisobject instead. - 2026-03-26: Working theory is now a surface/preference mismatch, not a typo in YAML loading.
- 2026-03-26: Reframed the bug more clearly as a likely DFT-to-Vega-Lite mapping/application failure rather than a missing Vega-Lite property.
QA Exploration
- [ ] QA exploration completed (or N/A for non-UI tasks)
Notes:
- Reproduced in the M1 structure lab on the local playground.
- The observed behavior was stable across reloads once the playground was moved to a fresh port.
Review Feedback
- [ ] Review cleared