Adding Vega-Lite Settings To Dataface¶
This page documents the process for adding more Vega-Lite-backed options to Dataface over time.
Use it when you want to expose a new Vega-Lite capability through Dataface without:
- mirroring the whole Vega-Lite schema
- adding ad hoc dict passthroughs
- hiding mapping logic in renderer helpers
- creating one-off naming seams that nobody can explain later
For the surrounding architecture, also read Chart Rendering Architecture and Chart Object Model.
Core Rule¶
Do not start by copying a Vega-Lite field directly into random Dataface models.
Start by deciding whether the setting belongs in Dataface's owned style system, in chart semantics, or should remain upstream Vega-Lite behavior.
The path is:
Vega-Lite capability
-> decide whether Dataface should own it
-> add it to the right Dataface contract
-> compile it into StyleCompiled or chart contracts
-> map it explicitly to Vega-Lite output
-> test the main path
First Decision: Should Dataface Own This Setting?¶
Before adding anything, classify the setting.
Add It To Dataface Style¶
Use the style system when the setting is a presentation default or override that should be:
- themeable
- inheritable
- overrideable at board or chart level
- available through
style
Examples:
- axis label font size
- title color
- bar corner radius
- line stroke width
- chart background
- view stroke or fill
- palettes and range colors
- chart inference defaults such as
style.charts.inference.infer_zero_when_missing
Add It To Chart Semantics¶
Use chart contracts instead of style when the setting changes chart meaning or encoding behavior rather than presentation defaults.
Examples:
- chart type
- mark choice when it affects chart meaning
- axis field assignment
- sort semantics
- stack behavior
- inferred type or scale behavior
Do Not Add It Yet¶
Leave the setting upstream if:
- Dataface does not need to own it yet
- Vega-Lite's default is acceptable
- the setting would only be used through raw passthrough for edge cases
- there is no clear authored API for it yet
Not every Vega-Lite option needs to exist in Dataface immediately.
Second Decision: Where Does It Live In Dataface?¶
If Dataface should own the setting, place it in the right layer.
Authored Surface¶
Add it under style if it is a presentation option.
Examples:
style: charts: axis: label_font_size: 12 bar: corner_radius: 4 inference: infer_zero_when_missing: true
Use names that are clear in Dataface first. Do not contort the authored API just to mimic Vega-Lite naming exactly.
Patch Model¶
Add the field to the appropriate Compiled*Style class in style_model.py
and expose it through the corresponding Compiled*StylePatch (generated via
build_patch_model).
Current live authored-surface primitives in style.py:
TitleStyle— chart title font/anchor/overflowScaleStyle— chart-local scale config (band padding, etc.)RangeStyle— chart-local palette/range overridesCompiledAxisStylePatch,CompiledLegendStylePatch— axis/legend overlays
Compiled Model¶
Make sure the setting has a home in StyleCompiled.
Rules:
StylePatchis sparse and optionalStyleCompiledis authoritative compiled presentation state- only add fields Dataface intends to own
Output Model¶
Add the corresponding field to VegaLiteConfig if Dataface will emit it.
Do not use the output model as the authored model.
The Standard Implementation Process¶
Follow this order when adding a new setting.
1. Define The Dataface Meaning¶
Write down:
- what the setting means in Dataface
- whether it is board-level, chart-level, or both
- whether it is inheritable
- whether it belongs in style or chart semantics
If this cannot be explained in one or two sentences, the setting is probably not ready to add.
2. Add It To A Shared Style Primitive¶
Put the field on the smallest shared nested model that makes sense.
Good:
AxisStyle.label_font_sizeBarStyle.corner_radius
Bad:
- dumping unrelated fields onto one giant flat model
- adding a Vega-Lite-only object that bypasses the shared primitive layer
3. Expose It Through StylePatch¶
Make the setting available to authored YAML and theme presets through the patch model.
This is the layer where sparse overrides live.
4. Compile It Into StyleCompiled¶
Make sure the compiled board-scoped style object can carry the setting after:
- default style merge
- preset inheritance
- board-level overrides
- chart-level overrides
This step is what turns a setting from "available" into "real."
If the setting is chart-specific, the resolved chart path should consume one
effective chart style view, not repeated chart.style or face.style logic.
5. Map It Explicitly In style_to_vega_lite(...)¶
Add the field-to-field mapping deliberately.
Examples:
style.background-> Vega-Lite top-levelbackgroundstyle.charts.axis.label_font_size->config.axis.labelFontSizestyle.charts.bar.corner_radius->config.bar.cornerRadius
Do not hide the mapping in unrelated render helpers.
6. Emit Only The Supported Vega-Lite Output¶
If Dataface has non-Vega sections such as:
style.charts.tablestyle.charts.kpimarkdown
they must not leak into Vega-Lite output.
style_to_vega_lite(...) should emit only the supported chart-relevant subset.
7. Add Tests At Three Levels¶
Every newly owned setting should be covered by tests that prove:
- The contract exists.
- The contract is used.
- The contract is enforced.
Concretely:
- Contract exists
- authored
styleaccepts the setting StylePatch,StyleCompiled, andVegaLiteConfigknow about it- Contract is used
- board or chart style reaches the main render path
- the emitted Vega-Lite output includes the mapped field
- Contract is enforced
- unsupported values fail validation if appropriate
- regression tests catch accidental removal or bypass
Naming Rules¶
When naming the Dataface field:
- prefer clear Dataface names over raw upstream names
- keep naming consistent with nearby style primitives
- avoid introducing aliases unless compatibility requires them
- avoid shadow fields or inheritance tricks that rename upstream models
If the Vega-Lite name is awkward for authored YAML, use a better Dataface name and map it explicitly.
When Not To Add A Setting¶
Do not add a new Dataface-owned setting if:
- it is only needed once and passthrough already handles it
- it has unclear authored semantics
- it belongs to chart meaning rather than style
- it would force Dataface to mirror a large upstream sub-schema just to expose one niche field
The bar is not "can Vega-Lite do this?" The bar is "should Dataface own this as part of its deliberate authored contract?"
Anti-Patterns¶
Avoid these patterns:
- adding random dict keys to compiled style blobs
- making the generated upstream schema the runtime source of truth
- hiding field translation in renderer-specific branches
- adding a setting only to docs or only to a validator without wiring the main path
- letting non-Vega sections bleed into Vega-Lite output
Short Checklist¶
When adding a new Vega-Lite-backed setting, verify all of these:
- classify it first: style, semantics, or upstream-only
- add it to the right shared primitive
- expose it through
StylePatch - compile it into
StyleCompiled - make sure chart-local style produces one effective chart style view
- map it in
style_to_vega_lite(...) - keep non-Vega sections out of Vega-Lite output
- add contract-exists, contract-used, and contract-enforced tests
- update docs if the authored surface changed
If a proposed change skips one of these steps, it is probably incomplete.