@automattic/charts 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/TOKENS.md +107 -48
  3. package/dist/index.cjs +584 -209
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.css +97 -43
  6. package/dist/index.d.cts +46 -41
  7. package/dist/index.d.ts +46 -41
  8. package/dist/index.js +582 -210
  9. package/dist/index.js.map +1 -1
  10. package/package.json +2 -2
  11. package/src/charts/area-chart/area-chart.module.scss +8 -3
  12. package/src/charts/area-chart/area-chart.tsx +3 -5
  13. package/src/charts/bar-chart/bar-chart.module.scss +14 -6
  14. package/src/charts/bar-chart/bar-chart.tsx +24 -15
  15. package/src/charts/bar-chart/private/use-bar-chart-options.ts +197 -30
  16. package/src/charts/bar-chart/test/bar-chart.test.tsx +685 -1
  17. package/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss +17 -12
  18. package/src/charts/conversion-funnel-chart/conversion-funnel-chart.tsx +107 -86
  19. package/src/charts/conversion-funnel-chart/test/chart-scope.test.tsx +36 -0
  20. package/src/charts/geo-chart/geo-chart.tsx +12 -4
  21. package/src/charts/heatmap-chart/heatmap-chart.module.scss +13 -9
  22. package/src/charts/heatmap-chart/heatmap-chart.tsx +12 -5
  23. package/src/charts/leaderboard-chart/leaderboard-chart.module.scss +13 -7
  24. package/src/charts/leaderboard-chart/types.ts +0 -2
  25. package/src/charts/line-chart/line-chart.module.scss +10 -5
  26. package/src/charts/line-chart/line-chart.tsx +3 -5
  27. package/src/charts/line-chart/private/line-chart-annotation.tsx +4 -4
  28. package/src/charts/pie-chart/pie-chart.tsx +4 -1
  29. package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx +4 -1
  30. package/src/charts/private/svg-empty-state/svg-empty-state.module.scss +1 -1
  31. package/src/charts/private/test/time-axis.test.ts +247 -2
  32. package/src/charts/private/time-axis.ts +252 -63
  33. package/src/charts/private/with-responsive/test/with-responsive.test.tsx +16 -0
  34. package/src/charts/private/with-responsive/with-responsive.tsx +18 -11
  35. package/src/charts/private/x-zoom/x-zoom.module.scss +3 -3
  36. package/src/components/legend/private/base-legend.tsx +3 -1
  37. package/src/components/legend/test/legend.test.tsx +2 -1
  38. package/src/components/tooltip/accessible-tooltip.tsx +4 -2
  39. package/src/components/tooltip/base-tooltip.tsx +8 -1
  40. package/src/components/trend-indicator/test/trend-indicator.test.tsx +22 -1
  41. package/src/components/trend-indicator/trend-indicator.module.scss +3 -6
  42. package/src/components/trend-indicator/trend-indicator.tsx +3 -0
  43. package/src/hooks/test/use-chart-margin.test.tsx +60 -0
  44. package/src/hooks/test/use-xychart-theme-provider-override.test.tsx +28 -0
  45. package/src/hooks/test/use-xychart-theme-style-reads.test.tsx +89 -0
  46. package/src/hooks/test/use-xychart-theme.test.tsx +25 -0
  47. package/src/hooks/use-chart-margin.tsx +3 -4
  48. package/src/hooks/use-xychart-theme.ts +19 -11
  49. package/src/index.ts +9 -2
  50. package/src/providers/chart-context/global-charts-provider.tsx +35 -12
  51. package/src/providers/chart-context/private/theme-override-vars.ts +87 -0
  52. package/src/providers/chart-context/private/with-catalog-pointers.ts +50 -0
  53. package/src/providers/chart-context/test/chart-context.test.tsx +0 -40
  54. package/src/providers/chart-context/test/chart-scope-class.test.tsx +19 -0
  55. package/src/providers/chart-context/test/sparse-theme.test.ts +35 -0
  56. package/src/providers/chart-context/test/theme-override-vars-guard.test.tsx +29 -0
  57. package/src/providers/chart-context/test/theme-override-vars.test.ts +118 -0
  58. package/src/providers/chart-context/test/with-catalog-pointers.test.ts +47 -0
  59. package/src/providers/chart-context/themes.ts +18 -27
  60. package/src/providers/chart-context/types.ts +0 -3
  61. package/src/providers/chart-scope/chart-scope-context.ts +8 -0
  62. package/src/providers/chart-scope/index.ts +3 -0
  63. package/src/providers/chart-scope/test/chart-scope.test.tsx +24 -0
  64. package/src/providers/chart-scope/test/use-standalone-scope-class.test.tsx +20 -0
  65. package/src/providers/chart-scope/use-chart-scope-element.ts +9 -0
  66. package/src/providers/chart-scope/use-standalone-scope-class.ts +13 -0
  67. package/src/providers/index.ts +1 -0
  68. package/src/styles/chart-scope-class.ts +6 -0
  69. package/src/styles/chart-scope.scss +83 -0
  70. package/src/styles/test/chart-scope.test.ts +165 -0
  71. package/src/types.ts +6 -40
  72. package/src/utils/index.ts +1 -1
  73. package/src/utils/resolve-css-var.ts +69 -28
  74. package/src/utils/test/create-css-variable-resolver.test.ts +83 -0
  75. package/src/charts/private/grid-control/grid-control.module.scss +0 -8
  76. package/src/charts/private/grid-control/grid-control.tsx +0 -26
  77. package/src/charts/private/grid-control/index.ts +0 -1
  78. package/src/charts/private/grid-control/test/grid-control.test.tsx +0 -56
package/CHANGELOG.md CHANGED
@@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.0.0] - 2026-08-21
9
+ ### Changed
10
+ - Emit the `--a8c-charts-*` token catalog on the charts provider, so any token can be overridden in CSS anywhere inside it or through the `theme` prop, and resolve tokens against the chart element so CSS-painted and SVG-painted colors honour the same override. A `theme`-prop override keeps the reach of the field it was set from: `svgLabelSmall.fill` moves the SVG axis labels without touching legend labels or heatmap cell values, and `backgroundColor` repaints the chart background without touching tooltips, the annotation label or the zoom-reset control.
11
+
12
+ `useChartRegistration` and `useChartScopeElement` are now exported from the package root. Both were documented with a `@automattic/charts` import that did not resolve.
13
+
14
+ Breaking changes:
15
+
16
+ - An override set above `GlobalChartsProvider` — on `:root`, on `body`, or on any other ancestor — no longer applies, because the provider declares the role on its own wrapper and a declaration beats a value inherited from further up the tree. Replace `:root { --a8c-charts-… }` with `.a8c-charts-scope { --a8c-charts-… }`, which themes the whole page as before: it matches every provider wrapper, including the one a bare chart mounts for itself and the one a portal-rendered tooltip carries.
17
+ - `@wordpress/theme`'s `ThemeProvider` must sit above the charts provider rather than between it and a chart, or CSS-painted colors keep their light-mode defaults.
18
+ - The override names that predate the `--a8c-charts-{category}-{name}` convention are removed. Set `--a8c-charts-color-trend-up`, `--a8c-charts-color-trend-down` and `--a8c-charts-color-trend-neutral` in place of `--charts-trend-up-color`, `--charts-trend-down-color` and `--charts-trend-neutral-color`, and `--a8c-charts-border-radius-leaderboard-bar` in place of `--a8c--charts--leaderboard--bar--border-radius`.
19
+ - `--a8c-charts-color-focus` is removed. Focus and selection rings follow `--wpds-color-stroke-focus`, so override that token instead.
20
+ - The `GridProps` type is removed. It described a grid component that was never exported and is no longer part of the package; gridlines are drawn and coloured by the chart itself.
21
+ - `resolveThemeColor` is removed from the value returned by `useGlobalChartsContext`. It resolved against the `GlobalChartsProvider` wrapper, so it could not see an override set closer to a single chart — the reason every chart that needed a resolved color stopped calling it. Call `normalizeColorToHex( value, useChartScopeElement(), resolveCssVariable )` instead, which resolves at the scope the same override paints CSS at. `resolveCssVariable` is now exported for this. [#51308]
22
+
23
+ ## [2.0.1] - 2026-08-19
24
+ ### Changed
25
+ - Charts: adapt bar chart time-axis tick labels to the data's bucket resolution and time span, support the `tickResolution` hint, and name each bar's bucket in its tooltip. [#51274]
26
+ - Resolve an XY chart theme's color roles from a single computed-style snapshot, and rebuild the theme only when a series color changes rather than on every render. [#51342]
27
+
28
+ ### Fixed
29
+ - Charts: keep a bar chart's time axis on the buckets it actually draws, so a labelled bar, a comparison series, or a series hidden from the legend can no longer strand a tick at the axis origin, and label such a bar by its label in both the axis and the tooltip. [#51343]
30
+ - Charts: keep the year and the day on a bar chart's time axis, which could previously skip the tick that named them, and stop the same label falling on two ticks in a row. [#51339]
31
+ - Charts: measure a horizontal chart's left margin from the labels it will actually draw, so a caller's tick formatter is applied exactly once and time-of-day labels stop reserving room for the string "Invalid Date". [#51272]
32
+ - Charts: stop a bar chart's time axis dropping to a couple of ticks when it reaches for the year, and speed up how it picks them. [#51339]
33
+
8
34
  ## [2.0.0] - 2026-08-10
9
35
  ### Added
10
36
  - Time axis: Accept a tickResolution hint on the x-axis options so callers that know the data's bucket size can set tick formats directly instead of relying on inference. [#51017]
@@ -965,6 +991,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
965
991
  - Fixed lints following ESLint rule changes for TS [#40584]
966
992
  - Fixing a bug in Chart storybook data. [#40640]
967
993
 
994
+ [3.0.0]: https://github.com/Automattic/charts/compare/v2.0.1...v3.0.0
995
+ [2.0.1]: https://github.com/Automattic/charts/compare/v2.0.0...v2.0.1
968
996
  [2.0.0]: https://github.com/Automattic/charts/compare/v1.12.0...v2.0.0
969
997
  [1.12.0]: https://github.com/Automattic/charts/compare/v1.11.0...v1.12.0
970
998
  [1.11.0]: https://github.com/Automattic/charts/compare/v1.10.3...v1.11.0
package/TOKENS.md CHANGED
@@ -1,24 +1,86 @@
1
1
  # Charts CSS custom-property catalog
2
2
 
3
- `@automattic/charts` exposes its themeable values as CSS custom properties under a
4
- single convention: `--a8c-charts-{category}-{name}`. `{category}` mirrors the WPDS
5
- token type (`color`, `dimension`, `border-radius`).
3
+ `@automattic/charts` exposes its themeable values as CSS custom properties under a single convention: `--a8c-charts-{category}-{name}`. `{category}` mirrors the WPDS token type (`color`, `dimension`, `border-radius`).
6
4
 
7
- ## How it resolves today
5
+ ## How it resolves
8
6
 
9
- Nothing emits these variables at runtime yet (that is CHARTS-203). Each reference in
10
- the library carries its default inline as a fallback:
7
+ `src/styles/chart-scope.scss` declares the whole catalog once, on the `GlobalChartsProvider` wrapper, via `:where(.a8c-charts-scope)`. `:where()` keeps the rule at zero specificity, so a consumer rule targeting that same element wins without `!important`. It is declared on the wrapper rather than `:root` because `@wordpress/theme`'s `ThemeProvider` emits its generated `--wpds-*` ramp as inline styles on its own wrapper div — a `:root` declaration would miss a `ThemeProvider` entirely.
8
+
9
+ Chart roots deliberately do *not* carry the `a8c-charts-scope` class. Custom properties inherit down the tree, and an element only shadows an inherited value by re-declaring it, so a chart root that re-declared the catalog would beat an override set between it and the provider — closing off the one place consumers are meant to set overrides. This inheritance rule drives every precedence question below.
10
+
11
+ Portal-rendered tooltips carry the class unconditionally, because a React portal renders outside the provider's DOM tree and would otherwise inherit nothing. `TrendIndicator`, `BaseTooltip` and `BaseLegend` carry it only when no provider is above them (`useStandaloneScopeClass()`).
12
+
13
+ That unconditional class has a cost: a portal tooltip re-declares the catalog on itself, so it sees only the catalog *default*, never an instance override — both the provider's inline `theme` var and a consumer rule scoped to the provider wrapper live on an ancestor the portal is not a descendant of. A bare `.a8c-charts-scope { … }` rule does reach it, matching the tooltip's own class directly.
14
+
15
+ Each catalog entry maps to a WPDS token with the WPDS spec value as its fallback:
16
+
17
+ ```scss
18
+ :where(.a8c-charts-scope) {
19
+ --a8c-charts-color-grid: var(--wpds-color-stroke-surface-neutral, #dbdbdb);
20
+ }
21
+ ```
22
+
23
+ Charts reference the catalog bare — `stroke: var(--a8c-charts-color-grid)`. For anything that *is* a catalog role, `chart-scope.scss` is the only place its `--wpds-*` mapping is named, so design-system churn lands in one file. One kind of `--wpds-*` reference lives outside it, deliberately: **values that are not chart roles** — incidental typography, padding, gap and interaction motion read their design-system token directly at the call site, as interface chrome that should track the host's theme rather than charts-level theming.
24
+
25
+ ### Precedence
26
+
27
+ Highest first:
28
+
29
+ 1. The role set on any element between the chart and the provider — the closest declaration wins. A role set on the chart's *own* element reaches only what CSS paints; see "The SVG bridge".
30
+ 2. The role set by a consumer rule targeting the provider wrapper. It beats the catalog default because `:where()` is zero-specificity.
31
+ 3. The theme layer `GlobalChartsProvider` writes inline from a `theme` prop override — see below.
32
+ 4. The catalog default on the provider wrapper, resolving the mapped `--wpds-*` token.
33
+ 5. The WPDS spec-value fallback, when no `--wpds-*` token is set either (SSR, jsdom, or WPDS not loaded).
34
+
35
+ A CSS declaration of a role therefore beats a `theme` prop override *anywhere* it is set, the wrapper included — the prop writes a variable the role reads, not the role itself, and a role declared in CSS never reads it.
36
+
37
+ An override set **above** `GlobalChartsProvider` does not apply: the provider's own declaration on its wrapper beats a value merely inherited from an ancestor. Set overrides inside the provider tree, or target the scope class itself — `.a8c-charts-scope { --a8c-charts-color-grid: #e0e0e0; }` matches every provider wrapper on the page, including the one a bare chart mounts for itself and the one a portal tooltip carries, and outranks the zero-specificity catalog default. That rule is the replacement for a page-level `:root` override. The same rule limits `@wordpress/theme`'s `ThemeProvider` to *above* the charts provider: the catalog substitutes its `--wpds-*` tokens at the wrapper, so a `ThemeProvider` mounted between the wrapper and a chart is never consulted and CSS-painted colours keep their light-mode spec fallbacks. The JS-painted ones do not — `getElementStyles` resolves at the chart element — so that nesting shows up as a chart whose SVG marks retint while its gridlines and surfaces do not.
38
+
39
+ #### The theme layer
40
+
41
+ Each of the five roles a `theme` prop field can override is declared reading a `*-theme` variable first:
11
42
 
12
43
  ```scss
13
- stroke: var(--a8c-charts-color-grid, var(--wpds-color-stroke-surface-neutral, #dbdbdb));
44
+ :where(.a8c-charts-scope) {
45
+ --a8c-charts-color-grid: var(--a8c-charts-color-grid-theme, var(--wpds-color-stroke-surface-neutral, #dbdbdb));
46
+ }
14
47
  ```
15
48
 
16
- So an `--a8c-charts-*` variable you set on a chart container wins; otherwise the
17
- mapped `--wpds-*` token wins; otherwise the spec-value hex wins. Setting any
18
- `--a8c-charts-*` variable on a chart ancestor overrides that role.
49
+ `GlobalChartsProvider` writes `--a8c-charts-color-grid-theme` inline from `theme.gridStyles.stroke`. Publishing the consumer's value one layer out is what keeps the catalog default reachable: a value that is invalid at computed-value time — `var(--wpds-color-stroke-surface-neutral)` with no fallback, in a host that never loaded the WPDS stylesheet — invalidates only the theme layer, and the role still resolves its mapped token. Written as the role itself, that same value made the role guaranteed-invalid, and that propagates to every bare `var(--a8c-charts-color-grid)` read site: `stroke` computed to `unset`, so the gridlines disappeared rather than degrading to the spec grey.
50
+
51
+ A value that reads the role it would override is not published at all. The role reads its theme layer, so such a value closes a cycle through the catalog entry, and CSS marks *every* custom property in a cycle invalid — the role's own fallback is not used, and the token resolves to nothing. `withCatalogPointers` restores the theme field to the catalog pointer whether or not the value was published, so visx never paints a literal the CSS side cannot see.
52
+
53
+ `src/styles/test/chart-scope.test.ts` pins which roles carry the layer, from the same list the provider maps fields with.
54
+
55
+ #### A `theme`-prop override keeps the reach of the field it was set from
56
+
57
+ A role is a shared name, so publishing an override as a custom property could widen it — `theme={ { svgLabelSmall: { fill: 'purple' } } }` recolouring legend labels, heatmap cell values, funnel labels and the line-chart tooltip along with the SVG axis labels it names.
58
+
59
+ It doesn't, because a mapped field publishes a role read by exactly the elements that field already controlled. Where the obvious role has wider readership, one side or the other gets a role of its own:
60
+
61
+ | Theme field | Publishes | Kept off it | How |
62
+ |---|---|---|---|
63
+ | `svgLabelSmall.fill` | `--a8c-charts-color-label-axis` | legend labels, `.heatmap-chart__cell-value`, funnel labels, the line-chart tooltip | the field takes a narrow role deriving from `--a8c-charts-color-label` |
64
+ | `backgroundColor` | `--a8c-charts-color-background` | the annotation label, `.x-zoom__reset`, tooltips | those readers take `--a8c-charts-color-surface` instead |
65
+
66
+ **The two are shaped differently, and the difference is load-bearing.** `--a8c-charts-color-label-axis` *derives* from `--a8c-charts-color-label`: the theme field publishes the narrow role, so the broad one stays free as a move-every-label knob. `--a8c-charts-color-surface` is a **sibling** of `--a8c-charts-color-background`, not a child — there the theme field publishes the broad role, so deriving would hand the override straight back to the surfaces it is meant to spare. Deriving is only safe when the narrow role is the one the `theme` prop writes.
67
+
68
+ The consequence: `--a8c-charts-color-label` moves every label, but no single role repaints the chart background and the floating surfaces together.
69
+
70
+ `gridStyles.stroke`, `xAxisLineStyles.stroke` and `xTickLineStyles.stroke` need no narrow role — nothing outside the element each names reads their role.
71
+
72
+ ### The SVG bridge
73
+
74
+ visx and Google Charts apply colours as SVG presentation attributes, where `var()` does not resolve. Those colours are resolved in JS through `getComputedStyle` against the chart's own scope element — never `document.documentElement` — so both delivery paths obey the same cascade. The JS theme in `themes.ts` therefore holds a bare catalog pointer with a terminal literal (`var(--a8c-charts-color-grid, #dbdbdb)`); the literal is the last resort for SSR and jsdom, where `getComputedStyle` resolves nothing.
75
+
76
+ The scope element is the wrapper a chart is rendered into, which sits **above** the element the chart's own `className` lands on. A role declared on that inner element is therefore invisible to this bridge: `.line-chart { --a8c-charts-color-grid: red }` recolours what the chart paints in CSS and leaves the gridlines, axis lines and tick labels at the inherited value, because the SVG carries a value already resolved higher up. Scope such a rule to a wrapper around the chart, not to the chart itself. CHARTS-255 tracks closing this.
77
+
78
+ `GeoChart` (Google Charts) takes a resolved-hex snapshot at render, so it does not live-update on a theme change without a re-render.
19
79
 
20
80
  ## Tier 1 — semantic catalog (shared, themeable roles)
21
81
 
82
+ > These tables are checked against `src/styles/chart-scope.scss` by `src/styles/test/chart-scope.test.ts`. Update the stylesheet and the table together.
83
+
22
84
  | Role | Maps to `--wpds-*` | Fallback |
23
85
  |---|---|---|
24
86
  | `--a8c-charts-color-grid` | `--wpds-color-stroke-surface-neutral` | `#dbdbdb` |
@@ -27,64 +89,61 @@ mapped `--wpds-*` token wins; otherwise the spec-value hex wins. Setting any
27
89
  | `--a8c-charts-color-label` | `--wpds-color-foreground-content-neutral` | `#1e1e1e` |
28
90
  | `--a8c-charts-color-label-secondary` | `--wpds-color-foreground-content-neutral-weak` | `#707070` |
29
91
  | `--a8c-charts-color-label-inverse` | `--wpds-color-foreground-interactive-neutral-strong` | `#f0f0f0` |
30
- | `--a8c-charts-color-label-on-fill` | _(none — white-on-series-fill, no WPDS fit)_ | `#FFFFFF` |
92
+ | `--a8c-charts-color-label-on-fill` | _(none — white-on-series-fill, no WPDS fit)_ | `#fff` |
93
+ | `--a8c-charts-color-label-axis` | _(derives from `--a8c-charts-color-label`)_ | — |
31
94
  | `--a8c-charts-color-annotation` | `--wpds-color-foreground-content-neutral` | `#1e1e1e` |
32
95
  | `--a8c-charts-color-trend-up` | `--wpds-color-foreground-content-success-weak` | `#008030` |
33
96
  | `--a8c-charts-color-trend-down` | `--wpds-color-foreground-content-error-weak` | `#cc1818` |
34
97
  | `--a8c-charts-color-trend-neutral` | `--wpds-color-foreground-content-neutral-weak` | `#707070` |
35
98
  | `--a8c-charts-color-background` | `--wpds-color-background-surface-neutral-strong` | `#fff` |
99
+ | `--a8c-charts-color-surface` | `--wpds-color-background-surface-neutral-strong` | `#fff` |
36
100
  | `--a8c-charts-color-surface-secondary` | `--wpds-color-background-surface-neutral-weak` | `#f4f4f4` |
37
101
  | `--a8c-charts-color-track` | `--wpds-color-background-track-neutral-weak` | `#f0f0f0` |
38
- | `--a8c-charts-color-tooltip-surface` | _(none — translucent dark surface, no WPDS fit)_ | `rgba(0,0,0,0.85)` |
39
- | `--a8c-charts-color-focus` | `--wpds-color-stroke-focus` | `#3858e9` |
102
+ | `--a8c-charts-color-tooltip-surface` | _(none — translucent dark surface, no WPDS fit)_ | `rgb(0 0 0 / 85%)` |
103
+
104
+ Axis and tick share grid's WPDS token but stay distinct roles, so the three can be themed independently.
40
105
 
41
- `--a8c-charts-color-axis` (axis line) and `--a8c-charts-color-tick` (tick marks)
42
- resolve to the same value as `--a8c-charts-color-grid` by default. They are kept as
43
- distinct roles so axis, tick marks, and gridlines can be themed independently; each
44
- maps directly to its own `--wpds-*` token rather than chaining through `grid`.
106
+ ## Non-colour roles
107
+
108
+ | Role | Maps to `--wpds-*` | Fallback |
109
+ |---|---|---|
110
+ | `--a8c-charts-motion-duration-entrance` | `--wpds-motion-duration-xl` | `400ms` |
111
+ | `--a8c-charts-motion-easing-entrance` | `--wpds-motion-easing-expressive` | `cubic-bezier(0.25, 0, 0, 1)` |
112
+ | `--a8c-charts-border-radius-bar` | `--wpds-border-radius-md` | `4px` |
113
+ | `--a8c-charts-border-radius-cell` | `--wpds-border-radius-sm` | `2px` |
114
+ | `--a8c-charts-border-radius-leaderboard-bar` | _(none — pill shape, no WPDS radius fits)_ | `9999px` |
115
+ | `--a8c-charts-elevation-xs` | _(none — `--wpds-elevation-*` removed in theme 1.0.0)_ | `0 1px 1px 0 #00000008, 0 1px 2px 0 #00000005, 0 3px 3px 0 #00000005, 0 4px 4px 0 #00000003` |
116
+ | `--a8c-charts-elevation-sm` | _(none — `--wpds-elevation-*` removed in theme 1.0.0)_ | `0 1px 2px 0 #0000000d, 0 2px 3px 0 #0000000a, 0 6px 6px 0 #00000008, 0 8px 8px 0 #00000005` |
117
+
118
+ The motion pair carries the one-shot reveal a data mark plays on first paint, across all six charts that animate in. It deliberately does **not** cover interaction motion: hover and transition timings read `--wpds-motion-*` directly, as interface chrome rather than a chart role.
119
+
120
+ The elevation fallbacks hold the values their removed `--wpds-elevation-*` tokens used to resolve to, until a replacement exists.
45
121
 
46
122
  ## Tier 2 — component-specific variables
47
123
 
48
- Instance styling knobs, on the same convention but not shared semantic roles:
49
- `--a8c-charts-border-radius-leaderboard-bar`,
50
- `--a8c-charts-dimension-leaderboard-bar-hover-inset`,
51
- `--a8c-charts-color-heatmap-*`, `--a8c-charts-dimension-heatmap-*`,
52
- `--a8c-charts-heatmap-cell-intensity`,
53
- `--a8c-charts-color-zoom-selection`, `--a8c-charts-color-zoom-selection-stroke`,
54
- `--a8c-charts-elevation-xs`.
124
+ Instance styling knobs, on the same convention but not shared semantic roles: `--a8c-charts-dimension-leaderboard-bar-hover-inset`, `--a8c-charts-color-heatmap-*`, `--a8c-charts-dimension-heatmap-*`, `--a8c-charts-heatmap-cell-intensity`, `--a8c-charts-color-zoom-selection`, `--a8c-charts-color-zoom-selection-stroke`.
55
125
 
56
126
  | Role | Maps to `--wpds-*` | Fallback |
57
127
  |---|---|---|
58
128
  | `--a8c-charts-color-zoom-selection` | `--wpds-color-background-interactive-brand-strong` | `#3858e9` |
59
129
  | `--a8c-charts-color-zoom-selection-stroke` | `--wpds-color-stroke-interactive-brand` | `#3858e9` |
60
- | `--a8c-charts-elevation-xs` | _(none — `--wpds-elevation-*` removed in theme 1.0.0)_ | `0 1px 1px 0 #00000008, 0 1px 2px 0 #00000005, 0 3px 3px 0 #00000005, 0 4px 4px 0 #00000003` |
61
130
 
62
- The zoom selection roles carry the drag-to-zoom rectangle's fill and border. Their
63
- translucency is not part of the role: it lives in the `fill-opacity` /
64
- `stroke-opacity` properties, so overriding either role sets an opaque colour and
65
- keeps the intended transparency.
131
+ The zoom selection roles' translucency is not part of the role — it lives in `fill-opacity` / `stroke-opacity`, so an override sets an opaque colour and keeps the intended transparency.
66
132
 
67
- `--a8c-charts-elevation-xs` carries the zoom reset button's shadow. It has no
68
- `--wpds-*` mapping: `@wordpress/theme` 1.0.0 removed the whole
69
- `--wpds-elevation-*` group without a replacement, so the fallback holds the value
70
- `--wpds-elevation-xs` used to resolve to.
133
+ `--a8c-charts-heatmap-cell-intensity` is the one variable without a `{category}` segment: it holds a unitless 0–1 scalar consumed inside `color-mix()`, not a colour.
71
134
 
72
- `--a8c-charts-heatmap-cell-intensity` is the one variable without a `{category}`
73
- segment: it holds a unitless 0–1 scalar consumed inside `color-mix()`, not a colour.
135
+ The heatmap Tier-2 variables and `--a8c-charts-dimension-leaderboard-bar-hover-inset` are **component-emitted** — set from JS per render, or in the component's own stylesheet — rather than on the provider wrapper. They are deliberately absent from `chart-scope.scss` and are not consumer override points in the same sense as the catalog above.
74
136
 
75
- The heatmap Tier-2 variables (`--a8c-charts-color-heatmap-*`,
76
- `--a8c-charts-dimension-heatmap-*`, `--a8c-charts-heatmap-cell-intensity`) are
77
- **component-emitted** — the chart sets them from JS per render — not consumer
78
- override points.
137
+ ## Removed override variables
79
138
 
80
- ## Public override variables
139
+ Every role in the catalog is a supported override point, on the precedence rules above. These names are not, and no longer resolve — set the replacement instead:
81
140
 
82
- These are documented, supported override points. Deprecated names still work — they
83
- are read as an inner fallback behind the new name:
84
-
85
- | New | Deprecated alias |
141
+ | Removed | Set instead |
86
142
  |---|---|
87
- | `--a8c-charts-color-trend-up` | `--charts-trend-up-color` |
88
- | `--a8c-charts-color-trend-down` | `--charts-trend-down-color` |
89
- | `--a8c-charts-color-trend-neutral` | `--charts-trend-neutral-color` |
90
- | `--a8c-charts-border-radius-leaderboard-bar` | `--a8c--charts--leaderboard--bar--border-radius` |
143
+ | `--charts-trend-up-color` | `--a8c-charts-color-trend-up` |
144
+ | `--charts-trend-down-color` | `--a8c-charts-color-trend-down` |
145
+ | `--charts-trend-neutral-color` | `--a8c-charts-color-trend-neutral` |
146
+ | `--a8c--charts--leaderboard--bar--border-radius` | `--a8c-charts-border-radius-leaderboard-bar` |
147
+ | `--a8c-charts-color-focus` | `--wpds-color-stroke-focus` |
148
+
149
+ Removing the first four also removes a second name for a role, read at its component's own call site rather than through the catalog: each sat inside the role as its fallback — `var(--a8c-charts-*, var(--deprecated-name, …))` — so it applied only where the role itself was unset. No `--a8c-charts-*` role is now read anywhere but bare.