[Lens] Enable monospace numeric font features for Lens renderers#251576
[Lens] Enable monospace numeric font features for Lens renderers#251576awahab07 merged 21 commits into
Conversation
|
Pinging @elastic/kibana-visualizations (Team:Visualizations) |
|
Thank you @awahab07 for putting this together, it looks amazing! I noticed a few details which in some cases are directly related to these features and in other cases are a consequence, let me explain.
There is one additional caveat here, this detail should be applied only when labels are purely numbers because otherwise we would reduce the spacing on letters too. I know this is an additional complexity that probably does not need to be solved here, rather at components side (an example is Metric Chart values, we should introduce this additional css setting directly at the component, not in this PR)
Happy to talk about these in person if that is easier, thank you again Abdul! |
This happens because the canvas used to compute the text width in Charts doesn't have the same font variables applied. Thus the calculation consider just the classic Inter font config and sizes.
|
|
@tkajtoch sorry to bother, can we ask you one thing? do you maybe know something about the first point of my message above? For some reason the number 1 digit does not get monospaced features applied. We had the same issue when we tested together and it got solved by the update of font version, and actually in your EUI pr it works fine I can't figure it out and I figured it might have worth to ask before going into a rabbit hole :) |
|
@elasticmachine merge upstream |
Inter v3, which is currently used by Kibana (specifically In order to inspect available font features, drag the file onto https://wakamaifondue.com/beta/ and it'll show available font features
For visual difference when upgrading to v4 from v3, font author says:
See how do we want to proceed here. |
|
About the issue mentioned above: There's PR elastic/elastic-charts#2798 which uses in-Dom Canvas (instead of off-screen Canvas) to measure text. This works quite well, but discovered a limitation that Canvas element in Firefox does not support OpenType Font Features like |
|
thanks @awahab07, two points here: 1 - Version 4 of Inter font. @markov00 reached out to EUI again since they had a PR for this, they re-opemn it (#242012) and we can probably review and approve it. It should fix all these issues and it would be awesome 2 - Firefox bug. I am afraid we can't avoid it, Marco was suggesting a little trick, to add a few pixel to the calculation. If the math return us a value of 100px of length, let's by default add a few pixels in order for that to fix the problem with a little hack. I hope I explained that properly, we can discuss it together with Marco as well maybe so that we evaluate that |
|
I’ve filed a bug with Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=2024179. If it gets fixed on their side, that would be ideal and we can avoid introducing any workarounds. |
|
The WHATWG's Canvas Text Propagation Algorithm doesn't mention propagating OpenType font features, and as a result Firefox doesn't implement it (and may not implement unless it's part of the standard). There's a WHATWG discussion about enabling OpenType font features for Canvas (explicit way of defining font attributes for Canvas), but doesn't seem like it'll be dealt with anytime soon. This is a major blocker, that on Firefox, all Canvas based charts cannot render OpenType font features. |
- Ensure legacy metric chart and tag cloud uses "Elastic UI Numeric".
…monospaced-font-in-charts
|
Cloud deployment initiated, see credentials at: https://buildkite.com/elastic/kibana-deploy-cloud-from-pr/builds/896 |
|
|
||
| it('should render tagcloud', async () => { | ||
| const tags = await tagCloud.getTextTag(); | ||
| expect(tags).to.eql([ |
| 'RangeKey no label auto assigned - Tag Cloud' | ||
| ); | ||
|
|
||
| expect(seriesColors).to.eql([ |
💛 Build succeeded, but was flaky
Failed CI StepsTest Failures
Metrics [docs]Module Count
Async chunks
Page load bundle
History
|
markov00
left a comment
There was a problem hiding this comment.
Tested locally, looks great!
jloleysens
left a comment
There was a problem hiding this comment.
Nice work @awahab07 ! I've left a comment regarding tests, otherwise code-only review from core lgtm.
| unicode-range: ${unicodeRange};` | ||
| : '' | ||
| } | ||
| ${fontFaceRules.join('\n ')} |
There was a problem hiding this comment.
I'm a little surprised there's no test case for this yet... would you mind adding one? Thank you!
There was a problem hiding this comment.
Thanks for pointing this out @jloleysens, I've opened a PR #262103.
…stic#251576) Closes elastic#249382 ## Summary Enable monospaced numeric rendering for Lens charts (axis labels, legend values, data labels, tooltips) by introducing a **numeric-only font** (`"Elastic UI Numeric"`) with the required OpenType features **baked into the glyphs**, and using it as the **first font in the elastic-charts font stack**. An earlier CSS-only approach (`font-feature-settings` / `font-variant-numeric`) which works in Chromium/WebKit but is **not supported for canvas text in Firefox**, has been discarded in favor of the pre-baked `"Elastic UI Numeric"` font (`src/core/packages/apps/server-internal/assets/fonts/elastic_ui_numeric/ElasticUINumeric-Variable.woff2` has all the required numeric features pre-applied). With the new approach, `"Elastic UI Numeric"` will also work for charts which don't use Inter as the base font e.g. **Legacy Metric** chart or **Tag cloud** . ## Implementation - **Added `Elastic UI Numeric` font (≈8KB WOFF2)**: - Derived from Inter (OFL 1.1), **subset to digits + common punctuation** via `unicode-range` - Features baked in: **`tnum`, `zero`, `ss01`, `ss07`** - **Registered `@font-face` globally** in core rendering (`Fonts` template) so Kibana can serve/load it. - **Prepended `'Elastic UI Numeric'` to all elastic-charts `fontFamily` values** in the shared charts `ThemeService`, ensuring all charts under Lens use it as the preferred font. - **Applied the same font stack for Lens DOM + tooltip portals** (`.lnsExpressionRenderer` and `[id^='echTooltipPortal']`) so non-canvas elements/tooltips inherit it too. ## Licensing `Elastic UI Numeric` is a **modified version of Inter** licensed under **SIL OFL 1.1**. - OFL text is included in `src/core/packages/apps/server-internal/assets/fonts/elastic_ui_numeric/LICENSE.txt` - We do **not** use Inter’s Reserved Font Name as the font family name, and the font’s internal naming is updated accordingly. - References: - Upstream OFL text: [Inter LICENSE.txt](https://raw.githubusercontent.com/rsms/inter/master/LICENSE.txt) - Google Fonts page (also OFL): [Inter license](https://fonts.google.com/specimen/Inter/license) ## Testing This [dashboard](https://kibana-pr-251576-16eb8c.kb.us-west2.gcp.elastic-cloud.com/app/dashboards#/view/43090e2b-ba4e-4c1e-94a9-18e9c97295f4) can be used for testing ([creds](elastic#251576 (comment))). ## Visuals <img width="2400" height="7200" alt="Lens-charts-and-Elastic_UI_Numeric-font" src="https://github.com/user-attachments/assets/4cc07dd3-6d45-468d-af04-156f7be5966f" /> <details> <summary> <h4>Before / After</h4> </summary> | Before | After | |--------|-------| | <img width="400" alt="metric-charts-before" src="https://github.com/user-attachments/assets/33d547f0-b8f0-42fd-a37b-7ef20a5d05ee" /> | <img width="400" alt="Metric-charts-after" src="https://github.com/user-attachments/assets/0d6e3738-14db-4eb7-af77-5717bdcc1377" /> | | <img width="400" alt="line-chart-before" src="https://github.com/user-attachments/assets/e9abac31-5050-47ba-8f0e-fabd663de378" /> | <img width="400" alt="line-chart-after" src="https://github.com/user-attachments/assets/0e8bd3ab-17ee-4f4a-9824-b4bb33ff7486" /> | | <img width="400" alt="gauge-chart-before" src="https://github.com/user-attachments/assets/9b74f30e-0e3e-42cf-95af-a1db10365b56" /> | <img width="400" alt="gauge-chart-after" src="https://github.com/user-attachments/assets/cdf2dd48-6a28-4422-bcfd-114ba0014834" /> | | <img width="400" alt="pie-chart-before" src="https://github.com/user-attachments/assets/f6ff8d44-d4ff-4bb0-b4df-28c654a65f4d" /> | <img width="400" alt="pie-chart-after" src="https://github.com/user-attachments/assets/48e34805-cc50-40c0-97fa-654c82c4f74a" /> | | <img width="400" alt="table-chart-before" src="https://github.com/user-attachments/assets/445eb6e5-8bad-4cb7-9b66-e20fd522a107" /> | <img width="400" alt="table-chart-after" src="https://github.com/user-attachments/assets/2dffd504-b4d3-4cd9-8994-1f2422c3426b" /> | </details> --------- Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
…als outside of Lens (#261168) ## Summary Fix issue where `"Elastic UI Numeric"` font is applied to portals outside of Lens e.g. fields overview popover in Discover or Datepicker popover. (The monospaced font `"Elastic UI Numeric"` is added in #251576) Before <img width="1237" height="997" alt="image" src="https://github.com/user-attachments/assets/0f140778-44fe-4644-ab3d-e19e71507c69" /> After <img width="1239" height="997" alt="image" src="https://github.com/user-attachments/assets/256f4288-aa7d-4809-b623-bc1cae464c2f" />
…I theme context (#261476) Resolves #260954 ### Summary - Fixes `Cannot read properties of undefined (reading 'font')` error when rendering the Lens chart in the alerting_v2 rule preview - Wraps both app mount functions with `coreStart.rendering.addContext()` to provide the EUI theme (and other Kibana global context) to the React tree ### Root Cause The alerting_v2 app mounts via ReactDOM.render() which creates a standalone React tree without any EUI ThemeProvider. When Lens renders its embeddable chart inside the rule preview, `lnsNumericFontStyles` reads `euiTheme.font.family` (PR: #251576) from Emotion's theme context which is undefined without the provider, causing the error. ### Testing - Open alerting_v2 rule form and trigger a rule preview with an ES|QL query that renders a Lens chart - Verify the chart renders without errors - Verify notification policies page still loads correctly ### Screenshots <img width="1234" height="781" alt="Screenshot 2026-04-07 at 10 21 24 AM" src="https://github.com/user-attachments/assets/9375415e-8aae-493a-b8c3-006db48333ca" />
…als outside of Lens (elastic#261168) ## Summary Fix issue where `"Elastic UI Numeric"` font is applied to portals outside of Lens e.g. fields overview popover in Discover or Datepicker popover. (The monospaced font `"Elastic UI Numeric"` is added in elastic#251576) Before <img width="1237" height="997" alt="image" src="https://github.com/user-attachments/assets/0f140778-44fe-4644-ab3d-e19e71507c69" /> After <img width="1239" height="997" alt="image" src="https://github.com/user-attachments/assets/256f4288-aa7d-4809-b623-bc1cae464c2f" />
…I theme context (elastic#261476) Resolves elastic#260954 ### Summary - Fixes `Cannot read properties of undefined (reading 'font')` error when rendering the Lens chart in the alerting_v2 rule preview - Wraps both app mount functions with `coreStart.rendering.addContext()` to provide the EUI theme (and other Kibana global context) to the React tree ### Root Cause The alerting_v2 app mounts via ReactDOM.render() which creates a standalone React tree without any EUI ThemeProvider. When Lens renders its embeddable chart inside the rule preview, `lnsNumericFontStyles` reads `euiTheme.font.family` (PR: elastic#251576) from Emotion's theme context which is undefined without the provider, causing the error. ### Testing - Open alerting_v2 rule form and trigger a rule preview with an ES|QL query that renders a Lens chart - Verify the chart renders without errors - Verify notification policies page still loads correctly ### Screenshots <img width="1234" height="781" alt="Screenshot 2026-04-07 at 10 21 24 AM" src="https://github.com/user-attachments/assets/9375415e-8aae-493a-b8c3-006db48333ca" />















Closes #249382
Summary
Enable monospaced numeric rendering for Lens charts (axis labels, legend values, data labels, tooltips) by introducing a numeric-only font (
"Elastic UI Numeric") with the required OpenType features baked into the glyphs, and using it as the first font in the elastic-charts font stack.An earlier CSS-only approach (
font-feature-settings/font-variant-numeric) which works in Chromium/WebKit but is not supported for canvas text in Firefox, has been discarded in favor of the pre-baked"Elastic UI Numeric"font (src/core/packages/apps/server-internal/assets/fonts/elastic_ui_numeric/ElasticUINumeric-Variable.woff2has all the required numeric features pre-applied). With the new approach,"Elastic UI Numeric"will also work for charts which don't use Inter as the base font e.g. Legacy Metric chart or Tag cloud .Implementation
Elastic UI Numericfont (≈8KB WOFF2):unicode-rangetnum,zero,ss01,ss07@font-faceglobally in core rendering (Fontstemplate) so Kibana can serve/load it.'Elastic UI Numeric'to all elastic-chartsfontFamilyvalues in the shared chartsThemeService, ensuring all charts under Lens use it as the preferred font..lnsExpressionRendererand[id^='echTooltipPortal']) so non-canvas elements/tooltips inherit it too.Licensing
Elastic UI Numericis a modified version of Inter licensed under SIL OFL 1.1.src/core/packages/apps/server-internal/assets/fonts/elastic_ui_numeric/LICENSE.txtTesting
This dashboard can be used for testing (creds).
Visuals
Before / After