Charts: Replace hardcoded typography with WPDS design tokens#47989
Charts: Replace hardcoded typography with WPDS design tokens#47989adamwoodnz merged 20 commits intotrunkfrom
Conversation
|
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.
Interested in more tips and information?
|
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖 Follow this PR Review Process:
If you have questions about anything, reach out in #jetpack-developers for guidance! |
Code Coverage SummaryCoverage changed in 2 files.
1 file is newly checked for coverage.
|
projects/js-packages/charts/src/charts/conversion-funnel-chart/stories/index.docs.mdx
Outdated
Show resolved
Hide resolved
...ts/js-packages/charts/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss
Outdated
Show resolved
Hide resolved
...ts/js-packages/charts/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss
Outdated
Show resolved
Hide resolved
projects/js-packages/charts/src/charts/line-chart/line-chart.module.scss
Outdated
Show resolved
Hide resolved
...ts/js-packages/charts/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss
Outdated
Show resolved
Hide resolved
projects/js-packages/charts/src/providers/chart-context/themes.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Replace hardcoded typography across @automattic/charts with WPDS CSS custom property tokens (--wpds-font-*) so consuming products can control typography centrally.
Changes:
- Update multiple chart/component SCSS modules to use WPDS font family/size/weight/line-height tokens with fallbacks.
- Adjust PieChart label sizing logic to derive SVG label font size from the theme when estimating label background width.
- Update Storybook docs/stories to reflect the new WPDS token-based typography approach and add a changelog entry.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| projects/js-packages/charts/src/components/trend-indicator/trend-indicator.module.scss | Switch trend indicator typography to WPDS token-based font size/weight. |
| projects/js-packages/charts/src/components/tooltip/base-tooltip.module.scss | Switch tooltip font-size to WPDS token with fallback. |
| projects/js-packages/charts/src/components/legend/private/base-legend.module.scss | Switch legend font-size/weight to WPDS tokens with fallbacks. |
| projects/js-packages/charts/src/charts/sparkline/sparkline.module.scss | Add WPDS-based font-family for sparkline container. |
| projects/js-packages/charts/src/charts/pie-semi-circle-chart/stories/index.docs.mdx | Update docs to describe WPDS token-driven label/note typography. |
| projects/js-packages/charts/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.module.scss | Move label/note typography to WPDS tokens with fallbacks. |
| projects/js-packages/charts/src/charts/pie-chart/pie-chart.tsx | Use themed SVG label font size when estimating label background width. |
| projects/js-packages/charts/src/charts/pie-chart/pie-chart.module.scss | Add WPDS-based font-family for pie chart container. |
| projects/js-packages/charts/src/charts/line-chart/line-chart.module.scss | Add WPDS-based font-family and update tooltip/annotation typography tokens. |
| projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.stories.tsx | Remove hardcoded fontFamily from story inline styles. |
| projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.docs.mdx | Remove hardcoded font-family examples from docs. |
| projects/js-packages/charts/src/charts/leaderboard-chart/leaderboard-chart.module.scss | Add WPDS-based font-family and tokenized empty state font-size. |
| projects/js-packages/charts/src/charts/geo-chart/geo-chart.module.scss | Add WPDS-based font-family to geo chart container. |
| projects/js-packages/charts/src/charts/conversion-funnel-chart/stories/index.docs.mdx | Remove docs for old font custom properties and keep theming guidance. |
| projects/js-packages/charts/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss | Replace funnel/step font custom properties with WPDS tokens and fallbacks. |
| projects/js-packages/charts/src/charts/bar-chart/bar-chart.module.scss | Add WPDS-based font-family to bar chart container. |
| projects/js-packages/charts/changelog/charts-typography-tokenization | Add changelog entry for typography tokenization. |
projects/js-packages/charts/src/components/trend-indicator/trend-indicator.module.scss
Show resolved
Hide resolved
projects/js-packages/charts/src/components/legend/private/base-legend.module.scss
Show resolved
Hide resolved
projects/js-packages/charts/src/charts/line-chart/line-chart.module.scss
Show resolved
Hide resolved
projects/js-packages/charts/src/charts/line-chart/line-chart.module.scss
Show resolved
Hide resolved
projects/js-packages/charts/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.module.scss
Show resolved
Hide resolved
projects/js-packages/charts/src/charts/bar-chart/bar-chart.module.scss
Outdated
Show resolved
Hide resolved
...ts/js-packages/charts/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss
Show resolved
Hide resolved
...ts/js-packages/charts/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss
Show resolved
Hide resolved
...ts/js-packages/charts/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss
Outdated
Show resolved
Hide resolved
|
Thanks for the review, Copilot. Consolidating responses to several related comments in this thread:
|
Replace all hardcoded font-family, font-size, font-weight, and line-height values across chart SCSS modules and components with WPDS (WordPress Design System) CSS custom property tokens (--wpds-font-*). SCSS modules updated: - conversion-funnel-chart: Replace SF Pro font families with --wpds-font-family-body, all font sizes with --wpds-font-size-*, weights with --wpds-font-weight-*, and line heights with --wpds-font-line-height-* - line-chart: Tokenize tooltip font-weight and annotation popover font-size - base-legend: Tokenize legend item font-size and value font-weight - base-tooltip: Tokenize tooltip font-size - pie-semi-circle-chart: Tokenize label font-weight/size and note font-size - trend-indicator: Tokenize font-size and font-weight - leaderboard-chart: Tokenize empty state font-size Theme/component updates: - Default theme svgLabelSmall: Add fontFamily token for SVG text elements - pie-chart: Wire SVG label fontSize/fontFamily through theme.svgLabelSmall - Leaderboard story: Remove hardcoded SF Pro Text fontFamily override Documentation updates: - conversion-funnel-chart docs: Replace --funnel-font-family/--step-font-family with --wpds-font-family-body - leaderboard-chart docs: Replace font-family examples with WPDS tokens - pie-semi-circle-chart docs: Reference WPDS tokens for label/note typography All tokens use current values as fallbacks to preserve visual backward compatibility when WPDS tokens are not provided by the host environment.
WPDS tokens should be set through ThemeProvider, not raw CSS overrides. Remove the entire section per review feedback.
Per review feedback, use only sans-serif as the fallback for --wpds-font-family-body instead of SF Pro or system font stacks. Also remove WPDS token override from leaderboard CSS docs example.
…on funnel font-family is an inherited CSS property, so child elements within .conversion-funnel-chart inherit it from the top-level selector. Removed the redundant declarations from .main-rate, .change-indicator, .step-label, .step-rate, .tooltip-title, and .tooltip-content. Kept font-family on .tooltip-wrapper since tooltips render in a visx portal outside the .conversion-funnel-chart DOM tree.
WPDS only provides --wpds-font-weight-regular (400) and --wpds-font-weight-medium (499). There are no tokens for semibold (600) or bold (700), so these should remain hardcoded rather than being incorrectly mapped to --wpds-font-weight-medium.
Use only weights available in the design system: - --wpds-font-weight-medium with fallback 499 - --wpds-font-weight-regular with fallback 400 Previous 500, 600, and 700 values are all mapped to medium (499) to match the WPDS token definitions.
Apply font-family: var(--wpds-font-family-body, sans-serif) to the outer selector of all chart SCSS modules so every chart opts in to the WPDS font-family token. Children inherit automatically. Charts updated: bar-chart, geo-chart, leaderboard-chart, line-chart, pie-chart, pie-semi-circle-chart, sparkline. (conversion-funnel-chart already had it.)
The fontFamily on svgLabelSmall was redundant: inline SVG <text> elements inherit font-family from their parent HTML element via CSS inheritance. Now that every chart root selector sets font-family: var(--wpds-font-family-body, sans-serif), all SVG text inside those charts inherits it automatically. Also removes the explicit fontFamily prop from the pie chart's slice label <text> element for the same reason.
…aphy The label background width previously called getStringWidth with only the numeric fontSize, silently falling back to 12 when svgLabelSmall.fontSize was a string like '12px', and never passed fontFamily or fontWeight. Export resolveFontSize from use-chart-margin so it can be reused, then use it in PieChart and pass fontFamily/fontWeight through to getStringWidth so the measured background matches the rendered label. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Re-add --funnel-font-family and --step-font-family as fallbacks in the ConversionFunnelChart cascade so consumers already setting either variable continue to get their custom font. --wpds-font-family-body takes precedence when set. Both variables are now documented as deprecated in the Storybook docs and will be removed in a future release. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Remove the separate pie-chart and conversion-funnel changelog entries added alongside the recent fixes. Their contents are covered by the existing charts-typography-tokenization entry, which is the single changelog entry for this PR. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…chart roots Chart components should not dictate their own font-family — that is the host application's responsibility. Previously each chart module declared font-family: var(--wpds-font-family-body, sans-serif) at its root, which silently overrode the host's typography cascade whenever --wpds-font-family-body was not defined. Remove the declaration from every chart root (bar, line, pie, pie-semi-circle, sparkline, geo, leaderboard, conversion-funnel) and from the conversion-funnel tooltip-wrapper. Charts now inherit the font-family set by the host page or component, which is the standard UI component convention. Also drop the short-lived backward-compatibility layer for the deprecated --funnel-font-family and --step-font-family custom properties and its docs section, since with no font-family at the chart root there is no longer a natural home for the fallback chain. Consumers relying on the implicit sans-serif fallback will now inherit from their host page. Consumers relying on the deprecated funnel custom properties should set font-family on an ancestor element (typically body) via their own theme layer. Storybook now sets body font-family to --wpds-font-family-body, acting as a WPDS-themed host so stories render with the design system font without the chart components themselves declaring it. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The previous commit set body font-family in the shared Storybook SCSS, which would have affected every package's stories. Move the rule to a .charts-storybook-host wrapper applied by a decorator that only fires for stories titled under "JS Packages/Charts Library", so charts still render with the design system font without leaking typography changes into other packages' stories. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
507a361 to
393ceb5
Compare
…rator The previous commit applied the WPDS body font via a decorator and CSS class in the shared Storybook preview. That worked but put charts-specific concerns into code shared with every other package's stories. Move the host-app font-family wrapper into the charts package's own shared decorator (StoryChartProvider, which backs both chartDecorator and simpleChartDecorator). Charts stories now render inside a div with font-family: var(--wpds-font-family-body, system-ui, sans-serif) without touching the shared storybook preview.jsx or style.scss. Revert the shared Storybook changes from the previous commit so the host-app simulation lives entirely in the charts package. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
393ceb5 to
f8be364
Compare
resolveFontSize was defined locally inside use-chart-margin and then re-exported through the hooks barrel so pie-chart could reuse it for label sizing. Now that there are multiple call sites, move it into its own file under src/utils alongside the other chart helpers and export it from the utils barrel. Drop the re-export from the hooks barrel and update pie-chart to import directly from utils. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
|
@claude review please |
|
Claude finished @adamwoodnz's task in 4m 25s —— View job Code Review
Overall this is well-executed. The tokenization is thorough, the architecture decision to inherit font-family from the host is sound, and the Medium:
|
kangzj
left a comment
There was a problem hiding this comment.
Looks good and tests well. A big step forward 👍
visx's buildChartTheme injects a hardcoded font stack (-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif) into every axis tickLabel and axisLabel style, which visx's Axis components then apply as an inline style on SVG <text> elements. Inline styles beat inherited CSS, so axis text was silently ignoring the host application's font-family cascade regardless of what the chart roots did. Set fontFamily: 'inherit' on svgLabelSmall and svgLabelBig in the default theme so the inline value emitted by visx is 'inherit', letting SVG text actually pick up the host's font-family via normal CSS inheritance — consistent with the rest of this PR's decision that chart components should not dictate typography. Expose svgLabelBig on ChartTheme so it can be overridden alongside svgLabelSmall. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Earlier in this PR we standardized on a single sans-serif fallback for --wpds-font-family-body across every chart SCSS module. The Storybook decorator drifted from that policy by including system-ui in the middle of the chain. Align it with the rest of the PR so the fallback policy is consistent everywhere the variable is used. The fallback is essentially defensive — design-tokens.css is imported unconditionally by Storybook's preview, so the var should always resolve in practice. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The same WPDS token was being used with three different fallback values across the package: 13px (conversion-funnel, svg-empty-state), 14px (line-chart, leaderboard, base-tooltip, pie-semi-circle), and 0.875rem (trend-indicator, base-legend). When WPDS tokens are present they all resolve to the same canonical value, but in no-WPDS environments the inconsistency produced visibly different sizes between adjacent components in the same chart. Standardize on 13px — the actual WPDS design system value for --wpds-font-size-md — so the fallback matches the token everywhere and matches the policy already used by the conversion funnel and empty state. Update the pie-semi-circle docs to reflect the new default. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The previous implementation used parseFloat() on any string input, which silently accepted relative units like 0.875rem and returned the unitless prefix (0.875). Callers in use-chart-margin and pie-chart would then treat that as a pixel value, producing nearly-zero margins or invisible label backgrounds. Tighten the parser to accept only plain numeric strings and pixel values, rejecting rem, em, %, vh, vw, and CSS keywords like inherit or medium. The function now matches its JSDoc contract: returns undefined for any value it cannot reliably resolve to absolute pixels, so callers fall back to their own defaults. Add a dedicated unit test file covering numeric input, pixel strings, whitespace trimming, NaN, undefined, empty strings, unparseable input, and the previously-accepted relative units that should now be rejected. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The id was added as a label of intent for the host-app font wrapper div, but Storybook docs pages render multiple stories side-by-side in the same DOM, which would produce duplicate id attributes — invalid HTML and a potential selector collision. The wrapper's purpose is documented by the adjacent comment, so the id is unnecessary. Remove it. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
|
Thanks for the review @claude! Addressed in three follow-up commits:
Medium Minor observation about All 853 tests pass. |
|
Claude finished @adamwoodnz's task in 1m 5s —— View job Follow-up Review
All three fixes confirmed correct. Here's what I checked: Medium #1 — Every Low #1 — Low #2 — Medium #2 skip — Agreed. This is ready to merge. |
Fixes: CHARTS-198
Proposed changes
Replace hardcoded typography values across
@automattic/chartswith WPDS (WordPress Design System) CSS custom property tokens (--wpds-font-*), so consumers (Jetpack, Woo, Newspack, etc.) can control chart typography centrally through their design system.This PR also corrects a related architectural issue: chart components should not dictate their own
font-family— they should inherit it from the host application's cascade. The original version of this PR addedfont-family: var(--wpds-font-family-body, sans-serif)to every chart root, which silently overrode host typography whenever the token wasn't defined. That has been reverted; charts now inherit typography the same way any well-behaved UI component does.Token mapping
--wpds-font-family-body--wpds-font-size-sm12px--wpds-font-size-md13px--wpds-font-size-md14px--wpds-font-size-lg16px--wpds-font-size-xl18px--wpds-font-weight-regular400--wpds-font-weight-medium499--wpds-font-line-height-xs16px--wpds-font-line-height-sm20pxOn the
499medium fallback:499is the exact value defined by the WPDS token, not a typo. The fallback is intentionally aligned with the design system value rather than the previous500hardcode.On font weights generally: The previous code used arbitrary weights (
500,600,700) in various places. The WPDS design system only providesregularandmediumfor body-level typography, so this PR deliberately collapses all of those tomedium. This is a small visual change in a few labels/tooltips where text was previously bold; it is intentional alignment with the design system rather than a regression.Typography scope (chart components do not set font-family)
Chart components intentionally do not declare
font-familyat their root. Hosts are expected to set typography at a suitable ancestor (typicallybody), and charts inherit it via normal CSS cascade. This matches how every other well-behaved UI component works and gives the host complete control.For SVG
<text>elements — which inheritfont-familyfrom their closest HTML ancestor via standard CSS inheritance — no special handling is required.For portaled tooltips (which escape the chart's DOM tree via visx's
TooltipInPortal), the portal mounts todocument.bodyand inherits from whatever the host sets there. The same rule applies: the host owns typography.Storybook host simulation
Because charts no longer declare
font-familyat the root, Storybook needs to act as a WPDS-themed host application so stories render with the design system font. This is done inside the charts package's ownStoryChartProvider(insrc/stories/chart-decorator.tsx), which wraps stories in a<div style={{ fontFamily: 'var(--wpds-font-family-body, system-ui, sans-serif)' }}>. The shared Jetpack Storybookpreview.jsxis untouched.PieChart label background sizing fix
While reviewing typography, we discovered that
PieChartwas measuring SVG label widths with only a numericfontSize— falling back to12wheneverproviderTheme.svgLabelSmall?.fontSizewas a string (e.g.'12px') — and never passingfontFamilyorfontWeighttogetStringWidth. This produced incorrect label background rectangles for themed pie charts.The numeric fallback logic previously lived inside
use-chart-marginas a private helper. It has been extracted into a shared utility (src/utils/resolve-font-size.ts) and is now used by bothuse-chart-marginandPieChart, which also passesfontFamilyandfontWeightthrough togetStringWidthfor accurate measurement.Breaking changes to be aware of
Two previously-documented custom properties on
ConversionFunnelCharthave been removed:--funnel-font-family--step-font-familyThese are replaced by the standard host-app convention of setting
font-familyon an ancestor element. Consumers who were setting either variable should migrate to settingfont-family(or--wpds-font-family-body) on an ancestor such asbody.Files changed
SCSS modules:
conversion-funnel-chart.module.scss— Typography tokenized; removed deprecated--funnel-font-family/--step-font-family; removedfont-familyfrom root and child selectors.line-chart.module.scss— Typography tokenized.pie-semi-circle-chart.module.scss— Typography tokenized.base-legend.module.scss— Typography tokenized.base-tooltip.module.scss— Typography tokenized.trend-indicator.module.scss— Typography tokenized.leaderboard-chart.module.scss— Typography tokenized.TypeScript:
pie-chart.tsx— Uses sharedresolveFontSizeand passesfontFamily/fontWeighttogetStringWidthfor accurate SVG label measurement.use-chart-margin.tsx— ImportsresolveFontSizefrom the shared utility.utils/resolve-font-size.ts— New shared utility for parsingnumber | stringfontSize values from themes.utils/index.ts— ExportsresolveFontSize.stories/chart-decorator.tsx— Wraps chart stories in a host-app<div>with--wpds-font-family-bodyso Storybook acts as a WPDS-themed host.Docs / stories:
font-familyexamples.Does this pull request change what data or activity we track or use?
No.
Testing instructions
pnpm jetpack test js js-packages/charts— 841 tests pass.pnpm jetpack build js-packages/charts— build succeeds;dist/index.csscontains--wpds-font-*tokens.--wpds-font-family-bodyatbodyor an ancestor overrides the font as expected.bodyfont correctly.PieChartlabel backgrounds size correctly whensvgLabelSmall.fontSizeis provided as a string like'12px'.