Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
0f872f5
feat(vegalite): add Calendar Heatmap template
zl190 Jul 19, 2026
ed3b376
feat(vegalite): canonical GitHub calendar via quantile color scale
zl190 Jul 19, 2026
4adde88
Plotly: realize ThemeSpec decisions onto figures
Chenglong-MS Aug 6, 2026
da3cbe3
Plotly theme: chrome placed by domain, and ink by direction
Chenglong-MS Aug 6, 2026
dc56621
plotly theme: fix the gaps the synthetic corpus found
Chenglong-MS Aug 6, 2026
b7ffb84
plotly theme: measure ticks in room, not in counts
Chenglong-MS Aug 6, 2026
c32b9a7
plotly theme: unit tests for the realizer
Chenglong-MS Aug 6, 2026
9fd55bc
site: view the Plotly themes in the browser
Chenglong-MS Aug 6, 2026
50b92f1
Fix Plotly chart cropping and close the gaps against themed Vega-Lite
Chenglong-MS Aug 6, 2026
29d759c
Refine radar layout, secondary points, and grids
Chenglong-MS Aug 6, 2026
fc6c3b8
Align Plotly high-cardinality pies with Vega-Lite
Chenglong-MS Aug 6, 2026
f093096
Refine Plotly rose polar guides
Chenglong-MS Aug 6, 2026
5acdb37
Restore Plotly rose scale values
Chenglong-MS Aug 6, 2026
fdac7f5
Label Plotly rose wedge totals
Chenglong-MS Aug 7, 2026
dd9a0a7
Avoid duplicate Plotly pie legends
Chenglong-MS Aug 7, 2026
30d1b9f
Adapt Plotly pie label wrapping
Chenglong-MS Aug 7, 2026
a8157d6
Place Plotly rose totals outside
Chenglong-MS Aug 7, 2026
ffb9029
Fix Plotly cross-family theme failures
Chenglong-MS Aug 7, 2026
87054ce
Extend paired theme audit to r2
Chenglong-MS Aug 7, 2026
1f1a6b5
Complete Plotly theme parity audit
Chenglong-MS Aug 7, 2026
e28041e
Merge pull request #64 from zl190/feat/vegalite-calendar
Chenglong-MS Aug 8, 2026
eb82cc3
Refine Plotly line point density
Chenglong-MS Aug 8, 2026
959a616
Merge branch 'theme-plotly' into dev
Chenglong-MS Aug 8, 2026
677b0aa
fix: theme Vega-Lite calendar heatmaps
Chenglong-MS Aug 8, 2026
980361b
fix: add Vega-Lite calendar to gallery
Chenglong-MS Aug 8, 2026
d1902e4
feat(theme): calibrate sparse band fit per house, and keep straight l…
Chenglong-MS Aug 12, 2026
86d4d0b
fix(waterfall): size the step axis as the band it is drawn on
Chenglong-MS Aug 12, 2026
1071314
fix(theme): never print a house label off a template's working column
Chenglong-MS Aug 12, 2026
118eb55
fix(layout): reserve the margins a chart draws before fitting its bands
Chenglong-MS Aug 12, 2026
f20b902
fix(calendar): drop the plot frame, and let the caller square the cells
Chenglong-MS Aug 12, 2026
57701f7
fixes
Chenglong-MS Aug 12, 2026
8ee8e8a
release: 0.5.1
Chenglong-MS Aug 12, 2026
ad18e38
docs: announce 0.5.1, and invite readers to the hosted server
Chenglong-MS Aug 12, 2026
8d00918
cleaning up
Chenglong-MS Aug 12, 2026
2659241
ok
Chenglong-MS Aug 13, 2026
18046bb
update
Chenglong-MS Aug 13, 2026
5fbb36f
ok
Chenglong-MS Aug 13, 2026
c51ccd8
cleanup
Chenglong-MS Aug 13, 2026
d31da14
fixes
Chenglong-MS Aug 14, 2026
a6f538c
fixes
Chenglong-MS Aug 14, 2026
5d9c33b
ok
Chenglong-MS Aug 14, 2026
8db6473
fix
Chenglong-MS Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 25 additions & 51 deletions .github/release-notes/0.5.0.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,24 @@
# Flint 0.5.0: Formal visual themes

Flint 0.5 introduces `ThemeSpec`, a formal specification for applying a
coherent design system across an entire chart library. Instead of requiring
creators or agents to reproduce design guidance chart by chart, a ThemeSpec
participates directly in compilation and adapts to the chart's semantics,
data, cardinality, and available space.

A ThemeSpec shapes compilation in three stages. Using resolved semantic
information, it:

- governs layout constraints and dynamics, including density, spacing, sizing,
and stretch limits;
- conditionally resolves visual preferences for labels, legends, axes,
annotations, and semantic roles; and
- supplies design fixtures such as typography, color, surfaces, mark geometry,
and structural line styles to backend-specific code generation.
Flint 0.5 introduces `ThemeSpec`, a formal specification for applying a coherent design system across an entire chart library. Instead of requiring creators or agents to reproduce design guidance chart by chart, a ThemeSpec participates directly in compilation and adapts to the chart's semantics, data, cardinality, and available space.

A ThemeSpec shapes compilation in three stages. Using resolved semantic information, it:

- governs layout constraints and dynamics, including density, spacing, sizing, and stretch limits;
- conditionally resolves visual preferences for labels, legends, axes, annotations, and semantic roles; and
- supplies design fixtures such as typography, color, surfaces, mark geometry, and structural line styles to backend-specific code generation.

<p align="center">
<img width="100%" alt="ThemeSpec shaping the Flint compilation process through resolved semantics, layout constraints, visual preferences, and design fixtures." src="https://raw.githubusercontent.com/microsoft/flint-chart/2f147ef3d068a8ecf26ec10ad0a50c01c862f0ab/docs/figs/theme-spec-expl.png" />
<br>
<sub>ThemeSpec participates throughout compilation, from resolved semantics and layout dynamics to conditional visual preferences and backend design fixtures.</sub>
</p>

This release also adds ten built-in themes, custom and inherited ThemeSpecs,
public theme APIs, a visual-theme explorer and Theme Lab, plus theme discovery
and authoring support in the Flint MCP server and MCP App.
This release also adds ten built-in themes, custom and inherited ThemeSpecs, public theme APIs, a visual-theme explorer and Theme Lab, plus theme discovery and authoring support in the Flint MCP server and MCP App.

## Use a visual theme

Add `theme_spec` beside `chart_spec`. The chart spec continues to define what
the chart means; the theme defines how that meaning is presented.
Add `theme_spec` beside `chart_spec`. The chart spec continues to define what the chart means; the theme defines how that meaning is presented.

```json
{
Expand All @@ -46,10 +35,7 @@ the chart means; the theme defines how that meaning is presented.

## Ten built-in themes

Flint ships New York Times, Economist, Swiss, Nature, McKinsey, Datawrapper,
Power BI, Power BI Light, Pop, and Cartoon presets. The
[visual-theme explorer](https://microsoft.github.io/flint-chart/#/themes)
applies each preset to the same set of charts for direct comparison.
Flint ships New York Times, Economist, Swiss, Nature, McKinsey, Datawrapper, Power BI, Power BI Light, Pop, and Cartoon presets. The [visual-theme explorer](https://microsoft.github.io/flint-chart/#/themes) applies each preset to the same set of charts for direct comparison.

<p align="center">
<a href="https://microsoft.github.io/flint-chart/#/themes?theme=economist&amp;layout=banner">
Expand Down Expand Up @@ -77,8 +63,7 @@ applies each preset to the same set of charts for direct comparison.

## Create a brand theme

Pass a custom `ThemeSpec`, or inherit a built-in preset and override only the
decisions that should differ:
Pass a custom `ThemeSpec`, or inherit a built-in preset and override only the decisions that should differ:

```json
{
Expand All @@ -98,30 +83,19 @@ Nested objects merge; arrays and scalar values replace inherited values.

## Tools and integrations

- The [visual-theme explorer](https://microsoft.github.io/flint-chart/#/themes)
compares presets across the same chart wall.
- [Theme Lab](https://microsoft.github.io/flint-chart/#/theme-lab) tests custom
ThemeSpecs across chart types and data shapes.
- The MCP server and MCP App add theme discovery, preset selection, and custom
ThemeSpec support through `list_themes`.
- The bundled `flint://theme-skill` resource and `author_flint_theme` prompt
help agents translate design guidance into reusable ThemeSpecs.
- Public APIs include `ThemeSpec`, `ThemePreset`, `THEME_PRESETS`,
`listThemePresets()`, and `resolveThemeSpec()`.
- The theme explorer, Theme Lab, and authoring guidance are available in
English and Chinese.

The release also improves Vega-Lite logarithmic tick and grid spacing, line
endpoint guides, and heatmap grid treatment.

ThemeSpec is currently realized by the Vega-Lite backend. Other backends still
accept the shared Flint input but do not yet apply `theme_spec`. Existing inputs
without a theme retain Flint's default behavior.

See [Using themes](https://microsoft.github.io/flint-chart/#/documentation/theme-spec)
for the complete vocabulary and examples.

See the [changelog](https://github.com/microsoft/flint-chart/blob/main/CHANGELOG.md)
for the complete technical summary.
- The [visual-theme explorer](https://microsoft.github.io/flint-chart/#/themes) compares presets across the same chart wall.
- [Theme Lab](https://microsoft.github.io/flint-chart/#/theme-lab) tests custom ThemeSpecs across chart types and data shapes.
- The MCP server and MCP App add theme discovery, preset selection, and custom ThemeSpec support through `list_themes`.
- The bundled `flint://theme-skill` resource and `author_flint_theme` prompt help agents translate design guidance into reusable ThemeSpecs.
- Public APIs include `ThemeSpec`, `ThemePreset`, `THEME_PRESETS`, `listThemePresets()`, and `resolveThemeSpec()`.
- The theme explorer, Theme Lab, and authoring guidance are available in English and Chinese.

The release also improves Vega-Lite logarithmic tick and grid spacing, line endpoint guides, and heatmap grid treatment.

ThemeSpec is currently realized by the Vega-Lite backend. Other backends still accept the shared Flint input but do not yet apply `theme_spec`. Existing inputs without a theme retain Flint's default behavior.

See [Using themes](https://microsoft.github.io/flint-chart/#/documentation/theme-spec) for the complete vocabulary and examples.

See the [changelog](https://github.com/microsoft/flint-chart/blob/main/CHANGELOG.md) for the complete technical summary.

**Full Changelog**: https://github.com/microsoft/flint-chart/compare/0.4.0...0.5.0
62 changes: 62 additions & 0 deletions .github/release-notes/0.5.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Flint 0.5.1: Themes on Plotly, and a calendar heatmap

Flint 0.5.1 extends the theme system introduced in 0.5 to a second backend, adds Vega-Lite Calendar Heatmap, and tightens how charts fit the space they are given.

## Themes on Plotly

`theme_spec` now realizes onto Plotly figures. The neutral grounding stage is reused unchanged from Vega-Lite — no field in the theme layer moved to accommodate Plotly, which is the first evidence that the neutral layer really is neutral.

```json
{
"chart_spec": {
"chartType": "Line Chart",
"encodings": {
"x": { "field": "month" },
"y": { "field": "revenue" }
}
},
"theme_spec": "economist",
"backend": "plotly"
}
```

Surface, typography, axes, marks, series ink, legend, facet chrome, and data labels all follow the house. Where Plotly cannot do what a decision asks, it approximates and records what it did in `figure._theme.report`. `assemblePlotly` also renders `chart_spec.title` for the first time — a house's headline treatment is most of what makes it recognisable, and there was nothing to treat.

The Plotly templates were reworked against a paired audit with themed Vega-Lite: line point density, pie label wrapping, rose wedge totals and polar guides, radar layout, facet chrome, and figure cropping all move toward parity.

## Calendar Heatmap

A new Vega-Lite chart type for daily values on a Monday-first week grid.

```json
{
"chart_spec": {
"chartType": "Calendar Heatmap",
"encodings": {
"x": { "field": "date" },
"color": { "field": "commits" }
},
"chartProperties": { "cornerRadius": 2 }
}
}
```

`cornerRadius` squares the cells into a continuous field or rounds them into tiles, and the `github` color scheme reproduces the familiar contribution graph through a quantile scale.

## Charts that fit the space they are given

Three changes to sizing, each visible on charts that were previously cramped or overgrown:

- **Bands are fitted per house.** The new `layout.bandStepFit` field states how far a preset will grow a bar toward its slot when a chart has few categories. All ten presets are calibrated from first-party sources, so a Datawrapper bar fills its step and a Nature bar stays slim.
- **Furniture is reserved before bands are fitted.** Value labels, tick gutters, the title block, and the legend are counted first, so a house no longer sizes bands against room its own furniture is about to take.
- **Long headlines are fitted rather than left to widen the graphic.** A headline that only overhangs its block is left alone, one that overhangs further is set down a size, and only a headline that still does not fit is broken — over even lines, with the height taken out of the plot rather than added to the canvas.

## Fixes

- A closing rule under a banded plot runs the width of the bands, not the width a continuous plot would have taken, so a house that draws one no longer stretches the canvas past the chart.
- Waterfall declares its step axis as the band it is drawn on, so a temporal waterfall is sized per category instead of as a continuous run. Fixed in both the JavaScript and Python implementations.
- A house no longer prints a value label off a template's internal working column, which leaked computed values onto Vega-Lite waterfalls.
- Calendar heatmaps drop the plot frame, which had drawn a box around the days a part week does not have.
- Straight axis labels that cannot fit their band are no longer held flat by a house that prefers them straight.

**Full Changelog**: https://github.com/microsoft/flint-chart/blob/main/CHANGELOG.md
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,11 @@ loops/
# Generated eval-results data for the flint-py results viewer (8.5MB+, contains
# run-specific paths/tracebacks). Regenerate locally via tools/build_results_page.py.
packages/flint-py/tools/viewer/results.js

# Theme audit renders and bundled audit scripts
audit-out/
scripts/.*.mjs

# Third-party theme research artifacts. Keep provenance and findings tracked;
# source PDFs/images remain local and are reproducible from the manifest.
theme-evidence/*
103 changes: 102 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,106 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.5.1] - 2026-08-13

### Added

- Theme support for the Plotly backend. `theme_spec` now realizes onto Plotly
figures — surface, typography, axes, marks, series ink, legend, facet chrome,
and data labels — reusing the same neutral grounding stage as Vega-Lite. Where
Plotly cannot honor a decision it approximates and records what it did in
`figure._theme.report`. `assemblePlotly` also renders `chart_spec.title` for
the first time.
- A Vega-Lite **Calendar Heatmap** chart type: daily values on a Monday-first
week grid, with a `cornerRadius` chart property and a canonical GitHub look
through a quantile color scale.
- Per-house sparse band fitting through the new `layout.bandStepFit` field, so
each preset states how far it will grow a bar toward its slot when a chart has
few categories. All ten presets are calibrated from first-party sources.

### Changed

- An axis title that is still needed now lies flat at the head of its own ruler,
beside the values it names and on whichever side those values sit, rather than
being turned on its side. Where two rulers each carry a measure, both are
named: one name cannot say which quantity is horizontal and which is vertical.
- A measure axis that draws a grid rounds its domain to the tick count the axis
actually draws, so the plot's edge falls on a grid line instead of stopping
short of one and leaving the outermost reading with nothing above it. Axes
that draw no grid, and non-linear rulers whose ticks are decades rather than a
count, are left alone. On a dot scale the rounding is applied to the data
rather than to the domain the renderer has already opened by a dot's radius:
rounding the padded domain turned a few pixels of clearance into a whole extra
interval, and a score bounded 0 to 100 came out running -10 to 110.
- A measure axis that draws a grid but no ticks carries that grid a few pixels
past the plot, in grid ink, so each line ends under its own number. Flush with
the last mark — a histogram's final bar — the line led nowhere.
- A unit is stated once. Where the axis title already carries it, the ruler no
longer repeats it down every tick.
- Economist axis labels and titles are calibrated against the 300x300 and
400x300 canvases the library actually draws, and the house now lays its axis
titles flat rather than turning them on their side.
- McKinsey declares the `deck` and `axisTitle` type roles it had left implicit
and quiets `axisLabel`. Raising one role while leaving others to the global
defaults had inverted the ranking: the tick labels were the second-largest
text on the chart, above the subtitle and the axis title.
- Vega-Lite reserves the margins a chart will actually draw — value labels, tick
gutters, the title block, and the legend — before fitting bands, so a wide
house no longer sizes bands against room its own furniture will take.
- Long headlines are fitted rather than left to widen the graphic. A headline
that only overhangs its block is left alone, one that overhangs further is set
down a size, and only a headline that still does not fit is broken — over even
lines, with the height taken out of the plot rather than added to the canvas.
- A long deck is fitted the same way, and was not before: Vega-Lite measures it
as one unbroken run and grows the canvas to fit, so a deck alone took a 420px
chart out past 1,200px even where the headline above it had been brought to
heel. It is only ever broken, never set smaller — the deck is already the
quietest line in the block.
- Both are measured against the whole graphic rather than the plot rectangle.
The axis gutter beneath a title is the title's to use, and measuring without
it broke a headline that had room to spare beside its row labels.
- Both now run when no house is named. Staying inside the size the caller asked
for is a Flint concern rather than a house preference, and an un-themed chart
was getting no fitting at all.
- Plotly line, bar, scatter, pie, rose, radar, slope, heatmap, ranged-dot, and
KPI-card templates were reworked against a paired audit with themed Vega-Lite:
point density, label wrapping, wedge totals, polar guides, facet chrome, and
cropping all move toward parity.

### Fixed

- A house that omits its grid, its rule and its ticks does so because the value
is printed on the mark — a consulting-deck bar. A scatter prints nothing, and
the same house left its readings floating with no way to judge one against
another. Where no mark prints its value and the ruler draws nothing, the quiet
grid returns. A house may choose how a value is read; it may not leave no way
to read one.
- A measure axis no longer surrenders the right margin to series-end labels that
are never drawn. The placement was chosen off the house's ranked list whether
or not there was a key to place, so a single-series line chart evicted its own
ruler to the left and lost the house's opposite-seated axis on the plainest
chart it draws.
- Series-end and band-end labels no longer reserve canvas margin the renderer
has already reserved. They are ordinary text marks, and the default `pad`
autosize already grows the canvas to the scene's bounds, so the estimate was
counted twice — around 90px of dead margin per chart.
- A flat axis title no longer lands on the side its values are not. On a
right-seated ruler it was laid at the plot's left edge, captioning the wrong
column, and only the first of two rulers was ever laid flat.
- A flat axis title clears the topmost value rather than sitting on it.
- A closing rule drawn under a banded plot now runs the width of the bands
rather than the width a continuous plot would have taken, so a house that
draws one no longer stretches the canvas past the chart.
- Waterfall now declares its step axis as the band it is drawn on, so a temporal
waterfall is sized per category instead of as a continuous run. Fixed in both
the JavaScript and Python implementations.
- A house no longer prints a value label off a template's internal working
column, which leaked computed values onto Vega-Lite waterfalls.
- Calendar heatmaps drop the plot frame, which had drawn a box around the days
a part week does not have.
- Straight axis labels that cannot fit their band are no longer held flat by a
house that prefers them straight.

## [0.5.0] - 2026-08-05

### Added
Expand Down Expand Up @@ -218,7 +318,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Treated only lowercase `start` and `end` Waterfall Type values as total
anchors in Vega-Lite; other values now remain floating deltas colored by sign.

[Unreleased]: https://github.com/microsoft/flint-chart/compare/0.5.0...HEAD
[Unreleased]: https://github.com/microsoft/flint-chart/compare/0.5.1...HEAD
[0.5.1]: https://github.com/microsoft/flint-chart/compare/0.5...0.5.1
[0.5.0]: https://github.com/microsoft/flint-chart/compare/0.4.0...0.5.0
[0.4.1]: https://github.com/microsoft/flint-chart/compare/0.4.0...0.4.1
[0.4.0]: https://github.com/microsoft/flint-chart/compare/0.3.0...0.4.0
Expand Down
Loading
Loading