diff --git a/src-docs/src/views/theme/typography/_typography_js.tsx b/src-docs/src/views/theme/typography/_typography_js.tsx index c54793b46a2..354c7c5bd34 100644 --- a/src-docs/src/views/theme/typography/_typography_js.tsx +++ b/src-docs/src/views/theme/typography/_typography_js.tsx @@ -1,6 +1,6 @@ import React, { FunctionComponent, useState } from 'react'; import { css } from '@emotion/react'; -import { useEuiTheme } from '../../../../../src/services'; +import { useEuiTheme, EuiThemeProvider } from '../../../../../src/services'; import { EuiBasicTable, EuiButtonGroup, @@ -9,6 +9,7 @@ import { EuiDescribedFormGroup, EuiPanel, EuiSpacer, + EuiText, } from '../../../../../src/components'; import { @@ -16,8 +17,8 @@ import { useEuiFontSize, EuiThemeFontWeights, EuiThemeFontScales, - EuiThemeFontSizeMeasurements, - _EuiThemeFontSizeMeasurement, + EuiThemeFontUnits, + _EuiThemeFontUnit, } from '../../../../../src/global_styling'; import { EuiThemeFontBase, EuiThemeFontWeight, ThemeRowType } from '../_props'; @@ -104,6 +105,26 @@ export const FontJS = () => { snippet={'font-feature-settings: ${euiTheme.font.featureSettings};'} snippetLanguage="emotion" /> + + euiTheme.font.defaultUnits} + description={getDescription(baseProps.defaultUnits)} + example={ + + + My font size and line height is set using px{' '} + and not rem + + + } + snippet={` + +

Hello world

+
+
+`} + snippetLanguage="jsx" + /> ); }; @@ -229,27 +250,25 @@ export const FontScaleValuesJS = () => { const euiThemeContext = useEuiTheme(); const scaleKeys = EuiThemeFontScales; - const measurementButtons = EuiThemeFontSizeMeasurements.map((m) => { + const unitButtons = EuiThemeFontUnits.map((m) => { return { id: m, label: m, }; }); - const [measurementSelected, setMeasurementSelected] = useState( - measurementButtons[0].id - ); + const [unitSelected, setUnitSelected] = useState(unitButtons[0].id); return ( <> Value measurements} + title={

Font units

} description={

- The font sizing function also supports the three main measurements - for font-size, rem | px | em, with{' '} + The font sizing function also supports three main units for font + size and line height: rem | px | em, with{' '} rem being default for all EUI components.

} @@ -257,12 +276,10 @@ export const FontScaleValuesJS = () => { - setMeasurementSelected(id as _EuiThemeFontSizeMeasurement) - } + legend="Value unit to show in table" + options={unitButtons} + idSelected={unitSelected} + onChange={(id) => setUnitSelected(id as _EuiThemeFontUnit)} color="accent" isFullWidth /> @@ -272,23 +289,17 @@ export const FontScaleValuesJS = () => { tableLayout="auto" items={scaleKeys.map((scale, index) => { + const { fontSize, lineHeight } = euiFontSize(euiThemeContext, scale, { + unit: unitSelected, + }); + return { id: scale, value: `useEuiFontSize('${scale}'${ - measurementSelected !== 'rem' - ? `,\n { measurement: '${measurementSelected}' }\n` - : '' + unitSelected !== 'rem' ? `, { unit: '${unitSelected}' }` : '' })`, - size: `${ - euiFontSize(euiThemeContext, scale, { - measurement: measurementSelected, - }).fontSize - }`, - lineHeight: `${ - euiFontSize(euiThemeContext, scale, { - measurement: measurementSelected, - }).lineHeight - }`, + size: String(fontSize), + lineHeight: String(lineHeight), index, }; })} @@ -302,7 +313,7 @@ export const FontScaleValuesJS = () => {
diff --git a/src/components/markdown_editor/markdown_format.styles.ts b/src/components/markdown_editor/markdown_format.styles.ts index 0def45152a3..c57fb005b3a 100644 --- a/src/components/markdown_editor/markdown_format.styles.ts +++ b/src/components/markdown_editor/markdown_format.styles.ts @@ -24,8 +24,8 @@ const euiScaleMarkdownFormatText = ( options: _FontScaleOptions ) => { const { fontSize, lineHeight } = euiFontSize(euiTheme, 'm', options); - const { measurement } = options; - const lineHeightSize = measurement === 'em' ? `${lineHeight}em` : lineHeight; + const { unit } = options; + const lineHeightSize = unit === 'em' ? `${lineHeight}em` : lineHeight; // Custom scales const tablePaddingVertical = mathWithUnits(fontSize, (x) => x / 4); @@ -67,25 +67,22 @@ export const euiMarkdownFormatStyles = (euiTheme: UseEuiTheme) => ({ // Text sizes m: css` ${euiScaleMarkdownFormatText(euiTheme, { - measurement: 'rem', customScale: 'm', })} `, s: css` ${euiScaleMarkdownFormatText(euiTheme, { - measurement: 'rem', customScale: 's', })} `, xs: css` ${euiScaleMarkdownFormatText(euiTheme, { - measurement: 'rem', customScale: 'xs', })} `, relative: css` ${euiScaleMarkdownFormatText(euiTheme, { - measurement: 'em', + unit: 'em', })} `, }); diff --git a/src/components/text/text.styles.ts b/src/components/text/text.styles.ts index 568d07293d5..0bcc68b2c45 100644 --- a/src/components/text/text.styles.ts +++ b/src/components/text/text.styles.ts @@ -46,8 +46,8 @@ const euiScaleText = ( ) => { const { fontSize, lineHeight } = euiFontSize(euiThemeContext, 'm', options); const { euiTheme } = euiThemeContext; - const { measurement, customScale: _customScale } = options; - const lineHeightSize = measurement === 'em' ? `${lineHeight}em` : lineHeight; + const { unit, customScale: _customScale } = options; + const lineHeightSize = unit === 'em' ? `${lineHeight}em` : lineHeight; const headings = { h1: euiTitle(euiThemeContext, 'l', options), @@ -345,25 +345,22 @@ export const euiTextStyles = (euiThemeContext: UseEuiTheme) => { // Sizes m: css` ${euiScaleText(euiThemeContext, { - measurement: 'rem', customScale: 'm', })} `, s: css` ${euiScaleText(euiThemeContext, { - measurement: 'rem', customScale: 's', })} `, xs: css` ${euiScaleText(euiThemeContext, { - measurement: 'rem', customScale: 'xs', })} `, relative: css` ${euiScaleText(euiThemeContext, { - measurement: 'em', + unit: 'em', })} `, }; diff --git a/src/global_styling/functions/__snapshots__/typography.test.tsx.snap b/src/global_styling/functions/__snapshots__/typography.test.tsx.snap new file mode 100644 index 00000000000..3c300bdafab --- /dev/null +++ b/src/global_styling/functions/__snapshots__/typography.test.tsx.snap @@ -0,0 +1,45 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`euiFontSizeFromScale scale l 1`] = `"1.5714rem"`; + +exports[`euiFontSizeFromScale scale m 1`] = `"1.1429rem"`; + +exports[`euiFontSizeFromScale scale s 1`] = `"1.0000rem"`; + +exports[`euiFontSizeFromScale scale xl 1`] = `"1.9286rem"`; + +exports[`euiFontSizeFromScale scale xs 1`] = `"0.8571rem"`; + +exports[`euiFontSizeFromScale scale xxl 1`] = `"2.4286rem"`; + +exports[`euiFontSizeFromScale scale xxs 1`] = `"0.7857rem"`; + +exports[`euiFontSizeFromScale scale xxxs 1`] = `"0.6429rem"`; + +exports[`euiFontSizeFromScale unit em 1`] = `"1em"`; + +exports[`euiFontSizeFromScale unit px 1`] = `"16px"`; + +exports[`euiFontSizeFromScale unit rem 1`] = `"1.1429rem"`; + +exports[`euiLineHeightFromBaseline scale l 1`] = `"1.7143rem"`; + +exports[`euiLineHeightFromBaseline scale m 1`] = `"1.7143rem"`; + +exports[`euiLineHeightFromBaseline scale s 1`] = `"1.4286rem"`; + +exports[`euiLineHeightFromBaseline scale xl 1`] = `"2.2857rem"`; + +exports[`euiLineHeightFromBaseline scale xs 1`] = `"1.1429rem"`; + +exports[`euiLineHeightFromBaseline scale xxl 1`] = `"2.8571rem"`; + +exports[`euiLineHeightFromBaseline scale xxs 1`] = `"1.1429rem"`; + +exports[`euiLineHeightFromBaseline scale xxxs 1`] = `"0.8571rem"`; + +exports[`euiLineHeightFromBaseline unit em 1`] = `"1.5000"`; + +exports[`euiLineHeightFromBaseline unit px 1`] = `"24px"`; + +exports[`euiLineHeightFromBaseline unit rem 1`] = `"1.7143rem"`; diff --git a/src/global_styling/functions/typography.test.tsx b/src/global_styling/functions/typography.test.tsx new file mode 100644 index 00000000000..19aa28d553f --- /dev/null +++ b/src/global_styling/functions/typography.test.tsx @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FunctionComponent, PropsWithChildren } from 'react'; +import { renderHook } from '@testing-library/react'; + +import { EuiProvider } from '../../components'; +import { useEuiTheme } from '../../services'; +import { EuiThemeFontScales, EuiThemeFontUnits } from '../variables/typography'; + +import { euiFontSizeFromScale, euiLineHeightFromBaseline } from './typography'; + +// Default euiTheme to use for most tests +const { euiTheme } = renderHook(useEuiTheme).result.current; + +describe('euiFontSizeFromScale', () => { + describe('scale', () => { + EuiThemeFontScales.forEach((scale) => { + test(scale, () => { + expect(euiFontSizeFromScale(scale, euiTheme)).toMatchSnapshot(); + }); + }); + }); + + describe('custom scale', () => { + it('allows passing a custom modifier to the existing scale', () => { + expect( + euiFontSizeFromScale('xxxs', euiTheme, { customScale: 's' }) + ).toEqual('0.5625rem'); + }); + }); + + describe('unit', () => { + EuiThemeFontUnits.forEach((unit) => { + test(unit, () => { + const output = euiFontSizeFromScale('m', euiTheme, { unit }); + expect(output.endsWith(unit)).toBe(true); + expect(output).toMatchSnapshot(); + }); + }); + + it('falls back to the `defaultUnits` theme token if a unit is not passed', () => { + const wrapper: FunctionComponent = ({ children }) => ( + + {children} + + ); + const { euiTheme: modifiedEuiTheme } = renderHook(useEuiTheme, { + wrapper, + }).result.current; + + expect(euiFontSizeFromScale('m', modifiedEuiTheme)).toEqual('16px'); + }); + }); +}); + +describe('euiLineHeightFromBaseline', () => { + describe('scale', () => { + EuiThemeFontScales.forEach((scale) => { + test(scale, () => { + expect(euiLineHeightFromBaseline(scale, euiTheme)).toMatchSnapshot(); + }); + }); + }); + + describe('custom scale', () => { + it('allows passing a custom modifier to the existing scale', () => { + expect( + euiLineHeightFromBaseline('xxxs', euiTheme, { customScale: 's' }) + ).toEqual('0.8571rem'); + }); + }); + + describe('unit', () => { + EuiThemeFontUnits.forEach((unit) => { + test(unit, () => { + const output = euiLineHeightFromBaseline('m', euiTheme, { unit }); + + if (unit !== 'em') { + expect(output.endsWith(unit)).toBe(true); + } else { + expect(Number(output)).not.toBeNaN(); + } + + expect(output).toMatchSnapshot(); + }); + }); + + it('falls back to the `defaultUnits` theme token if a unit is not passed', () => { + const wrapper: FunctionComponent = ({ children }) => ( + + {children} + + ); + const { euiTheme: modifiedEuiTheme } = renderHook(useEuiTheme, { + wrapper, + }).result.current; + + expect(euiLineHeightFromBaseline('m', modifiedEuiTheme)).toEqual('24px'); + }); + }); +}); diff --git a/src/global_styling/functions/typography.ts b/src/global_styling/functions/typography.ts index cfff01e4772..1079febb407 100644 --- a/src/global_styling/functions/typography.ts +++ b/src/global_styling/functions/typography.ts @@ -8,7 +8,7 @@ import { _EuiThemeFontScale, - _EuiThemeFontSizeMeasurement, + _EuiThemeFontUnit, _EuiThemeFontWeights, } from '../variables/typography'; import { UseEuiTheme } from '../../services/theme/hooks'; @@ -16,9 +16,9 @@ import { logicalCSS } from './logicals'; export interface _FontScaleOptions { /** - * The returned string measurement + * The font-size or line-height unit to return */ - measurement?: _EuiThemeFontSizeMeasurement; + unit?: _EuiThemeFontUnit; /** * An additional custom scale multiplier to use against the current scale * This parameter can be used (e.g. by EuiText sizes) to get sizes of text smaller than the default @@ -38,9 +38,9 @@ export interface _FontScaleOptions { export function euiFontSizeFromScale( scale: _EuiThemeFontScale, { base, font }: UseEuiTheme['euiTheme'], - { measurement = 'rem', customScale }: _FontScaleOptions = {} + { unit = font.defaultUnits, customScale }: _FontScaleOptions = {} ) { - if (measurement === 'em') { + if (unit === 'em') { return `${font.scale[scale]}em`; } @@ -48,7 +48,7 @@ export function euiFontSizeFromScale( if (customScale) numerator *= font.scale[customScale]; const denominator = base * font.scale[font.body.scale]; - return measurement === 'px' + return unit === 'px' ? `${numerator}px` : `${(numerator / denominator).toFixed(4)}rem`; } @@ -68,7 +68,7 @@ export function euiFontSizeFromScale( export function euiLineHeightFromBaseline( scale: _EuiThemeFontScale, { base, font }: UseEuiTheme['euiTheme'], - { measurement = 'rem', customScale }: _FontScaleOptions = {} + { unit = font.defaultUnits, customScale }: _FontScaleOptions = {} ) { const { baseline, lineHeightMultiplier } = font; let numerator = base * font.scale[scale]; @@ -78,7 +78,7 @@ export function euiLineHeightFromBaseline( const _lineHeightMultiplier = numerator <= base ? lineHeightMultiplier : lineHeightMultiplier * 0.833; - if (measurement === 'em') { + if (unit === 'em') { // Even though the line-height via `em` cannot be determined against the pixel baseline grid; // we will assume that typically larger scale font-sizes should have a shorter line-height; return _lineHeightMultiplier.toFixed(4).toString(); @@ -87,7 +87,7 @@ export function euiLineHeightFromBaseline( const pixelValue = Math.floor(Math.round(numerator * _lineHeightMultiplier) / baseline) * baseline; - return measurement === 'px' + return unit === 'px' ? `${pixelValue}px` : `${(pixelValue / denominator).toFixed(4)}rem`; } diff --git a/src/global_styling/mixins/_typography.test.ts b/src/global_styling/mixins/_typography.test.ts index 71ec85e75dd..3ce71130925 100644 --- a/src/global_styling/mixins/_typography.test.ts +++ b/src/global_styling/mixins/_typography.test.ts @@ -8,10 +8,7 @@ import { testCustomHook } from '../../test/internal'; -import { - EuiThemeFontScales, - EuiThemeFontSizeMeasurements, -} from '../variables/typography'; +import { EuiThemeFontScales, EuiThemeFontUnits } from '../variables/typography'; import { useEuiFontSize, euiTextBreakWord, @@ -21,12 +18,12 @@ import { describe('euiFontSize', () => { describe('returns an object of font-size and line-height for each scale', () => { - EuiThemeFontSizeMeasurements.forEach((measurement) => { - describe(measurement, () => { + EuiThemeFontUnits.forEach((unit) => { + describe(unit, () => { EuiThemeFontScales.forEach((size) => { test(size, () => { expect( - testCustomHook(() => useEuiFontSize(size, { measurement })).return + testCustomHook(() => useEuiFontSize(size, { unit })).return ).toMatchSnapshot(); }); }); diff --git a/src/global_styling/variables/typography.ts b/src/global_styling/variables/typography.ts index f270a7ab6a7..80ebbc8b1cb 100644 --- a/src/global_styling/variables/typography.ts +++ b/src/global_styling/variables/typography.ts @@ -12,10 +12,9 @@ import { CSSProperties } from 'react'; * Font units of measure */ -export const EuiThemeFontSizeMeasurements = ['rem', 'px', 'em'] as const; +export const EuiThemeFontUnits = ['rem', 'px', 'em'] as const; -export type _EuiThemeFontSizeMeasurement = - (typeof EuiThemeFontSizeMeasurements)[number]; +export type _EuiThemeFontUnit = (typeof EuiThemeFontUnits)[number]; /* * Font scale @@ -59,6 +58,16 @@ export type _EuiThemeFontBase = { * https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings */ featureSettings?: string; + /** + * Sets the default units used for font size & line height set by UI components + * like EuiText or EuiTitle. Defaults to `rem`. + * + * NOTE: This may overridden by some internal usages, e.g. + * EuiText's `relative` size which must use `em`. + * + * @default 'rem' + */ + defaultUnits: _EuiThemeFontUnit; /** * A computed number that is 1/4 of `base` */ diff --git a/src/themes/amsterdam/global_styling/variables/_typography.ts b/src/themes/amsterdam/global_styling/variables/_typography.ts index f51b71aa0fe..3a95f26a6c5 100644 --- a/src/themes/amsterdam/global_styling/variables/_typography.ts +++ b/src/themes/amsterdam/global_styling/variables/_typography.ts @@ -34,6 +34,7 @@ export const fontBase: _EuiThemeFontBase = { // Careful using ligatures. Code editors like ACE will often error because of width calculations featureSettings: "'calt' 1, 'kern' 1, 'liga' 1", + defaultUnits: 'rem', baseline: computed(([base]) => base / 4, ['base']), lineHeightMultiplier: 1.5, diff --git a/upcoming_changelogs/7133.md b/upcoming_changelogs/7133.md new file mode 100644 index 00000000000..9ec8351cd25 --- /dev/null +++ b/upcoming_changelogs/7133.md @@ -0,0 +1,5 @@ +- Added `font.defaultUnits` theme token. EUI component font sizes default to `rem` units - this token allows consumers to configure this to `px` or `em` + +**CSS-in-JS conversions** + +- Renamed `useEuiFontSize()`'s `measurement` option to `unit` for clarity