From 31f63167679abb4948c6af53e4a8d57e78e0f01b Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Wed, 18 Sep 2024 13:03:37 +0200 Subject: [PATCH 01/32] fix: ensure getComputed resolves Computed objects correctly - externally created, compiled and imported themes don't pass the class check anymore we can check for the shape additionally --- packages/eui/src/services/theme/utils.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/eui/src/services/theme/utils.ts b/packages/eui/src/services/theme/utils.ts index c7c9c5216d0..5cbb3c2281e 100644 --- a/packages/eui/src/services/theme/utils.ts +++ b/packages/eui/src/services/theme/utils.ts @@ -203,6 +203,16 @@ export function computed( return new Computed(comp, dep); } +/** + * Type guard to check for a Computed object based on object shape + * without relying on the Computed class directly + */ +const isComputedLike = (key: object): key is Computed => { + if (typeof key !== 'object' || Array.isArray(key)) return false; + + return key.hasOwnProperty('dependencies') && key.hasOwnProperty('computer'); +}; + /** * Takes an uncomputed theme, and computes and returns all values taking * into consideration value overrides and configured color mode. @@ -217,7 +227,7 @@ export const getComputed = ( over: Partial>, colorMode: EuiThemeColorModeStandard ): EuiThemeComputed => { - const output = { themeName: base.key }; + const output: Partial = { themeName: base.key }; function loop( base: { [key: string]: any }, @@ -240,12 +250,14 @@ export const getComputed = ( } const existing = checkExisting && getOn(output, newPath); if (!existing || isObject(existing)) { + // NOTE: the class type check for Computed is not true for themes created externally; + // we additionally check on the object shape to confirm a Computed value const baseValue = - base[key] instanceof Computed + base[key] instanceof Computed || isComputedLike(base[key]) ? base[key].getValue(base.root, over.root, output, colorMode) : base[key]; const overValue = - over[key] instanceof Computed + over[key] instanceof Computed || isComputedLike(over[key]) ? over[key].getValue(base.root, over.root, output, colorMode) : over[key]; if (isObject(baseValue) && !Array.isArray(baseValue)) { From 3d8029137731809fbab463130052ea6b8c7783c6 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Wed, 18 Sep 2024 15:06:17 +0200 Subject: [PATCH 02/32] feat: setup new theme package - theme contains only cloned values from current theme --- packages/eui-theme-berlin/.gitignore | 8 ++ packages/eui-theme-berlin/README.md | 1 + packages/eui-theme-berlin/package.json | 33 ++++++++ packages/eui-theme-berlin/src/index.ts | 34 ++++++++ packages/eui-theme-berlin/src/theme_dark.scss | 5 ++ .../eui-theme-berlin/src/theme_light.scss | 5 ++ .../src/variables/_animation.ts | 31 ++++++++ .../src/variables/_borders.ts | 33 ++++++++ .../src/variables/_breakpoint.ts | 17 ++++ .../src/variables/_buttons.scss | 4 + .../eui-theme-berlin/src/variables/_colors.ts | 19 +++++ .../src/variables/_colors_dark.scss | 49 ++++++++++++ .../src/variables/_colors_dark.ts | 79 +++++++++++++++++++ .../src/variables/_colors_light.scss | 49 ++++++++++++ .../src/variables/_colors_light.ts | 79 +++++++++++++++++++ .../src/variables/_index.scss | 7 ++ .../eui-theme-berlin/src/variables/_levels.ts | 21 +++++ .../eui-theme-berlin/src/variables/_page.scss | 1 + .../eui-theme-berlin/src/variables/_size.ts | 29 +++++++ .../src/variables/_states.scss | 11 +++ .../eui-theme-berlin/src/variables/_states.ts | 25 ++++++ .../src/variables/_typography.scss | 64 +++++++++++++++ .../src/variables/_typography.ts | 64 +++++++++++++++ packages/eui-theme-berlin/tsconfig.json | 20 +++++ yarn.lock | 30 +++++++ 25 files changed, 718 insertions(+) create mode 100644 packages/eui-theme-berlin/.gitignore create mode 100644 packages/eui-theme-berlin/README.md create mode 100644 packages/eui-theme-berlin/package.json create mode 100644 packages/eui-theme-berlin/src/index.ts create mode 100644 packages/eui-theme-berlin/src/theme_dark.scss create mode 100644 packages/eui-theme-berlin/src/theme_light.scss create mode 100644 packages/eui-theme-berlin/src/variables/_animation.ts create mode 100644 packages/eui-theme-berlin/src/variables/_borders.ts create mode 100644 packages/eui-theme-berlin/src/variables/_breakpoint.ts create mode 100644 packages/eui-theme-berlin/src/variables/_buttons.scss create mode 100644 packages/eui-theme-berlin/src/variables/_colors.ts create mode 100644 packages/eui-theme-berlin/src/variables/_colors_dark.scss create mode 100644 packages/eui-theme-berlin/src/variables/_colors_dark.ts create mode 100644 packages/eui-theme-berlin/src/variables/_colors_light.scss create mode 100644 packages/eui-theme-berlin/src/variables/_colors_light.ts create mode 100644 packages/eui-theme-berlin/src/variables/_index.scss create mode 100644 packages/eui-theme-berlin/src/variables/_levels.ts create mode 100644 packages/eui-theme-berlin/src/variables/_page.scss create mode 100644 packages/eui-theme-berlin/src/variables/_size.ts create mode 100644 packages/eui-theme-berlin/src/variables/_states.scss create mode 100644 packages/eui-theme-berlin/src/variables/_states.ts create mode 100644 packages/eui-theme-berlin/src/variables/_typography.scss create mode 100644 packages/eui-theme-berlin/src/variables/_typography.ts create mode 100644 packages/eui-theme-berlin/tsconfig.json diff --git a/packages/eui-theme-berlin/.gitignore b/packages/eui-theme-berlin/.gitignore new file mode 100644 index 00000000000..1a3f60d4707 --- /dev/null +++ b/packages/eui-theme-berlin/.gitignore @@ -0,0 +1,8 @@ +# Dependencies +/node_modules + +# Production +/lib + +yarn-debug.log* +yarn-error.log* \ No newline at end of file diff --git a/packages/eui-theme-berlin/README.md b/packages/eui-theme-berlin/README.md new file mode 100644 index 00000000000..fbfeb8dcba3 --- /dev/null +++ b/packages/eui-theme-berlin/README.md @@ -0,0 +1 @@ +# `eui-theme-berlin` - A visual EUI theme \ No newline at end of file diff --git a/packages/eui-theme-berlin/package.json b/packages/eui-theme-berlin/package.json new file mode 100644 index 00000000000..9bb3b25452f --- /dev/null +++ b/packages/eui-theme-berlin/package.json @@ -0,0 +1,33 @@ +{ + "name": "@elastic/eui-theme-berlin", + "version": "0.0.1", + "description": "A visual theme for EUI", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc", + "build-pack": "yarn build && npm pack" + }, + "repository": { + "type": "git", + "url": "https://github.com/elastic/eui.git", + "directory": "packages/eui-theme-berlin" + }, + "private": true, + "devDependencies": { + "typescript": "^5.6.2" + }, + "peerDependencies": { + "@elastic/eui": "^95.10.1" + }, + "main": "lib/index.js", + "exports": { + "./lib/*": "./lib/*", + ".": { + "default": "./lib/index.js" + } + }, + "files": [ + "lib/", + "README.md" + ] +} diff --git a/packages/eui-theme-berlin/src/index.ts b/packages/eui-theme-berlin/src/index.ts new file mode 100644 index 00000000000..ac63b734c3a --- /dev/null +++ b/packages/eui-theme-berlin/src/index.ts @@ -0,0 +1,34 @@ +/* + * 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 { buildTheme, EuiThemeShape } from '@elastic/eui'; + +import { colors } from './variables/_colors'; +import { animation } from './variables/_animation'; +import { breakpoint } from './variables/_breakpoint'; +import { base, size } from './variables/_size'; +import { border } from './variables/_borders'; +import { levels } from './variables/_levels'; +import { font } from './variables/_typography'; +import { focus } from './variables/_states'; + +export const EUI_THEME_BERLIN_KEY = 'EUI_THEME_BERLIN'; + +export const euiThemeBerlin: EuiThemeShape = { + colors, + base, + size, + border, + font, + animation, + breakpoint, + levels, + focus, +}; + +export const EuiThemeBerlin = buildTheme(euiThemeBerlin, EUI_THEME_BERLIN_KEY); diff --git a/packages/eui-theme-berlin/src/theme_dark.scss b/packages/eui-theme-berlin/src/theme_dark.scss new file mode 100644 index 00000000000..d5710063a18 --- /dev/null +++ b/packages/eui-theme-berlin/src/theme_dark.scss @@ -0,0 +1,5 @@ +// color mode specific variables +@import './variables/colors_dark'; + +// Global styling +@import './variables/index'; \ No newline at end of file diff --git a/packages/eui-theme-berlin/src/theme_light.scss b/packages/eui-theme-berlin/src/theme_light.scss new file mode 100644 index 00000000000..ce7d45f4ef7 --- /dev/null +++ b/packages/eui-theme-berlin/src/theme_light.scss @@ -0,0 +1,5 @@ +// color mode specific variables +@import './variables/colors_light'; + +// Global styling +@import './variables/index'; \ No newline at end of file diff --git a/packages/eui-theme-berlin/src/variables/_animation.ts b/packages/eui-theme-berlin/src/variables/_animation.ts new file mode 100644 index 00000000000..7f8dfd998fd --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_animation.ts @@ -0,0 +1,31 @@ +/* + * 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 type { + _EuiThemeAnimationSpeeds, + _EuiThemeAnimationEasings, + _EuiThemeAnimation, +} from '@elastic/eui'; + +export const animation_speed: _EuiThemeAnimationSpeeds = { + extraFast: '90ms', + fast: '150ms', + normal: '250ms', + slow: '350ms', + extraSlow: '500ms', +}; + +export const animation_ease: _EuiThemeAnimationEasings = { + bounce: 'cubic-bezier(.34, 1.61, .7, 1)', + resistance: 'cubic-bezier(.694, .0482, .335, 1)', +}; + +export const animation: _EuiThemeAnimation = { + ...animation_speed, + ...animation_ease, +}; diff --git a/packages/eui-theme-berlin/src/variables/_borders.ts b/packages/eui-theme-berlin/src/variables/_borders.ts new file mode 100644 index 00000000000..8bddcf1364a --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_borders.ts @@ -0,0 +1,33 @@ +/* + * 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 { computed, sizeToPixel, type _EuiThemeBorder } from '@elastic/eui'; + +export const border: _EuiThemeBorder = { + color: computed(([lightShade]) => lightShade, ['colors.lightShade']), + width: { + thin: '1px', + thick: '2px', + }, + radius: { + medium: computed(sizeToPixel(0.375)), + small: computed(sizeToPixel(0.25)), + }, + thin: computed( + ([width, color]) => `${width.thin} solid ${color}`, + ['border.width', 'border.color'] + ), + thick: computed( + ([width, color]) => `${width.thick} solid ${color}`, + ['border.width', 'border.color'] + ), + editable: computed( + ([width, color]) => `${width.thick} dotted ${color}`, + ['border.width', 'border.color'] + ), +}; diff --git a/packages/eui-theme-berlin/src/variables/_breakpoint.ts b/packages/eui-theme-berlin/src/variables/_breakpoint.ts new file mode 100644 index 00000000000..503aba80aed --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_breakpoint.ts @@ -0,0 +1,17 @@ +/* + * 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 type { _EuiThemeBreakpoints } from '@elastic/eui'; + +export const breakpoint: _EuiThemeBreakpoints = { + xl: 1200, + l: 992, + m: 768, + s: 575, + xs: 0, +}; diff --git a/packages/eui-theme-berlin/src/variables/_buttons.scss b/packages/eui-theme-berlin/src/variables/_buttons.scss new file mode 100644 index 00000000000..f42b0c3264c --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_buttons.scss @@ -0,0 +1,4 @@ +$euiButtonColorDisabled: $euiColorDisabled; +$euiButtonColorDisabledText: $euiColorDisabledText; +$euiButtonDefaultTransparency: .8; +$euiButtonFontWeight: $euiFontWeightMedium; diff --git a/packages/eui-theme-berlin/src/variables/_colors.ts b/packages/eui-theme-berlin/src/variables/_colors.ts new file mode 100644 index 00000000000..ebd13918486 --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_colors.ts @@ -0,0 +1,19 @@ +/* + * 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 type { _EuiThemeColors } from '@elastic/eui'; + +import { light_colors } from './_colors_light'; +import { dark_colors } from './_colors_dark'; + +export const colors: _EuiThemeColors = { + ghost: '#FFF', + ink: '#000', + LIGHT: light_colors, + DARK: dark_colors, +}; diff --git a/packages/eui-theme-berlin/src/variables/_colors_dark.scss b/packages/eui-theme-berlin/src/variables/_colors_dark.scss new file mode 100644 index 00000000000..bd24f0d3c34 --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_colors_dark.scss @@ -0,0 +1,49 @@ +// stylelint-disable color-no-hex + +// This extra import allows any variables that are created via functions to work when loaded into JS +@import '@elastic/eui/global_styling/functions/index'; + +// These colors stay the same no matter the theme +$euiColorGhost: #FFF !default; +$euiColorInk: #000 !default; + +// Core +$euiColorPrimary: #36A2EF !default; +$euiColorAccent: #F68FBE !default; + +// Status +$euiColorSuccess: #7DDED8 !default; +$euiColorWarning: #F3D371 !default; +$euiColorDanger: #F86B63 !default; + +// Grays +$euiColorEmptyShade: #1D1E24 !default; +$euiColorLightestShade: #25262E !default; +$euiColorLightShade: #343741 !default; +$euiColorMediumShade: #535966 !default; +$euiColorDarkShade: #98A2B3 !default; +$euiColorDarkestShade: #D4DAE5 !default; +$euiColorFullShade: #FFF !default; + +// Backgrounds +$euiPageBackgroundColor: shade($euiColorLightestShade, 45%) !default; +$euiColorHighlight: #2E2D25 !default; + +// Variations from core +$euiTextColor: #DFE5EF !default; +$euiTitleColor: $euiTextColor !default; +$euiTextSubduedColor: makeHighContrastColor($euiColorMediumShade) !default; +$euiColorDisabled: #515761 !default; + +// Contrasty text variants +$euiColorPrimaryText: makeHighContrastColor($euiColorPrimary) !default; +$euiColorSuccessText: makeHighContrastColor($euiColorSuccess) !default; +$euiColorAccentText: makeHighContrastColor($euiColorAccent) !default; +$euiColorWarningText: makeHighContrastColor($euiColorWarning) !default; +$euiColorDangerText: makeHighContrastColor($euiColorDanger) !default; +$euiColorDisabledText: makeDisabledContrastColor($euiColorDisabled) !default; +$euiLinkColor: $euiColorPrimaryText !default; + +// Charts +$euiColorChartLines: $euiColorLightShade !default; +$euiColorChartBand: tint($euiColorLightestShade, 2.5%) !default; diff --git a/packages/eui-theme-berlin/src/variables/_colors_dark.ts b/packages/eui-theme-berlin/src/variables/_colors_dark.ts new file mode 100644 index 00000000000..37961eeee41 --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_colors_dark.ts @@ -0,0 +1,79 @@ +/* + * 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 { + computed, + makeHighContrastColor, + makeDisabledContrastColor, + shade, + tint, + type _EuiThemeColors, + type _EuiThemeBrandColors, + type _EuiThemeBrandTextColors, + type _EuiThemeShadeColors, + type _EuiThemeSpecialColors, + type _EuiThemeTextColors, + type _EuiThemeColorsMode, +} from '@elastic/eui'; + +/* + * DARK THEME + */ + +export const dark_brand_colors: _EuiThemeBrandColors = { + primary: '#36A2EF', + accent: '#F68FBE', + success: '#7DDED8', + warning: '#F3D371', + danger: '#F86B63', +}; + +export const dark_brand_text_colors: _EuiThemeBrandTextColors = { + primaryText: computed(makeHighContrastColor('colors.primary')), + accentText: computed(makeHighContrastColor('colors.accent')), + successText: computed(makeHighContrastColor('colors.success')), + warningText: computed(makeHighContrastColor('colors.warning')), + dangerText: computed(makeHighContrastColor('colors.danger')), +}; + +export const dark_shades: _EuiThemeShadeColors = { + emptyShade: '#1D1E24', + lightestShade: '#25262E', + lightShade: '#343741', + mediumShade: '#535966', + darkShade: '#98A2B3', + darkestShade: '#D4DAE5', + fullShade: '#FFF', +}; + +export const dark_special_colors: _EuiThemeSpecialColors = { + body: computed( + ([lightestShade]) => shade(lightestShade, 0.45), + ['colors.lightestShade'] + ), + highlight: '#2E2D25', + disabled: '#515761', + disabledText: computed(makeDisabledContrastColor('colors.disabled')), + shadow: computed(({ colors }) => colors.ink), +}; + +export const dark_text_colors: _EuiThemeTextColors = { + text: '#DFE5EF', + title: computed(([text]) => text, ['colors.text']), + subduedText: computed(makeHighContrastColor('colors.mediumShade')), + link: computed(([primaryText]) => primaryText, ['colors.primaryText']), +}; + +export const dark_colors: _EuiThemeColorsMode = { + ...dark_brand_colors, + ...dark_shades, + ...dark_special_colors, + // Need to come after special colors so they can react to `body` + ...dark_brand_text_colors, + ...dark_text_colors, +}; diff --git a/packages/eui-theme-berlin/src/variables/_colors_light.scss b/packages/eui-theme-berlin/src/variables/_colors_light.scss new file mode 100644 index 00000000000..fe763206579 --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_colors_light.scss @@ -0,0 +1,49 @@ +// stylelint-disable color-no-hex + +// This extra import allows any variables that are created via functions to work when loaded into JS +@import '@elastic/eui/global_styling/functions/index'; + +// These colors stay the same no matter the theme +$euiColorGhost: #FFF !default; +$euiColorInk: #000 !default; + +// Core +$euiColorPrimary: #07C !default; +$euiColorAccent: #F04E98 !default; + +// Status +$euiColorSuccess: #00BFB3 !default; +$euiColorWarning: #FEC514 !default; +$euiColorDanger: #BD271E !default; + +// Grays +$euiColorEmptyShade: #FFF !default; +$euiColorLightestShade: #F5F7FA !default; +$euiColorLightShade: #D3DAE6 !default; +$euiColorMediumShade: #98A2B3 !default; +$euiColorDarkShade: #69707D !default; +$euiColorDarkestShade: #343741 !default; +$euiColorFullShade: #000 !default; + +// Backgrounds +$euiPageBackgroundColor: tint($euiColorLightestShade, 50%) !default; +$euiColorHighlight: tint($euiColorWarning, 90%) !default; + +// Every color below must be based mathematically on the set above and in a particular order. +$euiTextColor: $euiColorDarkestShade !default; +$euiTitleColor: shade($euiTextColor, 50%) !default; +$euiTextSubduedColor: $euiColorDarkShade !default; +$euiColorDisabled: #ABB4C4 !default; + +// Contrasty text variants +$euiColorPrimaryText: makeHighContrastColor($euiColorPrimary) !default; +$euiColorSuccessText: makeHighContrastColor($euiColorSuccess) !default; +$euiColorAccentText: makeHighContrastColor($euiColorAccent) !default; +$euiColorWarningText: makeHighContrastColor($euiColorWarning) !default; +$euiColorDangerText: makeHighContrastColor($euiColorDanger) !default; +$euiColorDisabledText: makeDisabledContrastColor($euiColorDisabled) !default; +$euiLinkColor: $euiColorPrimaryText !default; + +// Charts +$euiColorChartLines: shade($euiColorLightestShade, 3%) !default; +$euiColorChartBand: $euiColorLightestShade !default; diff --git a/packages/eui-theme-berlin/src/variables/_colors_light.ts b/packages/eui-theme-berlin/src/variables/_colors_light.ts new file mode 100644 index 00000000000..d3411be74db --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_colors_light.ts @@ -0,0 +1,79 @@ +/* + * 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 { + computed, + makeHighContrastColor, + makeDisabledContrastColor, + shade, + tint, + type _EuiThemeColors, + type _EuiThemeBrandColors, + type _EuiThemeBrandTextColors, + type _EuiThemeShadeColors, + type _EuiThemeSpecialColors, + type _EuiThemeTextColors, + type _EuiThemeColorsMode, +} from '@elastic/eui'; + +/* + * LIGHT THEME + */ + +export const brand_colors: _EuiThemeBrandColors = { + primary: '#07C', + accent: '#F04E98', + success: '#00BFB3', + warning: '#FEC514', + danger: '#BD271E', +}; + +export const brand_text_colors: _EuiThemeBrandTextColors = { + primaryText: computed(makeHighContrastColor('colors.primary')), + accentText: computed(makeHighContrastColor('colors.accent')), + successText: computed(makeHighContrastColor('colors.success')), + warningText: computed(makeHighContrastColor('colors.warning')), + dangerText: computed(makeHighContrastColor('colors.danger')), +}; + +export const shade_colors: _EuiThemeShadeColors = { + emptyShade: '#FFF', + lightestShade: '#F1F4FA', + lightShade: '#D3DAE6', + mediumShade: '#98A2B3', + darkShade: '#69707D', + darkestShade: '#343741', + fullShade: '#000', +}; + +export const special_colors: _EuiThemeSpecialColors = { + body: computed( + ([lightestShade]) => tint(lightestShade, 0.4), + ['colors.lightestShade'] + ), + highlight: computed(([warning]) => tint(warning, 0.9), ['colors.warning']), + disabled: '#ABB4C4', + disabledText: computed(makeDisabledContrastColor('colors.disabled')), + shadow: computed(({ colors }) => colors.ink), +}; + +export const text_colors: _EuiThemeTextColors = { + text: computed(([darkestShade]) => darkestShade, ['colors.darkestShade']), + title: computed(([text]) => shade(text, 0.5), ['colors.text']), + subduedText: computed(makeHighContrastColor('colors.darkShade')), + link: computed(([primaryText]) => primaryText, ['colors.primaryText']), +}; + +export const light_colors: _EuiThemeColorsMode = { + ...brand_colors, + ...shade_colors, + ...special_colors, + // Need to come after special colors so they can react to `body` + ...brand_text_colors, + ...text_colors, +}; diff --git a/packages/eui-theme-berlin/src/variables/_index.scss b/packages/eui-theme-berlin/src/variables/_index.scss new file mode 100644 index 00000000000..563251ca270 --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_index.scss @@ -0,0 +1,7 @@ +// Import base theme first, then override +@import '@elastic/eui/global_styling/variables/index'; +@import 'states'; + +@import 'buttons'; +@import 'page'; +@import 'typography'; diff --git a/packages/eui-theme-berlin/src/variables/_levels.ts b/packages/eui-theme-berlin/src/variables/_levels.ts new file mode 100644 index 00000000000..ea1ca2e0a03 --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_levels.ts @@ -0,0 +1,21 @@ +/* + * 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 type { _EuiThemeLevels } from '@elastic/eui'; + +export const levels: _EuiThemeLevels = { + toast: 9000, + modal: 8000, + mask: 6000, + navigation: 6000, + menu: 2000, + header: 1000, + flyout: 1000, + maskBelowHeader: 1000, + content: 0, +}; diff --git a/packages/eui-theme-berlin/src/variables/_page.scss b/packages/eui-theme-berlin/src/variables/_page.scss new file mode 100644 index 00000000000..318cae55681 --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_page.scss @@ -0,0 +1 @@ +$euiPageDefaultMaxWidth: map-get($euiBreakpoints, 'xl'); diff --git a/packages/eui-theme-berlin/src/variables/_size.ts b/packages/eui-theme-berlin/src/variables/_size.ts new file mode 100644 index 00000000000..9ccb4736965 --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_size.ts @@ -0,0 +1,29 @@ +/* + * 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 { + computed, + sizeToPixel, + type _EuiThemeBase, + type _EuiThemeSizes, +} from '@elastic/eui'; + +export const base: _EuiThemeBase = 16; + +export const size: _EuiThemeSizes = { + xxs: computed(sizeToPixel(0.125)), + xs: computed(sizeToPixel(0.25)), + s: computed(sizeToPixel(0.5)), + m: computed(sizeToPixel(0.75)), + base: computed(sizeToPixel()), + l: computed(sizeToPixel(1.5)), + xl: computed(sizeToPixel(2)), + xxl: computed(sizeToPixel(2.5)), + xxxl: computed(sizeToPixel(3)), + xxxxl: computed(sizeToPixel(4)), +}; diff --git a/packages/eui-theme-berlin/src/variables/_states.scss b/packages/eui-theme-berlin/src/variables/_states.scss new file mode 100644 index 00000000000..13e30784936 --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_states.scss @@ -0,0 +1,11 @@ +// Color when not using currentColor +$euiFocusRingColor: $euiColorPrimaryText; + +// Sizing +$euiFocusRingAnimStartSize: 2px; +$euiFocusRingSize: 2px; + +// Transparency +$euiFocusTransparency: lightOrDarkTheme(.9, .8); +$euiFocusTransparencyPercent: lightOrDarkTheme(90%, 80%); +$euiFocusBackgroundColor: transparentize($euiColorPrimary, $euiFocusTransparency); diff --git a/packages/eui-theme-berlin/src/variables/_states.ts b/packages/eui-theme-berlin/src/variables/_states.ts new file mode 100644 index 00000000000..757ece4cc4b --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_states.ts @@ -0,0 +1,25 @@ +/* + * 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 { + computed, + transparentize, + sizeToPixel, + type _EuiThemeFocus, +} from '@elastic/eui'; + +export const focus: _EuiThemeFocus = { + // Focus ring + color: 'currentColor', + width: computed(sizeToPixel(0.125)), + // Focus background + transparency: { LIGHT: 0.1, DARK: 0.2 }, + backgroundColor: computed(({ colors, focus }) => + transparentize(colors.primary, focus.transparency) + ), +}; diff --git a/packages/eui-theme-berlin/src/variables/_typography.scss b/packages/eui-theme-berlin/src/variables/_typography.scss new file mode 100644 index 00000000000..824f56b42da --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_typography.scss @@ -0,0 +1,64 @@ +// Finally start using the non-beta version of Inter +$euiFontFamily: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol' !default; + +// Font sizes -- scale is loosely based on Major Third (1.250) with a base of 14px +// Base list is an altered scale based on 16px to match the resulted values below +$euiTextScale: 2.125, 1.6875, 1.375, 1.125, 1, .875, .75 !default; + +$euiFontSize: $euiSize - 2; // 14px + +$euiFontSizeXS: floor($euiFontSize * .86); // 12px // h6 +$euiFontSizeS: floor($euiFontSize * 1); // 14px // h5 --> Now the same as the base $euiFontSize +$euiFontSizeM: ceil($euiFontSize * 1.14); // 16px // h4 +$euiFontSizeL: ceil($euiFontSize * 1.57); // 22px // h3 +$euiFontSizeXL: floor($euiFontSize * 1.93); // 27px // h2 +$euiFontSizeXXL: floor($euiFontSize * 2.43); // 34px // h1 + +$euiBodyLineHeight: 1.142857143 !default; // 16px from a 14px base font size to ensure it aligns to our 16px grid + +$euiCodeFontWeightRegular: 400; +$euiCodeFontWeightBold: 700; + +// Normally functions are imported before variables in `_index.scss` files +// But because they need to consume some typography variables they need to live here +@function convertToRem($size) { + @return #{$size / $euiFontSize}rem; +} + +// Use 8px increments for base gridline +@function lineHeightFromBaseline($multiplier: 3) { + @return convertToRem(($euiSize / 2) * $multiplier); +} + +$euiTitles: ( + 'xxxs': ( + 'font-size': $euiFontSizeXS, + 'line-height': lineHeightFromBaseline(2), + 'font-weight': $euiFontWeightBold, + ), + 'xxs': ( + 'font-size': $euiFontSizeS, + 'line-height': lineHeightFromBaseline(3), + 'font-weight': $euiFontWeightBold, + ), + 'xs': ( + 'font-size': $euiFontSizeM, + 'line-height': lineHeightFromBaseline(3), + 'font-weight': $euiFontWeightBold, + ), + 's': ( + 'font-size': $euiFontSizeL, + 'line-height': lineHeightFromBaseline(4), + 'font-weight': $euiFontWeightBold, + ), + 'm': ( + 'font-size': $euiFontSizeXL, + 'line-height': lineHeightFromBaseline(4), + 'font-weight': $euiFontWeightBold, + ), + 'l': ( + 'font-size': $euiFontSizeXXL, + 'line-height': lineHeightFromBaseline(5), + 'font-weight': $euiFontWeightBold, + ), +); diff --git a/packages/eui-theme-berlin/src/variables/_typography.ts b/packages/eui-theme-berlin/src/variables/_typography.ts new file mode 100644 index 00000000000..4a7535acb5f --- /dev/null +++ b/packages/eui-theme-berlin/src/variables/_typography.ts @@ -0,0 +1,64 @@ +/* + * 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 { + computed, + type _EuiThemeFont, + type _EuiThemeFontBase, + type _EuiThemeFontScales, + type _EuiThemeFontWeights, +} from '@elastic/eui'; + +// import { computed } from '../../../eui/src/services/theme/utils'; + +// Typographic scale -- loosely based on Major Third (1.250) +export const fontScale: _EuiThemeFontScales = { + xxxs: 0.5625, + xxs: 0.6875, + xs: 0.75, + s: 0.875, + m: 1, + l: 1.375, + xl: 1.6875, + xxl: 2.125, +}; + +// Families & base font settings +export const fontBase: _EuiThemeFontBase = { + family: "'Inter', BlinkMacSystemFont, Helvetica, Arial, sans-serif", + familyCode: "'Roboto Mono', Menlo, Courier, monospace", + familySerif: 'Georgia, Times, Times New Roman, serif', + + // 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, +}; + +export const fontWeight: _EuiThemeFontWeights = { + light: 300, + regular: 400, + medium: 500, + semiBold: 600, + bold: 700, +}; + +export const font: _EuiThemeFont = { + ...fontBase, + scale: fontScale, + weight: fontWeight, + body: { + scale: 's', + weight: 'regular', + }, + title: { + weight: 'bold', + }, +}; diff --git a/packages/eui-theme-berlin/tsconfig.json b/packages/eui-theme-berlin/tsconfig.json new file mode 100644 index 00000000000..4415cdcb934 --- /dev/null +++ b/packages/eui-theme-berlin/tsconfig.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib", + "target": "ES2020", + "lib": ["ESNext", "DOM"], + "moduleResolution": "Node", + "declaration": true, + "sourceMap": true, + "noEmitHelpers": true, + "incremental": true, + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "tsBuildInfoFile": "lib/.tsbuildinfo" + }, + "include": ["src"], + "exclude": ["node_modules"], + } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index ff46d34f168..fc194efdeb4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5748,6 +5748,16 @@ __metadata: languageName: unknown linkType: soft +"@elastic/eui-theme-berlin@workspace:packages/eui-theme-berlin": + version: 0.0.0-use.local + resolution: "@elastic/eui-theme-berlin@workspace:packages/eui-theme-berlin" + dependencies: + typescript: "npm:^5.6.2" + peerDependencies: + "@elastic/eui": ^95.10.1 + languageName: unknown + linkType: soft + "@elastic/eui-website@workspace:packages/website": version: 0.0.0-use.local resolution: "@elastic/eui-website@workspace:packages/website" @@ -36582,6 +36592,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.6.2": + version: 5.6.2 + resolution: "typescript@npm:5.6.2" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/3ed8297a8c7c56b7fec282532503d1ac795239d06e7c4966b42d4330c6cf433a170b53bcf93a130a7f14ccc5235de5560df4f1045eb7f3550b46ebed16d3c5e5 + languageName: node + linkType: hard + "typescript@npm:~5.5.4": version: 5.5.4 resolution: "typescript@npm:5.5.4" @@ -36602,6 +36622,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A^5.6.2#optional!builtin": + version: 5.6.2 + resolution: "typescript@patch:typescript@npm%3A5.6.2#optional!builtin::version=5.6.2&hash=b45daf" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/e6c1662e4852e22fe4bbdca471dca3e3edc74f6f1df043135c44a18a7902037023ccb0abdfb754595ca9028df8920f2f8492c00fc3cbb4309079aae8b7de71cd + languageName: node + linkType: hard + "typescript@patch:typescript@npm%3A~5.5.4#optional!builtin": version: 5.5.4 resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin::version=5.5.4&hash=b45daf" From 5f0ae6d76179f728f7ea9cf0f94114764237ed29 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Thu, 19 Sep 2024 14:24:06 +0200 Subject: [PATCH 03/32] feat: add experimental flag --- packages/eui/src/services/theme/provider.tsx | 13 +++++++++++++ packages/eui/src/themes/index.ts | 6 +++++- packages/eui/src/themes/themes.ts | 11 +++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/eui/src/services/theme/provider.tsx b/packages/eui/src/services/theme/provider.tsx index c5a6957e8c3..e0678603074 100644 --- a/packages/eui/src/services/theme/provider.tsx +++ b/packages/eui/src/services/theme/provider.tsx @@ -20,6 +20,7 @@ import React, { import { Global, type CSSObject } from '@emotion/react'; import isEqual from 'lodash/isEqual'; +import { EUI_EXPERIMENTAL_THEME_ENABLED_KEY } from '../../themes/themes'; import type { CommonProps } from '../../components/common'; import { cloneElementWithCss } from '../emotion'; import { css, cx } from '../emotion/css'; @@ -117,6 +118,18 @@ export const EuiThemeProvider = ({ ) ); + // TODO: temp. testing code only, remove once obsolete + useEffect(() => { + if (process.env.NODE_ENV === 'development') { + const isEnabled = + localStorage.getItem(EUI_EXPERIMENTAL_THEME_ENABLED_KEY) != null; + + if (!isEnabled) { + localStorage.setItem(EUI_EXPERIMENTAL_THEME_ENABLED_KEY, 'true'); + } + } + }, []); + useEffect(() => { const newSystem = _system || parentSystem; if (prevSystemKey.current !== newSystem.key) { diff --git a/packages/eui/src/themes/index.ts b/packages/eui/src/themes/index.ts index cec3cda26c3..a77ffa51ee1 100644 --- a/packages/eui/src/themes/index.ts +++ b/packages/eui/src/themes/index.ts @@ -7,7 +7,11 @@ */ export type { EUI_THEME } from './themes'; -export { EUI_THEMES, isDefaultTheme } from './themes'; +export { + EUI_THEMES, + isDefaultTheme, + isExperimentalThemeEnabled, +} from './themes'; export { AMSTERDAM_NAME_KEY, EuiThemeAmsterdam } from './amsterdam/theme'; diff --git a/packages/eui/src/themes/themes.ts b/packages/eui/src/themes/themes.ts index d2f714092df..540fac2e5fe 100644 --- a/packages/eui/src/themes/themes.ts +++ b/packages/eui/src/themes/themes.ts @@ -31,3 +31,14 @@ export const EUI_THEMES: EUI_THEME[] = [ export const isDefaultTheme = (name: string) => { return name === AMSTERDAM_NAME_KEY; }; + +export const EUI_EXPERIMENTAL_THEME_ENABLED_KEY = + 'eui-experimental-theme-enabled'; + +export const isExperimentalThemeEnabled = () => { + if (typeof localStorage !== 'undefined') { + return localStorage.getItem(EUI_EXPERIMENTAL_THEME_ENABLED_KEY) === 'true'; + } + + return false; +}; From c2e5538564700d03c9f829c6920f1b8fed513f9a Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Thu, 19 Sep 2024 14:24:16 +0200 Subject: [PATCH 04/32] feat: add theme switcher to Storybook --- packages/eui/.storybook/decorator.tsx | 67 +++++++++++++++++++++++++-- packages/eui/.storybook/preview.tsx | 15 +++++- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/packages/eui/.storybook/decorator.tsx b/packages/eui/.storybook/decorator.tsx index 6b78a2e2353..d6e9657d997 100644 --- a/packages/eui/.storybook/decorator.tsx +++ b/packages/eui/.storybook/decorator.tsx @@ -6,12 +6,37 @@ * Side Public License, v 1. */ -import React, { useState, useMemo, FunctionComponent } from 'react'; +import React, { + useState, + useMemo, + FunctionComponent, + useEffect, + useCallback, +} from 'react'; import { css } from '@emotion/react'; import type { Preview } from '@storybook/react'; +import { EuiThemeBerlin } from '@elastic/eui-theme-berlin'; import { EuiThemeColorMode } from '../src/services'; import { EuiProvider, EuiProviderProps } from '../src/components/provider'; +import { EuiThemeAmsterdam } from '../src/themes'; + +const EXPERIMENTAL_THEMES = [ + { + text: 'Berlin', + value: EuiThemeBerlin.key, + provider: EuiThemeBerlin, + }, +]; + +export const AVAILABLE_THEMES = [ + { + text: 'Amsterdam', + value: EuiThemeAmsterdam.key, + provider: EuiThemeAmsterdam, + }, + ...EXPERIMENTAL_THEMES, +]; /** * Primary EuiProvider decorator to wrap around all stories @@ -20,8 +45,9 @@ import { EuiProvider, EuiProviderProps } from '../src/components/provider'; export const EuiProviderDecorator: FunctionComponent< EuiProviderProps<{}> & { writingMode: WritingModes; + themeName: string; } -> = ({ children, writingMode, ...euiProviderProps }) => { +> = ({ children, writingMode, themeName, theme, ...euiProviderProps }) => { // Append portals into Storybook's root div (rather than ) // so that loki correctly captures them for VRT screenshots const [sibling, setPortalSibling] = useState(null); @@ -39,8 +65,28 @@ export const EuiProviderDecorator: FunctionComponent< [writingMode] ); + const getTheme = useCallback(() => { + return AVAILABLE_THEMES.find((t) => themeName?.includes(t.value)); + }, [themeName]); + + const [_theme, setTheme] = useState(getTheme); + + useEffect(() => { + if (!themeName || theme) return; + + setTheme(getTheme); + }, [themeName, theme, getTheme]); + + const euiThemeProp = { + theme: theme ?? _theme?.provider, + }; + return ( - +
{portalInsert && children}
@@ -122,3 +168,18 @@ export const euiProviderDecoratorGlobals: Preview['globalTypes'] = { }, }, }; + +export const euiProviderDecoratorGlobalsExperimental = { + theme: { + description: 'Theme for EuiProvider', + defaultValue: EuiThemeAmsterdam.key, + toolbar: { + title: 'Theme', + items: [ + { value: EuiThemeAmsterdam.key, title: 'Amsterdam', icon: 'box' }, + { value: EuiThemeBerlin.key, title: 'Berlin', icon: 'box' }, + ], + dynamicTitle: true, + }, + }, +}; diff --git a/packages/eui/.storybook/preview.tsx b/packages/eui/.storybook/preview.tsx index c34435f5032..adf24f7f409 100644 --- a/packages/eui/.storybook/preview.tsx +++ b/packages/eui/.storybook/preview.tsx @@ -37,8 +37,13 @@ setEuiDevProviderWarning('error'); /** * Custom global decorators */ +import { isExperimentalThemeEnabled } from '../src/themes'; import { customJsxDecorator } from './addons/code-snippet/decorators/jsx_decorator'; -import { EuiProviderDecorator, euiProviderDecoratorGlobals } from './decorator'; +import { + EuiProviderDecorator, + euiProviderDecoratorGlobals, + euiProviderDecoratorGlobalsExperimental, +} from './decorator'; const preview: Preview = { decorators: [ @@ -48,12 +53,18 @@ const preview: Preview = { colorMode={context.globals.colorMode} {...(context.componentId === 'theming-euiprovider' && context.args)} writingMode={context.globals.writingMode} + themeName={context.globals.theme} > ), ], - globalTypes: { ...euiProviderDecoratorGlobals }, + globalTypes: isExperimentalThemeEnabled() + ? { + ...euiProviderDecoratorGlobals, + ...euiProviderDecoratorGlobalsExperimental, + } + : { ...euiProviderDecoratorGlobals }, parameters: { backgrounds: { disable: true }, // Use colorMode instead options: { From 51b59f1d322eba464e95d6550f1392f6f084914b Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Thu, 19 Sep 2024 14:25:00 +0200 Subject: [PATCH 05/32] feat: udpate theme switcher to eui docs --- .../guide_theme_selector.tsx | 9 ++++--- .../components/with_theme/theme_context.tsx | 27 +++++++++++++++++-- packages/eui/src-docs/src/index.js | 14 +++++++++- .../eui/src-docs/src/views/app_context.js | 10 ++++--- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/packages/eui/src-docs/src/components/guide_theme_selector/guide_theme_selector.tsx b/packages/eui/src-docs/src/components/guide_theme_selector/guide_theme_selector.tsx index bc9d4449b9d..0f99e738533 100644 --- a/packages/eui/src-docs/src/components/guide_theme_selector/guide_theme_selector.tsx +++ b/packages/eui/src-docs/src/components/guide_theme_selector/guide_theme_selector.tsx @@ -6,7 +6,8 @@ import { useEuiTheme, useIsWithinBreakpoints, } from '../../../../src/services'; -import { EUI_THEME, EUI_THEMES } from '../../../../src/themes'; +import { EUI_THEME } from '../../../../src/themes'; +import { AVAILABLE_THEMES } from '../with_theme/theme_context'; import { ThemeContext } from '../with_theme'; // @ts-ignore Not TS @@ -51,15 +52,15 @@ const GuideThemeSelectorComponent: React.FunctionComponent< const systemColorMode = useEuiTheme().colorMode.toLowerCase(); const currentTheme: EUI_THEME = - EUI_THEMES.find( + AVAILABLE_THEMES.find( (theme) => theme.value === (context.theme ?? systemColorMode) - ) || EUI_THEMES[0]; + ) || AVAILABLE_THEMES[0]; const getIconType = (value: EUI_THEME['value']) => { return value === currentTheme.value ? 'check' : 'empty'; }; - const items = EUI_THEMES.map((theme) => { + const items = AVAILABLE_THEMES.map((theme) => { return ( value); +const THEME_NAMES = AVAILABLE_THEMES.map(({ value }) => value); const THEME_LANGS = theme_languages.map(({ id }) => id); type ThemeContextType = { diff --git a/packages/eui/src-docs/src/index.js b/packages/eui/src-docs/src/index.js index a69a07e3613..d9cd2b13c35 100644 --- a/packages/eui/src-docs/src/index.js +++ b/packages/eui/src-docs/src/index.js @@ -4,6 +4,8 @@ import { Provider } from 'react-redux'; import { HashRouter, Switch, Route, Redirect } from 'react-router-dom'; import { Helmet } from 'react-helmet'; +import { isExperimentalThemeEnabled } from '../../src/themes'; + import configureStore from './store/configure_store'; import { AppContext } from './views/app_context'; @@ -13,13 +15,23 @@ import { NotFoundView } from './views/not_found/not_found_view'; import { registerTheme, ExampleContext } from './services'; import Routes from './routes'; +import { + ThemeProvider, + AVAILABLE_THEMES, +} from './components/with_theme/theme_context'; + +// TODO: update SCSS files for new theme once available import themeLight from './theme_light.scss'; import themeDark from './theme_dark.scss'; -import { ThemeProvider } from './components/with_theme/theme_context'; registerTheme('light', [themeLight]); registerTheme('dark', [themeDark]); +if (isExperimentalThemeEnabled()) { + registerTheme(AVAILABLE_THEMES[2].value, [themeLight]); + registerTheme(AVAILABLE_THEMES[3].value, [themeDark]); +} + // Set up app // Whether the docs app should be wrapped in diff --git a/packages/eui/src-docs/src/views/app_context.js b/packages/eui/src-docs/src/views/app_context.js index 729f4c94079..42645f5b2f1 100644 --- a/packages/eui/src-docs/src/views/app_context.js +++ b/packages/eui/src-docs/src/views/app_context.js @@ -11,7 +11,7 @@ import { setEuiDevProviderWarning, euiStylisPrefixer, } from '../../../src/services'; -import { EUI_THEMES } from '../../../src/themes'; +import { AVAILABLE_THEMES } from '../components/with_theme/theme_context'; import favicon16Prod from '../images/favicon/prod/favicon-16x16.png'; import favicon32Prod from '../images/favicon/prod/favicon-32x32.png'; @@ -55,9 +55,13 @@ export const AppContext = ({ children }) => { default: generalEmotionCache, utility: utilityCache, }} - theme={EUI_THEMES.find((t) => t.value === theme)?.provider} + theme={AVAILABLE_THEMES.find((t) => t.value === theme)?.provider} colorMode={ - theme ? (theme.includes('light') ? 'light' : 'dark') : undefined + theme + ? theme.toLowerCase().includes('light') + ? 'light' + : 'dark' + : undefined } > From 0c61e9044a5370d15dfb72834e8f8df3468c6499 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Thu, 19 Sep 2024 14:25:56 +0200 Subject: [PATCH 06/32] build: use workspace reference for EUI dependency - ensures current state EUI --- packages/docusaurus-theme/package.json | 2 +- packages/website/package.json | 2 +- yarn.lock | 57 ++------------------------ 3 files changed, 5 insertions(+), 56 deletions(-) diff --git a/packages/docusaurus-theme/package.json b/packages/docusaurus-theme/package.json index 0bdd0f5b122..5cfa3eece4e 100644 --- a/packages/docusaurus-theme/package.json +++ b/packages/docusaurus-theme/package.json @@ -34,7 +34,7 @@ "@docusaurus/theme-common": "^3.5.2", "@docusaurus/utils-validation": "^3.5.2", "@elastic/datemath": "^5.0.3", - "@elastic/eui": "94.5.0", + "@elastic/eui": "workspace:^", "@elastic/eui-docgen": "workspace:^", "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.4", diff --git a/packages/website/package.json b/packages/website/package.json index 959ba6e7b8d..77302ccfb73 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -18,7 +18,7 @@ "@docusaurus/core": "^3.5.2", "@docusaurus/preset-classic": "^3.5.2", "@elastic/datemath": "^5.0.3", - "@elastic/eui": "94.5.0", + "@elastic/eui": "workspace:^", "@elastic/eui-docgen": "workspace:^", "@elastic/eui-docusaurus-theme": "workspace:^", "@emotion/css": "^11.11.2", diff --git a/yarn.lock b/yarn.lock index fc194efdeb4..aebfae36179 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5719,7 +5719,7 @@ __metadata: "@docusaurus/types": "npm:^3.5.2" "@docusaurus/utils-validation": "npm:^3.5.2" "@elastic/datemath": "npm:^5.0.3" - "@elastic/eui": "npm:94.5.0" + "@elastic/eui": "workspace:^" "@elastic/eui-docgen": "workspace:^" "@emotion/css": "npm:^11.11.2" "@emotion/react": "npm:^11.11.4" @@ -5769,7 +5769,7 @@ __metadata: "@docusaurus/tsconfig": "npm:^3.5.2" "@docusaurus/types": "npm:^3.5.2" "@elastic/datemath": "npm:^5.0.3" - "@elastic/eui": "npm:94.5.0" + "@elastic/eui": "workspace:^" "@elastic/eui-docgen": "workspace:^" "@elastic/eui-docusaurus-theme": "workspace:^" "@emotion/css": "npm:^11.11.2" @@ -5789,58 +5789,7 @@ __metadata: languageName: unknown linkType: soft -"@elastic/eui@npm:94.5.0": - version: 94.5.0 - resolution: "@elastic/eui@npm:94.5.0" - dependencies: - "@hello-pangea/dnd": "npm:^16.6.0" - "@types/lodash": "npm:^4.14.202" - "@types/numeral": "npm:^2.0.5" - "@types/react-window": "npm:^1.8.8" - "@types/refractor": "npm:^3.4.0" - chroma-js: "npm:^2.4.2" - classnames: "npm:^2.5.1" - lodash: "npm:^4.17.21" - mdast-util-to-hast: "npm:^10.2.0" - numeral: "npm:^2.0.6" - prop-types: "npm:^15.8.1" - react-dropzone: "npm:^11.7.1" - react-element-to-jsx-string: "npm:^15.0.0" - react-focus-on: "npm:^3.9.1" - react-is: "npm:^17.0.2" - react-remove-scroll-bar: "npm:^2.3.4" - react-virtualized-auto-sizer: "npm:^1.0.24" - react-window: "npm:^1.8.10" - refractor: "npm:^3.6.0" - rehype-raw: "npm:^5.1.0" - rehype-react: "npm:^6.2.1" - rehype-stringify: "npm:^8.0.0" - remark-breaks: "npm:^2.0.2" - remark-emoji: "npm:^2.1.0" - remark-parse-no-trim: "npm:^8.0.4" - remark-rehype: "npm:^8.1.0" - tabbable: "npm:^5.3.3" - text-diff: "npm:^1.0.1" - unified: "npm:^9.2.2" - unist-util-visit: "npm:^2.0.3" - url-parse: "npm:^1.5.10" - uuid: "npm:^8.3.0" - vfile: "npm:^4.2.1" - peerDependencies: - "@elastic/datemath": ^5.0.2 - "@emotion/css": 11.x - "@emotion/react": 11.x - "@types/react": ^16.9 || ^17.0 || ^18.0 - "@types/react-dom": ^16.9 || ^17.0 || ^18.0 - moment: ^2.13.0 - react: ^16.12 || ^17.0 || ^18.0 - react-dom: ^16.12 || ^17.0 || ^18.0 - typescript: ~4.5.3 - checksum: 10c0/8735217fed4d961f12d4becee674629d5ca5ee80a742fc13ce7c0d66eb04055e17c0259f1d15138a6b4cfe50da76b06cdf3359df3a82c1adec9e9903d2b9acef - languageName: node - linkType: hard - -"@elastic/eui@workspace:packages/eui": +"@elastic/eui@workspace:^, @elastic/eui@workspace:packages/eui": version: 0.0.0-use.local resolution: "@elastic/eui@workspace:packages/eui" dependencies: From 13281dc406fb880b721fc243e643d476e204dbbf Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Thu, 19 Sep 2024 14:34:31 +0200 Subject: [PATCH 07/32] feat: add theme switcher to eui+ docs --- .../src/components/navbar_item/index.tsx | 4 +- .../src/components/theme_context/index.tsx | 58 +++++++++--- .../src/components/theme_switcher/index.tsx | 94 +++++++++++++++++++ .../src/theme/ColorModeToggle/index.tsx | 12 +-- .../docusaurus-theme/src/theme/Logo/index.tsx | 4 +- .../src/theme/Navbar/Content/index.tsx | 24 ++++- .../Navbar/MobileSidebar/Header/index.tsx | 3 + .../components/homepage/highlights/index.tsx | 6 -- 8 files changed, 177 insertions(+), 28 deletions(-) create mode 100644 packages/docusaurus-theme/src/components/theme_switcher/index.tsx diff --git a/packages/docusaurus-theme/src/components/navbar_item/index.tsx b/packages/docusaurus-theme/src/components/navbar_item/index.tsx index 130047a50e8..f4bacf65cfd 100644 --- a/packages/docusaurus-theme/src/components/navbar_item/index.tsx +++ b/packages/docusaurus-theme/src/components/navbar_item/index.tsx @@ -91,9 +91,9 @@ export const NavbarItem = (props: Props) => { } = props; const isBrowser = useIsBrowser(); - const { theme } = useContext(AppThemeContext); + const { colorMode } = useContext(AppThemeContext); - const isDarkMode = theme === 'dark'; + const isDarkMode = colorMode === 'dark'; const styles = useEuiMemoizedStyles(getStyles); const cssStyles = [ diff --git a/packages/docusaurus-theme/src/components/theme_context/index.tsx b/packages/docusaurus-theme/src/components/theme_context/index.tsx index d8a394fc8d5..19b92505ccd 100644 --- a/packages/docusaurus-theme/src/components/theme_context/index.tsx +++ b/packages/docusaurus-theme/src/components/theme_context/index.tsx @@ -5,17 +5,39 @@ import { useState, } from 'react'; import useIsBrowser from '@docusaurus/useIsBrowser'; -import { EUI_THEMES, EuiProvider, EuiThemeColorMode } from '@elastic/eui'; +import { + EuiProvider, + EuiThemeAmsterdam, + EuiThemeColorMode, +} from '@elastic/eui'; +import { EuiThemeBerlin } from '@elastic/eui-theme-berlin'; import { EuiThemeOverrides } from './theme_overrides'; -const EUI_THEME_NAMES = EUI_THEMES.map( - ({ value }) => value -) as EuiThemeColorMode[]; +const EXPERIMENTAL_THEMES = [ + { + text: 'Berlin', + value: EuiThemeBerlin.key, + provider: EuiThemeBerlin, + }, +]; + +export const AVAILABLE_THEMES = [ + { + text: 'Amsterdam', + value: EuiThemeAmsterdam.key, + provider: EuiThemeAmsterdam, + }, + ...EXPERIMENTAL_THEMES, +]; + +const EUI_COLOR_MODES = ['light', 'dark'] as EuiThemeColorMode[]; const defaultState = { - theme: EUI_THEME_NAMES[0] as EuiThemeColorMode, - changeTheme: (themeValue: EuiThemeColorMode) => {}, + colorMode: EUI_COLOR_MODES[0] as EuiThemeColorMode, + changeColorMode: (colorMode: EuiThemeColorMode) => {}, + theme: AVAILABLE_THEMES[0]!, + changeTheme: (themeValue: string) => {}, }; export const AppThemeContext = createContext(defaultState); @@ -24,25 +46,39 @@ export const AppThemeProvider: FunctionComponent = ({ children, }) => { const isBrowser = useIsBrowser(); - const [theme, setTheme] = useState(() => { + const [colorMode, setColorMode] = useState(() => { if (isBrowser) { - return localStorage.getItem('theme') as EuiThemeColorMode ?? defaultState.theme; + return ( + (localStorage.getItem('theme') as EuiThemeColorMode) ?? + defaultState.colorMode + ); } - return defaultState.theme; + return defaultState.colorMode; }); + const [theme, setTheme] = useState(defaultState.theme); + + const handleChangeTheme = (themeValue: string) => { + const themeObj = AVAILABLE_THEMES.find((t) => t.value === themeValue); + + setTheme((currentTheme) => themeObj ?? currentTheme); + }; + return ( {children} diff --git a/packages/docusaurus-theme/src/components/theme_switcher/index.tsx b/packages/docusaurus-theme/src/components/theme_switcher/index.tsx new file mode 100644 index 00000000000..eeb4a1706d3 --- /dev/null +++ b/packages/docusaurus-theme/src/components/theme_switcher/index.tsx @@ -0,0 +1,94 @@ +import { useContext, useEffect, useState } from 'react'; +import { css } from '@emotion/react'; +import { + EuiAvatar, + EuiButtonEmpty, + euiFocusRing, + EuiListGroup, + EuiListGroupItem, + EuiPopover, + useEuiMemoizedStyles, + useEuiTheme, + UseEuiTheme, +} from '@elastic/eui'; + +import { AppThemeContext, AVAILABLE_THEMES } from '../theme_context'; + +const getStyles = (euiThemeContext: UseEuiTheme) => { + const { euiTheme } = euiThemeContext; + + return { + button: css` + padding: 0; + `, + listItem: css` + .euiListGroupItem__button:focus-visible { + // overriding the global "outset" style to ensure the focus style is not cut off + ${euiFocusRing(euiThemeContext, 'inset', { + color: euiTheme.colors.primary, + })}; + } + `, + }; +}; + +export const ThemeSwitcher = () => { + const { euiTheme } = useEuiTheme(); + const [currentTheme, setCurrentTheme] = useState( + AVAILABLE_THEMES[0]?.value ?? '' + ); + const [isPopoverOpen, setPopoverOpen] = useState(false); + const { theme, changeTheme } = useContext(AppThemeContext); + + useEffect(() => { + changeTheme(currentTheme); + }, [currentTheme]); + + const styles = useEuiMemoizedStyles(getStyles); + + const button = ( + setPopoverOpen((isOpen) => !isOpen)} + aria-label={`${theme.text} theme`} + > + + + ); + + return ( + setPopoverOpen(false)} + button={button} + panelPaddingSize="xs" + repositionOnScroll + aria-label="EUI theme list" + > + + {AVAILABLE_THEMES && + AVAILABLE_THEMES.map((theme) => { + const isCurrentTheme = currentTheme === theme.value; + + const handleOnClick = () => { + setCurrentTheme(theme.value); + }; + + return ( + + ); + })} + + + ); +}; diff --git a/packages/docusaurus-theme/src/theme/ColorModeToggle/index.tsx b/packages/docusaurus-theme/src/theme/ColorModeToggle/index.tsx index aaefb2441bc..970e11e0397 100644 --- a/packages/docusaurus-theme/src/theme/ColorModeToggle/index.tsx +++ b/packages/docusaurus-theme/src/theme/ColorModeToggle/index.tsx @@ -17,20 +17,20 @@ function ColorModeToggle({ onChange, ...rest }: WrappedProps): JSX.Element { - const { theme, changeTheme } = useContext(AppThemeContext); + const { colorMode, changeColorMode } = useContext(AppThemeContext); useEffect(() => { - changeTheme(value); + changeColorMode(value); }, []); - const handleOnChange = (themeName: EuiThemeColorMode) => { - changeTheme(themeName); - onChange?.(themeName); + const handleOnChange = (colorMode: EuiThemeColorMode) => { + changeColorMode(colorMode); + onChange?.(colorMode); }; return ( diff --git a/packages/docusaurus-theme/src/theme/Logo/index.tsx b/packages/docusaurus-theme/src/theme/Logo/index.tsx index 3f64a7bd951..ff434592173 100644 --- a/packages/docusaurus-theme/src/theme/Logo/index.tsx +++ b/packages/docusaurus-theme/src/theme/Logo/index.tsx @@ -62,8 +62,8 @@ function LogoThemedImage({ alt: string; imageClassName?: string; }) { - const { theme } = useContext(AppThemeContext); - const isDarkMode = theme === 'dark'; + const { colorMode } = useContext(AppThemeContext); + const isDarkMode = colorMode === 'dark'; const styles = useEuiMemoizedStyles(getStyles); diff --git a/packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx b/packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx index 53b4f771ead..5fcac599372 100644 --- a/packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx +++ b/packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx @@ -15,7 +15,13 @@ import SearchBar from '@theme-original/SearchBar'; import NavbarMobileSidebarToggle from '@theme-original/Navbar/MobileSidebar/Toggle'; import NavbarLogo from '@theme-original/Navbar/Logo'; import NavbarSearch from '@theme-original/Navbar/Search'; -import { euiFocusRing, useEuiMemoizedStyles, UseEuiTheme } from '@elastic/eui'; +import { + euiFocusRing, + euiTextTruncate, + useEuiMemoizedStyles, + UseEuiTheme, + isExperimentalThemeEnabled, +} from '@elastic/eui'; import { euiFormControlText, euiFormVariables, @@ -24,6 +30,7 @@ import { import euiVersions from '@site/static/versions.json'; import { VersionSwitcher } from '../../../components/version_switcher'; +import { ThemeSwitcher } from '../../../components/theme_switcher'; const DOCS_PATH = '/docs'; @@ -67,6 +74,10 @@ const getStyles = (euiThemeContext: UseEuiTheme) => { @media (min-width: 997px) { gap: ${euiTheme.size.l}; } + + .navbar__link { + ${euiTextTruncate()} + } `, navbarItemsRight: css` gap: ${euiTheme.size.s}; @@ -125,6 +136,11 @@ const getStyles = (euiThemeContext: UseEuiTheme) => { display: none; } `, + themeSwitcher: css` + @media (max-width: 996px) { + display: none; + } + `, }; }; @@ -218,6 +234,12 @@ export default function NavbarContent(): JSX.Element { )} + + {isBrowser && isExperimentalThemeEnabled() && ( +
+ +
+ )} } /> diff --git a/packages/docusaurus-theme/src/theme/Navbar/MobileSidebar/Header/index.tsx b/packages/docusaurus-theme/src/theme/Navbar/MobileSidebar/Header/index.tsx index 08791e527a8..0e0daa13ed1 100644 --- a/packages/docusaurus-theme/src/theme/Navbar/MobileSidebar/Header/index.tsx +++ b/packages/docusaurus-theme/src/theme/Navbar/MobileSidebar/Header/index.tsx @@ -9,6 +9,8 @@ import useIsBrowser from '@docusaurus/useIsBrowser'; import euiVersions from '@site/static/versions.json'; import { VersionSwitcher } from '../../../../components/version_switcher'; +import { ThemeSwitcher } from '../../../../components/theme_switcher'; +import { isExperimentalThemeEnabled } from '@elastic/eui/lib/themes/themes'; const getStyles = ({ euiTheme }: UseEuiTheme) => ({ sidebar: css` @@ -64,6 +66,7 @@ export default function NavbarMobileSidebarHeader(): JSX.Element {
{isBrowser && versions && } + {isBrowser && isExperimentalThemeEnabled() && }
diff --git a/packages/website/src/components/homepage/highlights/index.tsx b/packages/website/src/components/homepage/highlights/index.tsx index 53b97525d70..5e920ee45d6 100644 --- a/packages/website/src/components/homepage/highlights/index.tsx +++ b/packages/website/src/components/homepage/highlights/index.tsx @@ -3,7 +3,6 @@ import { EuiButtonEmpty, EuiCard, EuiIcon, - EuiImage, EuiText, EuiTextAlign, useEuiMemoizedStyles, @@ -12,8 +11,6 @@ import { } from '@elastic/eui'; import { HomepageContainer, HomepageSection } from '../layout'; import { css } from '@emotion/react'; -import { useContext } from 'react'; -import { AppThemeContext } from '@elastic/eui-docusaurus-theme/lib/components/theme_context/index.js'; import SvgFlex from './svg/flex.svg'; import SvgSpacer from './svg/spacer.svg'; @@ -223,10 +220,7 @@ const getStyles = ({ euiTheme, colorMode }: UseEuiTheme) => ({ }); export const HomepageHighlights = () => { - const { theme } = useContext(AppThemeContext); const styles = useEuiMemoizedStyles(getStyles); - const isDarkMode = theme === 'dark'; - const headingId = useGeneratedHtmlId(); return ( From 9cdacbe749a654e7c4b23a8a447665dbec37304d Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Sun, 22 Sep 2024 16:00:26 +0200 Subject: [PATCH 08/32] build: add eui-common internal module package --- packages/eui-common/.eslintignore | 9 + packages/eui-common/.eslintplugin.js | 3 + packages/eui-common/.eslintrc.js | 115 ++++++++++++ packages/eui-common/.gitignore | 11 ++ packages/eui-common/.prettierrc | 7 + packages/eui-common/LICENSE.txt | 6 + packages/eui-common/README.md | 1 + packages/eui-common/babel.config.js | 6 + packages/eui-common/package.json | 48 +++++ .../require_license_header.js | 132 +++++++++++++ .../require_license_header.test.js | 177 ++++++++++++++++++ .../src/global_styling/functions/index.ts | 9 + .../src/global_styling/functions/size.ts | 26 +++ packages/eui-common/src/index.ts | 10 + packages/eui-common/src/types.ts | 56 ++++++ packages/eui-common/tsconfig.json | 27 +++ yarn.lock | 55 +++++- 17 files changed, 695 insertions(+), 3 deletions(-) create mode 100644 packages/eui-common/.eslintignore create mode 100644 packages/eui-common/.eslintplugin.js create mode 100644 packages/eui-common/.eslintrc.js create mode 100644 packages/eui-common/.gitignore create mode 100644 packages/eui-common/.prettierrc create mode 100644 packages/eui-common/LICENSE.txt create mode 100644 packages/eui-common/README.md create mode 100644 packages/eui-common/babel.config.js create mode 100644 packages/eui-common/package.json create mode 100644 packages/eui-common/scripts/eslint-plugin-local/require_license_header.js create mode 100644 packages/eui-common/scripts/eslint-plugin-local/require_license_header.test.js create mode 100644 packages/eui-common/src/global_styling/functions/index.ts create mode 100644 packages/eui-common/src/global_styling/functions/size.ts create mode 100644 packages/eui-common/src/index.ts create mode 100644 packages/eui-common/src/types.ts create mode 100644 packages/eui-common/tsconfig.json diff --git a/packages/eui-common/.eslintignore b/packages/eui-common/.eslintignore new file mode 100644 index 00000000000..4874b17b0b8 --- /dev/null +++ b/packages/eui-common/.eslintignore @@ -0,0 +1,9 @@ +dist +node_modules +lib +types +**/*.d.ts +package.json +scripts +.eslintrc.js +babel.config.js diff --git a/packages/eui-common/.eslintplugin.js b/packages/eui-common/.eslintplugin.js new file mode 100644 index 00000000000..25ddbe3db65 --- /dev/null +++ b/packages/eui-common/.eslintplugin.js @@ -0,0 +1,3 @@ +exports.rules = { + 'require-license-header': require('./scripts/eslint-plugin-local/require_license_header.js'), +}; diff --git a/packages/eui-common/.eslintrc.js b/packages/eui-common/.eslintrc.js new file mode 100644 index 00000000000..2d464dca972 --- /dev/null +++ b/packages/eui-common/.eslintrc.js @@ -0,0 +1,115 @@ +const SSPL_ELASTIC_2_0_LICENSE_HEADER = ` +/* + * 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. + */ +`; + +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: ['./tsconfig.json'], + ecmaFeatures: { + jsx: true, + }, + }, + settings: { + 'import/resolver': { + node: { + extensions: ['.ts', '.tsx', '.js', '.json'], + paths: ['.'], + }, + }, + }, + extends: [ + 'plugin:@typescript-eslint/recommended', + // Prettier options need to come last, in order to override other style rules + 'plugin:prettier/recommended', + ], + plugins: ['local', 'import'], + rules: { + 'block-scoped-var': 'error', + camelcase: 'off', + 'dot-notation': ['error', { allowKeywords: true }], + eqeqeq: ['error', 'always', { null: 'ignore' }], + 'guard-for-in': 'error', + 'new-cap': ['error', { capIsNewExceptions: ['Private'] }], + 'no-caller': 'error', + 'no-const-assign': 'error', + 'no-debugger': 'error', + 'no-empty': ['error', { allowEmptyCatch: true }], + 'no-eval': 'error', + 'no-extend-native': 'error', + 'no-global-assign': 'error', + 'no-loop-func': 'error', + 'no-restricted-globals': ['error', 'context'], + 'no-script-url': 'error', + 'no-sequences': 'error', + 'no-var': 'error', + 'no-with': 'error', + 'prefer-const': 'error', + 'prefer-template': 'error', + strict: ['error', 'never'], + 'valid-typeof': 'error', + + 'local/require-license-header': [ + 'warn', + { + license: SSPL_ELASTIC_2_0_LICENSE_HEADER, + }, + ], + + 'import/no-unresolved': ['error', { amd: true, commonjs: true }], + 'import/namespace': 'error', + 'import/default': 'error', + 'import/export': 'error', + 'import/no-named-as-default': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-duplicates': 'error', + + '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-member-accessibility': 'off', + '@typescript-eslint/indent': 'off', + '@typescript-eslint/ban-tslint-comment': 'error', + '@typescript-eslint/no-empty-interface': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-parameter-properties': 'off', + '@typescript-eslint/no-triple-slash-reference': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { argsIgnorePattern: '^_', ignoreRestSiblings: true }, + ], + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-empty-function': 'off', + // It"s all very well saying that some types are trivially inferrable, + // but being explicit is still clearer. + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-ignore': 'allow-with-description', + 'ts-expect-error': 'allow-with-description', + }, + ], + '@typescript-eslint/consistent-type-exports': [ + 'error', + { fixMixedExportsWithInlineTypeSpecifier: false }, + ], + }, + overrides: [ + { + files: ['*.d.ts'], + rules: { + 'react/prefer-es6-class': 'off', + }, + }, + ], +}; diff --git a/packages/eui-common/.gitignore b/packages/eui-common/.gitignore new file mode 100644 index 00000000000..4450fe8d868 --- /dev/null +++ b/packages/eui-common/.gitignore @@ -0,0 +1,11 @@ +# Dependencies +/node_modules + +# Production +/lib + +yarn-debug.log* +yarn-error.log* + +# Build-related files +.eslintcache \ No newline at end of file diff --git a/packages/eui-common/.prettierrc b/packages/eui-common/.prettierrc new file mode 100644 index 00000000000..b2f0fa8f00e --- /dev/null +++ b/packages/eui-common/.prettierrc @@ -0,0 +1,7 @@ +{ + "parser": "typescript", + "printWidth": 80, + "semi": true, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/packages/eui-common/LICENSE.txt b/packages/eui-common/LICENSE.txt new file mode 100644 index 00000000000..74327a8f6f3 --- /dev/null +++ b/packages/eui-common/LICENSE.txt @@ -0,0 +1,6 @@ +Source code in this repository is covered by (i) a dual license under the Server +Side Public License, v 1 and the Elastic License 2.0 or (ii) an Apache License +2.0 compatible license or (iii) solely under the Elastic License 2.0, in each +case, as noted in the applicable header. The default throughout the repository +is a dual license under the Server Side Public License, v 1 and the Elastic +License 2.0, unless the header specifies another license. diff --git a/packages/eui-common/README.md b/packages/eui-common/README.md new file mode 100644 index 00000000000..7531d756f9a --- /dev/null +++ b/packages/eui-common/README.md @@ -0,0 +1 @@ +# EUI common, shared functionality \ No newline at end of file diff --git a/packages/eui-common/babel.config.js b/packages/eui-common/babel.config.js new file mode 100644 index 00000000000..8165fe45577 --- /dev/null +++ b/packages/eui-common/babel.config.js @@ -0,0 +1,6 @@ +module.exports = { + presets: [ + ['@babel/preset-env', { targets: { node: 'current' } }], + '@babel/preset-typescript', + ], +}; diff --git a/packages/eui-common/package.json b/packages/eui-common/package.json new file mode 100644 index 00000000000..5ea8a9a5e9c --- /dev/null +++ b/packages/eui-common/package.json @@ -0,0 +1,48 @@ +{ + "name": "@elastic/eui-common", + "version": "0.0.1", + "description": "Common shared EUI functionality", + "license": "SEE LICENSE IN LICENSE.txt", + "scripts": { + "build": "tsc", + "lint": "yarn tsc --noEmit && yarn lint-es", + "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", + "test": "jest" + }, + "repository": { + "type": "git", + "url": "https://github.com/elastic/eui.git", + "directory": "packages/eui-common" + }, + "private": true, + "devDependencies": { + "@types/jest": "^29.5.12", + "@types/prettier": "2.7.3", + "@typescript-eslint/eslint-plugin": "^5.59.7", + "@typescript-eslint/parser": "^5.59.7", + "eslint": "^8.41.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jest": "^28.5.0", + "eslint-plugin-local": "^1.0.0", + "eslint-plugin-prettier": "^4.2.1", + "jest": "^29.7.0", + "prettier": "^2.8.8", + "typescript": "^5.6.2" + }, + "main": "lib/index.js", + "exports": { + "./lib/*": "./lib/*", + "./scripts/*": "./scripts/*", + ".": { + "default": "./lib/index.js" + } + }, + "files": [ + "lib/", + "README.md" + ], + "installConfig": { + "hoistingLimits": "workspaces" + } +} diff --git a/packages/eui-common/scripts/eslint-plugin-local/require_license_header.js b/packages/eui-common/scripts/eslint-plugin-local/require_license_header.js new file mode 100644 index 00000000000..23b83648dd1 --- /dev/null +++ b/packages/eui-common/scripts/eslint-plugin-local/require_license_header.js @@ -0,0 +1,132 @@ +const eslintParser = require('@typescript-eslint/parser'); + +function assert(truth, message) { + if (truth) { + return; + } + + const error = new Error(message); + error.failedAssertion = true; + throw error; +} + +function normalizeWhitespace(string) { + return string.replace(/\s+/g, ' '); +} + +function init(context, program, initStep) { + try { + return initStep(); + } catch (error) { + if (error.failedAssertion) { + context.report({ + node: program, + message: error.message, + }); + } else { + throw error; + } + } +} + +function isHashbang(text) { + return text.trim().startsWith('#!') && !text.trim().includes('\n'); +} + +module.exports = { + meta: { + fixable: 'code', + schema: [ + { + type: 'object', + properties: { + license: { + type: 'string', + }, + }, + additionalProperties: false, + }, + ], + }, + create: (context) => { + return { + Program(program) { + const license = init(context, program, function () { + const options = context.options[0] || {}; + const license = options.license; + + assert(!!license, '"license" option is required'); + + const parsed = eslintParser.parse(license, { comment: true }); + assert( + !parsed.body.length, + '"license" option must only include a single comment' + ); + assert( + parsed.comments.length === 1, + '"license" option must only include a single comment' + ); + + return { + source: license, + nodeValue: normalizeWhitespace(parsed.comments[0].value), + }; + }); + + if (!license) { + return; + } + + const sourceCode = context.getSourceCode(); + const comment = sourceCode + .getAllComments() + .find( + (node) => normalizeWhitespace(node.value) === license.nodeValue + ); + + // no licence comment + if (!comment) { + context.report({ + message: 'File must start with a license header', + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: sourceCode.lines[0].length - 1 }, + }, + fix(fixer) { + if (isHashbang(sourceCode.lines[0])) { + return undefined; + } + + return fixer.replaceTextRange([0, 0], license.source + '\n\n'); + }, + }); + return; + } + + // ensure there is nothing before the comment + const sourceBeforeNode = sourceCode + .getText() + .slice(0, sourceCode.getIndexFromLoc(comment.loc.start)); + if (sourceBeforeNode.length && !isHashbang(sourceBeforeNode)) { + context.report({ + node: comment, + message: 'License header must be at the very beginning of the file', + fix(fixer) { + // replace leading whitespace if possible + if (sourceBeforeNode.trim() === '') { + return fixer.replaceTextRange([0, sourceBeforeNode.length], ''); + } + + // inject content at top and remove node from current location + // if removing whitespace is not possible + return [ + fixer.remove(comment), + fixer.replaceTextRange([0, 0], license.source + '\n\n'), + ]; + }, + }); + } + }, + }; + }, +}; diff --git a/packages/eui-common/scripts/eslint-plugin-local/require_license_header.test.js b/packages/eui-common/scripts/eslint-plugin-local/require_license_header.test.js new file mode 100644 index 00000000000..904dff17bc0 --- /dev/null +++ b/packages/eui-common/scripts/eslint-plugin-local/require_license_header.test.js @@ -0,0 +1,177 @@ +const { RuleTester } = require('eslint'); +const rule = require('./require_license_header'); +const dedent = require('dedent'); + +const ruleTester = new RuleTester({ + parser: require.resolve('@typescript-eslint/parser'), +}); + +ruleTester.run('@kbn/eslint/require-license-header', rule, { + valid: [ + { + code: dedent` + /* license */ + + console.log('foo') + `, + + options: [{ license: '/* license */' }], + }, + { + code: dedent` + // license + + console.log('foo') + `, + + options: [{ license: '// license' }], + }, + ], + + invalid: [ + // missing license option + { + code: dedent` + console.log('foo') + `, + + options: [], + errors: [ + { + message: '"license" option is required', + }, + ], + }, + + // content cannot contain multiple block comments + { + code: dedent` + console.log('foo') + `, + + options: [{ license: '/* one *//* two */' }], + errors: [ + { + message: '"license" option must only include a single comment', + }, + ], + }, + + // content cannot contain multiple line comments + { + code: dedent` + console.log('foo') + `, + + options: [{ license: `// one\n// two` }], + errors: [ + { + message: '"license" option must only include a single comment', + }, + ], + }, + + // content cannot contain expressions + { + code: dedent` + console.log('foo') + `, + + options: [ + { + license: dedent` + /* license */ + console.log('hello world'); + `, + }, + ], + errors: [ + { + message: '"license" option must only include a single comment', + }, + ], + }, + + // content is not a single comment + { + code: dedent` + console.log('foo') + `, + + options: [{ license: `console.log('hello world');` }], + errors: [ + { + message: '"license" option must only include a single comment', + }, + ], + }, + + // missing license header + { + code: dedent` + console.log('foo') + `, + + options: [{ license: '/* license */' }], + errors: [ + { + message: 'File must start with a license header', + }, + ], + + output: dedent` + /* license */ + + console.log('foo') + `, + }, + + // strips newlines before the license comment + { + code: + '\n\n' + + dedent` + /* license */ + + console.log('foo') + `, + + options: [{ license: '/* license */' }], + errors: [ + { + message: 'License header must be at the very beginning of the file', + }, + ], + + output: dedent` + /* license */ + + console.log('foo') + `, + }, + + // moves license header before other nodes if necessary + { + code: dedent` + /* not license */ + /* license */ + console.log('foo') + `, + + options: [{ license: '/* license */' }], + errors: [ + { + message: 'License header must be at the very beginning of the file', + }, + ], + + output: dedent` + /* license */ + + /* not license */ + + console.log('foo') + `, + }, + ], +}); diff --git a/packages/eui-common/src/global_styling/functions/index.ts b/packages/eui-common/src/global_styling/functions/index.ts new file mode 100644 index 00000000000..5b07f8b8473 --- /dev/null +++ b/packages/eui-common/src/global_styling/functions/index.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export * from './size'; diff --git a/packages/eui-common/src/global_styling/functions/size.ts b/packages/eui-common/src/global_styling/functions/size.ts new file mode 100644 index 00000000000..a96b5b85452 --- /dev/null +++ b/packages/eui-common/src/global_styling/functions/size.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +/* TODO: move to a shared module package */ + +/** + * Calculates the `px` value based on a scale multiplier + * @param scale - The font scale multiplier + * * + * @param themeOrBase - Theme base value + * * + * @returns string - Rem unit aligned to baseline + */ + +export const sizeToPixel = + (scale: number = 1) => + (themeOrBase: number | { base: number; [key: string]: any }) => { + const base = + typeof themeOrBase === 'object' ? themeOrBase.base : themeOrBase; + return `${base * scale}px`; + }; diff --git a/packages/eui-common/src/index.ts b/packages/eui-common/src/index.ts new file mode 100644 index 00000000000..e86804db831 --- /dev/null +++ b/packages/eui-common/src/index.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +export * from './types'; +export * from './global_styling/functions'; diff --git a/packages/eui-common/src/types.ts b/packages/eui-common/src/types.ts new file mode 100644 index 00000000000..68c72d586df --- /dev/null +++ b/packages/eui-common/src/types.ts @@ -0,0 +1,56 @@ +/* + * 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. + */ + +/* TODO: duplicated types from /eui/src/components/common - extract to shared location */ + +/** + * Like `keyof typeof`, but for getting values instead of keys + * ValueOf + * Results in `'value1' | 'value2'` + */ +export type ValueOf = T[keyof T]; + +/** + * Replaces all properties on any type as optional, includes nested types + * + * @example + * ```ts + * interface Person { + * name: string; + * age?: number; + * spouse: Person; + * children: Person[]; + * } + * type PartialPerson = RecursivePartial; + * // results in + * interface PartialPerson { + * name?: string; + * age?: number; + * spouse?: RecursivePartial; + * children?: RecursivePartial[] + * } + * ``` + */ +export type RecursivePartial = { + [P in keyof T]?: T[P] extends NonAny[] // checks for nested any[] + ? T[P] + : T[P] extends readonly NonAny[] // checks for nested ReadonlyArray + ? T[P] + : T[P] extends Array + ? Array> + : T[P] extends ReadonlyArray + ? ReadonlyArray> + : T[P] extends Set // checks for Sets + ? Set> + : T[P] extends Map // checks for Maps + ? Map> + : T[P] extends NonAny // checks for primitive values + ? T[P] + : RecursivePartial; // recurse for all non-array and non-primitive values +}; +type NonAny = number | boolean | string | symbol | null; diff --git a/packages/eui-common/tsconfig.json b/packages/eui-common/tsconfig.json new file mode 100644 index 00000000000..c3190be619a --- /dev/null +++ b/packages/eui-common/tsconfig.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib", + "target": "ES2020", + "lib": [ + "ESNext", + "DOM" + ], + "moduleResolution": "Node", + "declaration": true, + "sourceMap": true, + "noEmitHelpers": true, + "incremental": true, + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "tsBuildInfoFile": "lib/.tsbuildinfo" + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules" + ], +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index aebfae36179..442b2ef4c5b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5696,6 +5696,26 @@ __metadata: languageName: unknown linkType: soft +"@elastic/eui-common@workspace:^, @elastic/eui-common@workspace:packages/eui-common": + version: 0.0.0-use.local + resolution: "@elastic/eui-common@workspace:packages/eui-common" + dependencies: + "@types/jest": "npm:^29.5.12" + "@types/prettier": "npm:2.7.3" + "@typescript-eslint/eslint-plugin": "npm:^5.59.7" + "@typescript-eslint/parser": "npm:^5.59.7" + eslint: "npm:^8.41.0" + eslint-config-prettier: "npm:^8.8.0" + eslint-plugin-import: "npm:^2.27.5" + eslint-plugin-jest: "npm:^28.5.0" + eslint-plugin-local: "npm:^1.0.0" + eslint-plugin-prettier: "npm:^4.2.1" + jest: "npm:^29.7.0" + prettier: "npm:^2.8.8" + typescript: "npm:^5.6.2" + languageName: unknown + linkType: soft + "@elastic/eui-docgen@workspace:^, @elastic/eui-docgen@workspace:packages/eui-docgen": version: 0.0.0-use.local resolution: "@elastic/eui-docgen@workspace:packages/eui-docgen" @@ -5721,6 +5741,7 @@ __metadata: "@elastic/datemath": "npm:^5.0.3" "@elastic/eui": "workspace:^" "@elastic/eui-docgen": "workspace:^" + "@elastic/eui-theme-berlin": "workspace:^" "@emotion/css": "npm:^11.11.2" "@emotion/react": "npm:^11.11.4" "@types/react": "npm:^18.3.3" @@ -5748,13 +5769,38 @@ __metadata: languageName: unknown linkType: soft -"@elastic/eui-theme-berlin@workspace:packages/eui-theme-berlin": +"@elastic/eui-theme-base@workspace:^, @elastic/eui-theme-base@workspace:packages/eui-theme-base": + version: 0.0.0-use.local + resolution: "@elastic/eui-theme-base@workspace:packages/eui-theme-base" + dependencies: + "@elastic/eui-common": "workspace:^" + "@types/jest": "npm:^29.5.12" + "@types/prettier": "npm:2.7.3" + "@typescript-eslint/eslint-plugin": "npm:^5.59.7" + "@typescript-eslint/parser": "npm:^5.59.7" + eslint: "npm:^8.41.0" + eslint-config-prettier: "npm:^8.8.0" + eslint-plugin-import: "npm:^2.27.5" + eslint-plugin-jest: "npm:^28.5.0" + eslint-plugin-local: "npm:^1.0.0" + eslint-plugin-prettier: "npm:^4.2.1" + jest: "npm:^29.7.0" + prettier: "npm:^2.8.8" + stylelint: "npm:^15.7.0" + stylelint-config-prettier-scss: "npm:^1.0.0" + stylelint-config-standard: "npm:^33.0.0" + stylelint-config-standard-scss: "npm:^9.0.0" + typescript: "npm:^5.6.2" + languageName: unknown + linkType: soft + +"@elastic/eui-theme-berlin@workspace:^, @elastic/eui-theme-berlin@workspace:packages/eui-theme-berlin": version: 0.0.0-use.local resolution: "@elastic/eui-theme-berlin@workspace:packages/eui-theme-berlin" dependencies: + "@elastic/eui-common": "workspace:^" + "@elastic/eui-theme-base": "workspace:^" typescript: "npm:^5.6.2" - peerDependencies: - "@elastic/eui": ^95.10.1 languageName: unknown linkType: soft @@ -5810,6 +5856,9 @@ __metadata: "@cypress/webpack-dev-server": "npm:^1.7.0" "@elastic/charts": "npm:^64.1.0" "@elastic/datemath": "npm:^5.0.3" + "@elastic/eui-common": "workspace:^" + "@elastic/eui-theme-base": "workspace:^" + "@elastic/eui-theme-berlin": "workspace:^" "@emotion/babel-preset-css-prop": "npm:^11.11.0" "@emotion/cache": "npm:^11.11.0" "@emotion/css": "npm:^11.11.0" From 5f618e0619afc3bc6c20bee4eed21342d8998d0d Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Sun, 22 Sep 2024 16:01:11 +0200 Subject: [PATCH 09/32] build: add eui-theme-base internal module package --- packages/eui-theme-base/.eslintignore | 9 + packages/eui-theme-base/.eslintplugin.js | 3 + packages/eui-theme-base/.eslintrc.js | 114 +++++ packages/eui-theme-base/.gitignore | 11 + packages/eui-theme-base/.prettierrc | 7 + packages/eui-theme-base/.stylelintrc.js | 163 ++++++++ packages/eui-theme-base/LICENSE.txt | 6 + packages/eui-theme-base/README.md | 1 + packages/eui-theme-base/babel.config.js | 6 + packages/eui-theme-base/package.json | 55 +++ packages/eui-theme-base/src/index.ts | 11 + packages/eui-theme-base/src/types.ts | 105 +++++ packages/eui-theme-base/src/utils.test.ts | 279 +++++++++++++ packages/eui-theme-base/src/utils.ts | 392 ++++++++++++++++++ .../src/variables/_animations.scss | 13 + .../src/variables/_borders.scss | 11 + .../src/variables/_buttons.scss | 19 + .../src/variables/_colors_vis.scss | 72 ++++ .../src/variables/_colors_vis.ts | 62 +++ .../src/variables/_font_weight.scss | 10 + .../eui-theme-base/src/variables/_form.scss | 59 +++ .../eui-theme-base/src/variables/_index.scss | 26 ++ .../eui-theme-base/src/variables/_page.scss | 2 + .../eui-theme-base/src/variables/_panel.scss | 21 + .../src/variables/_responsive.scss | 9 + .../src/variables/_shadows.scss | 2 + .../eui-theme-base/src/variables/_size.scss | 15 + .../eui-theme-base/src/variables/_states.scss | 14 + .../src/variables/_tool_tip.scss | 9 + .../src/variables/_typography.scss | 75 ++++ .../src/variables/_z_index.scss | 34 ++ .../src/variables/animations.ts | 66 +++ .../eui-theme-base/src/variables/borders.ts | 74 ++++ .../src/variables/breakpoint.ts | 28 ++ .../eui-theme-base/src/variables/colors.ts | 156 +++++++ .../eui-theme-base/src/variables/index.ts | 18 + .../eui-theme-base/src/variables/levels.ts | 60 +++ .../eui-theme-base/src/variables/shadow.ts | 28 ++ packages/eui-theme-base/src/variables/size.ts | 47 +++ .../eui-theme-base/src/variables/states.ts | 33 ++ .../src/variables/typography.ts | 146 +++++++ packages/eui-theme-base/tsconfig.json | 27 ++ 42 files changed, 2298 insertions(+) create mode 100644 packages/eui-theme-base/.eslintignore create mode 100644 packages/eui-theme-base/.eslintplugin.js create mode 100644 packages/eui-theme-base/.eslintrc.js create mode 100644 packages/eui-theme-base/.gitignore create mode 100644 packages/eui-theme-base/.prettierrc create mode 100644 packages/eui-theme-base/.stylelintrc.js create mode 100644 packages/eui-theme-base/LICENSE.txt create mode 100644 packages/eui-theme-base/README.md create mode 100644 packages/eui-theme-base/babel.config.js create mode 100644 packages/eui-theme-base/package.json create mode 100644 packages/eui-theme-base/src/index.ts create mode 100644 packages/eui-theme-base/src/types.ts create mode 100644 packages/eui-theme-base/src/utils.test.ts create mode 100644 packages/eui-theme-base/src/utils.ts create mode 100644 packages/eui-theme-base/src/variables/_animations.scss create mode 100644 packages/eui-theme-base/src/variables/_borders.scss create mode 100644 packages/eui-theme-base/src/variables/_buttons.scss create mode 100644 packages/eui-theme-base/src/variables/_colors_vis.scss create mode 100644 packages/eui-theme-base/src/variables/_colors_vis.ts create mode 100644 packages/eui-theme-base/src/variables/_font_weight.scss create mode 100644 packages/eui-theme-base/src/variables/_form.scss create mode 100644 packages/eui-theme-base/src/variables/_index.scss create mode 100644 packages/eui-theme-base/src/variables/_page.scss create mode 100644 packages/eui-theme-base/src/variables/_panel.scss create mode 100644 packages/eui-theme-base/src/variables/_responsive.scss create mode 100644 packages/eui-theme-base/src/variables/_shadows.scss create mode 100644 packages/eui-theme-base/src/variables/_size.scss create mode 100644 packages/eui-theme-base/src/variables/_states.scss create mode 100644 packages/eui-theme-base/src/variables/_tool_tip.scss create mode 100644 packages/eui-theme-base/src/variables/_typography.scss create mode 100644 packages/eui-theme-base/src/variables/_z_index.scss create mode 100644 packages/eui-theme-base/src/variables/animations.ts create mode 100644 packages/eui-theme-base/src/variables/borders.ts create mode 100644 packages/eui-theme-base/src/variables/breakpoint.ts create mode 100644 packages/eui-theme-base/src/variables/colors.ts create mode 100644 packages/eui-theme-base/src/variables/index.ts create mode 100644 packages/eui-theme-base/src/variables/levels.ts create mode 100644 packages/eui-theme-base/src/variables/shadow.ts create mode 100644 packages/eui-theme-base/src/variables/size.ts create mode 100644 packages/eui-theme-base/src/variables/states.ts create mode 100644 packages/eui-theme-base/src/variables/typography.ts create mode 100644 packages/eui-theme-base/tsconfig.json diff --git a/packages/eui-theme-base/.eslintignore b/packages/eui-theme-base/.eslintignore new file mode 100644 index 00000000000..4874b17b0b8 --- /dev/null +++ b/packages/eui-theme-base/.eslintignore @@ -0,0 +1,9 @@ +dist +node_modules +lib +types +**/*.d.ts +package.json +scripts +.eslintrc.js +babel.config.js diff --git a/packages/eui-theme-base/.eslintplugin.js b/packages/eui-theme-base/.eslintplugin.js new file mode 100644 index 00000000000..3a2357171e8 --- /dev/null +++ b/packages/eui-theme-base/.eslintplugin.js @@ -0,0 +1,3 @@ +exports.rules = { + 'require-license-header': require('@elastic/eui-common/scripts/eslint-plugin-local/require_license_header.js'), +}; diff --git a/packages/eui-theme-base/.eslintrc.js b/packages/eui-theme-base/.eslintrc.js new file mode 100644 index 00000000000..e33853c0255 --- /dev/null +++ b/packages/eui-theme-base/.eslintrc.js @@ -0,0 +1,114 @@ +const SSPL_ELASTIC_2_0_LICENSE_HEADER = ` +/* + * 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. + */ +`; + +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: ['./tsconfig.json'], + ecmaFeatures: { + jsx: true, + }, + }, + settings: { + 'import/resolver': { + node: { + extensions: ['.ts', '.tsx', '.js', '.json'], + }, + }, + }, + extends: [ + 'plugin:@typescript-eslint/recommended', + // Prettier options need to come last, in order to override other style rules + 'plugin:prettier/recommended', + ], + plugins: ['local', 'import'], + rules: { + 'block-scoped-var': 'error', + camelcase: 'off', + 'dot-notation': ['error', { allowKeywords: true }], + eqeqeq: ['error', 'always', { null: 'ignore' }], + 'guard-for-in': 'error', + 'new-cap': ['error', { capIsNewExceptions: ['Private'] }], + 'no-caller': 'error', + 'no-const-assign': 'error', + 'no-debugger': 'error', + 'no-empty': ['error', { allowEmptyCatch: true }], + 'no-eval': 'error', + 'no-extend-native': 'error', + 'no-global-assign': 'error', + 'no-loop-func': 'error', + 'no-restricted-globals': ['error', 'context'], + 'no-script-url': 'error', + 'no-sequences': 'error', + 'no-var': 'error', + 'no-with': 'error', + 'prefer-const': 'error', + 'prefer-template': 'error', + strict: ['error', 'never'], + 'valid-typeof': 'error', + + 'local/require-license-header': [ + 'warn', + { + license: SSPL_ELASTIC_2_0_LICENSE_HEADER, + }, + ], + + 'import/no-unresolved': ['error', { amd: true, commonjs: true }], + 'import/namespace': 'error', + 'import/default': 'error', + 'import/export': 'error', + 'import/no-named-as-default': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-duplicates': 'error', + + '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-member-accessibility': 'off', + '@typescript-eslint/indent': 'off', + '@typescript-eslint/ban-tslint-comment': 'error', + '@typescript-eslint/no-empty-interface': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-parameter-properties': 'off', + '@typescript-eslint/no-triple-slash-reference': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { argsIgnorePattern: '^_', ignoreRestSiblings: true }, + ], + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-empty-function': 'off', + // It"s all very well saying that some types are trivially inferrable, + // but being explicit is still clearer. + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-ignore': 'allow-with-description', + 'ts-expect-error': 'allow-with-description', + }, + ], + '@typescript-eslint/consistent-type-exports': [ + 'error', + { fixMixedExportsWithInlineTypeSpecifier: false }, + ], + }, + overrides: [ + { + files: ['*.d.ts'], + rules: { + 'react/prefer-es6-class': 'off', + }, + }, + ], +}; diff --git a/packages/eui-theme-base/.gitignore b/packages/eui-theme-base/.gitignore new file mode 100644 index 00000000000..4450fe8d868 --- /dev/null +++ b/packages/eui-theme-base/.gitignore @@ -0,0 +1,11 @@ +# Dependencies +/node_modules + +# Production +/lib + +yarn-debug.log* +yarn-error.log* + +# Build-related files +.eslintcache \ No newline at end of file diff --git a/packages/eui-theme-base/.prettierrc b/packages/eui-theme-base/.prettierrc new file mode 100644 index 00000000000..b2f0fa8f00e --- /dev/null +++ b/packages/eui-theme-base/.prettierrc @@ -0,0 +1,7 @@ +{ + "parser": "typescript", + "printWidth": 80, + "semi": true, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/packages/eui-theme-base/.stylelintrc.js b/packages/eui-theme-base/.stylelintrc.js new file mode 100644 index 00000000000..42adc41f28c --- /dev/null +++ b/packages/eui-theme-base/.stylelintrc.js @@ -0,0 +1,163 @@ +const camelCaseRegex = '^[a-z][\\w-]*$'; // Note: also allows `_` as part of BEM naming +const camelCaseValueRegex = '/^[a-z][\\w.]*$/'; // Note: also allows `.` for JS objects +const cssInJsVarRegex = '/\\${[a-zA-Z]+/'; + +module.exports = { + // @see https://stylelint.io/user-guide/rules + rules: { + // Enforce camelCase naming + 'selector-class-pattern': camelCaseRegex, + 'keyframes-name-pattern': camelCaseRegex, + 'custom-property-pattern': camelCaseRegex, + + // Opinionated rules + 'declaration-no-important': true, + 'max-nesting-depth': [ + 2, + { + ignore: ['blockless-at-rules', 'pseudo-classes'], + }, + ], + 'block-no-empty': true, + 'selector-no-qualifying-type': [ + true, + { + ignore: ['attribute'], // Allows input[type=search] + }, + ], + + // Non-Prettier newline rules + // Put a line-break between sections of CSS, but allow quick one-liners for legibility + 'rule-empty-line-before': [ + 'always-multi-line', + { + ignore: ['first-nested', 'after-comment'], + }, + ], + 'comment-empty-line-before': null, + 'declaration-empty-line-before': null, + + // Value preferences + 'number-max-precision': null, + // Attempt to catch/flag non-variable color values + 'color-named': 'never', + 'color-no-hex': true, + // Prefer lowercase values, except for font names and currentColor + 'value-keyword-case': [ + 'lower', + { + ignoreProperties: ['font-family', '/^\\$eui[\\w]+/'], // Allow fonts and Sass variables + ignoreKeywords: ['currentColor'], + }, + ], + 'declaration-block-no-duplicate-properties': [ + true, + { + ignore: ['consecutive-duplicates'], // We occasionally use duplicate property values for cross-browser fallbacks + }, + ], + + // TODO: It may be worth investigating and updating these rules to their more modern counterparts + 'color-function-notation': 'legacy', + 'alpha-value-notation': 'number', + + // Disable various opinionated extended stylelint rules that EUI has not previously enforced + 'no-descending-specificity': null, + 'keyframe-selector-notation': null, + 'declaration-block-no-redundant-longhand-properties': null, + }, + overrides: [ + { + // TODO: Remove Sass-specific config & rules once we're completely off Sass + files: ['**/*.scss'], + ignoreFiles: [ + 'generator-eui/**/*.scss', + 'src/global_styling/react_date_picker/**/*.scss', + 'src/themes/amsterdam/global_styling/react_date_picker/**/*.scss', + 'src/components/date_picker/react-datepicker/**/*.scss', + ], + extends: [ + 'stylelint-config-standard-scss', + 'stylelint-config-prettier-scss', + ], + // @see https://github.com/stylelint-scss/stylelint-scss#list-of-rules + rules: { + // Casing + 'scss/dollar-variable-pattern': camelCaseRegex, + 'scss/at-mixin-pattern': camelCaseRegex, + 'scss/at-function-pattern': camelCaseRegex, + 'function-name-case': [ + 'lower', + { + ignoreFunctions: [`/${camelCaseRegex}/`, 'MIN'], + }, + ], + + // Whitespace/newlines + 'scss/at-if-closing-brace-space-after': 'always-intermediate', + 'scss/operator-no-unspaced': true, + + // Formatting rules deprecated as of v15 - keep them in Sass styles just in case until end of migration + // @see https://github.com/stylelint/stylelint/blob/main/docs/user-guide/rules.md#deprecated + 'color-hex-case': 'upper', + 'string-quotes': 'single', + // 2 spaces for indentation + indentation: [2, { indentInsideParens: 'once-at-root-twice-in-block' }], + // Mimic 1tbs `} else {` brace style, like our JS + 'block-opening-brace-space-before': 'always', + 'block-closing-brace-newline-before': 'always-multi-line', + // Ensure multiple selectors on one line each + 'selector-list-comma-newline-before': 'never-multi-line', + 'selector-list-comma-newline-after': 'always', + // Trim unnecessary newlines/whitespace + 'block-closing-brace-empty-line-before': 'never', + 'max-empty-lines': 1, + 'no-eol-whitespace': true, + // Enforce spacing around various syntax symbols (colons, operators, etc.) + 'declaration-colon-space-after': 'always-single-line', + 'declaration-colon-space-before': 'never', + 'function-calc-no-unspaced-operator': true, + 'selector-combinator-space-before': 'always', + 'selector-combinator-space-after': 'always', + // Ensure trailing semicolons are always present on non-oneliners + 'declaration-block-semicolon-newline-after': 'always-multi-line', + + // Disable various opinionated extended stylelint rules that EUI has not previously enforced + 'scss/no-global-function-names': null, + 'scss/dollar-variable-empty-line-before': null, + 'scss/at-rule-conditional-no-parentheses': null, + 'scss/double-slash-comment-empty-line-before': null, + 'scss/at-if-no-null': null, + 'selector-not-notation': null, // Enforce comma notation for CSS-in-JS moving forward + }, + }, + { + files: ['**/*.styles.ts', '**/*.ts', '**/*.tsx'], + extends: ['stylelint-config-standard'], + customSyntax: 'postcss-styled-syntax', + rules: { + // Unfortunately, double slash comments must be replaced with standard CSS /* */ comments + // Otherwise we get a parsing error - see https://github.com/hudochenkov/postcss-styled-syntax#known-issues + 'no-invalid-double-slash-comments': true, + // Empty style keys should be allowed, as Emotion still uses them for generating classNames + 'no-empty-source': null, + // Don't lint casing on interpolated JS vars + 'function-name-case': ['lower', { ignoreFunctions: [cssInJsVarRegex] }], + 'function-no-unknown': [true, { ignoreFunctions: [cssInJsVarRegex] }], + 'value-keyword-case': [ + 'lower', + { + ignoreProperties: ['font-family'], + ignoreKeywords: [camelCaseValueRegex], + }, + ], + // This is set to deprecate after stylelint v16, but in the meanwhile, is helpful + // for finding extraneous semicolons after utils that already output semicolons (e.g. logicalCSS()) + 'no-extra-semicolons': true, + + // Emotion uses the `label` property to generate the output className string + 'property-no-unknown': [true, { ignoreProperties: 'label' }], + }, + }, + ], +}; diff --git a/packages/eui-theme-base/LICENSE.txt b/packages/eui-theme-base/LICENSE.txt new file mode 100644 index 00000000000..74327a8f6f3 --- /dev/null +++ b/packages/eui-theme-base/LICENSE.txt @@ -0,0 +1,6 @@ +Source code in this repository is covered by (i) a dual license under the Server +Side Public License, v 1 and the Elastic License 2.0 or (ii) an Apache License +2.0 compatible license or (iii) solely under the Elastic License 2.0, in each +case, as noted in the applicable header. The default throughout the repository +is a dual license under the Server Side Public License, v 1 and the Elastic +License 2.0, unless the header specifies another license. diff --git a/packages/eui-theme-base/README.md b/packages/eui-theme-base/README.md new file mode 100644 index 00000000000..77f336dbb81 --- /dev/null +++ b/packages/eui-theme-base/README.md @@ -0,0 +1 @@ +# EUI base theme functionality and styling \ No newline at end of file diff --git a/packages/eui-theme-base/babel.config.js b/packages/eui-theme-base/babel.config.js new file mode 100644 index 00000000000..8165fe45577 --- /dev/null +++ b/packages/eui-theme-base/babel.config.js @@ -0,0 +1,6 @@ +module.exports = { + presets: [ + ['@babel/preset-env', { targets: { node: 'current' } }], + '@babel/preset-typescript', + ], +}; diff --git a/packages/eui-theme-base/package.json b/packages/eui-theme-base/package.json new file mode 100644 index 00000000000..b4b3052be63 --- /dev/null +++ b/packages/eui-theme-base/package.json @@ -0,0 +1,55 @@ +{ + "name": "@elastic/eui-theme-base", + "version": "0.0.1", + "description": "EUI theme base", + "license": "SEE LICENSE IN LICENSE.txt", + "scripts": { + "build": "tsc", + "lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-sass", + "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", + "lint-sass": "yarn stylelint \"**/*.scss\" --quiet-deprecation-warnings", + "test": "jest" + }, + "repository": { + "type": "git", + "url": "https://github.com/elastic/eui.git", + "directory": "packages/eui-theme-base" + }, + "private": true, + "dependencies": { + "@elastic/eui-common": "workspace:^" + }, + "devDependencies": { + "@types/jest": "^29.5.12", + "@types/prettier": "2.7.3", + "@typescript-eslint/eslint-plugin": "^5.59.7", + "@typescript-eslint/parser": "^5.59.7", + "eslint": "^8.41.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jest": "^28.5.0", + "eslint-plugin-local": "^1.0.0", + "eslint-plugin-prettier": "^4.2.1", + "jest": "^29.7.0", + "prettier": "^2.8.8", + "stylelint": "^15.7.0", + "stylelint-config-prettier-scss": "^1.0.0", + "stylelint-config-standard": "^33.0.0", + "stylelint-config-standard-scss": "^9.0.0", + "typescript": "^5.6.2" + }, + "main": "lib/index.js", + "exports": { + "./lib/*": "./lib/*", + ".": { + "default": "./lib/index.js" + } + }, + "files": [ + "lib/", + "README.md" + ], + "installConfig": { + "hoistingLimits": "workspaces" + } +} diff --git a/packages/eui-theme-base/src/index.ts b/packages/eui-theme-base/src/index.ts new file mode 100644 index 00000000000..4434190910f --- /dev/null +++ b/packages/eui-theme-base/src/index.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +export * from './types'; +export * from './variables'; +export * from './utils'; diff --git a/packages/eui-theme-base/src/types.ts b/packages/eui-theme-base/src/types.ts new file mode 100644 index 00000000000..ba2d7392666 --- /dev/null +++ b/packages/eui-theme-base/src/types.ts @@ -0,0 +1,105 @@ +/* + * 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 type { CSSObject } from '@emotion/react'; +import type { RecursivePartial, ValueOf } from '@elastic/eui-common'; + +import { _EuiThemeAnimation } from './variables/animations'; +import { _EuiThemeBreakpoints } from './variables/breakpoint'; +import { _EuiThemeBorder } from './variables/borders'; +import { _EuiThemeColors } from './variables/colors'; +import { _EuiThemeBase, _EuiThemeSizes } from './variables/size'; +import { _EuiThemeFont } from './variables/typography'; +import { _EuiThemeFocus } from './variables/states'; +import { _EuiThemeLevels } from './variables/levels'; + +export const COLOR_MODES_STANDARD = { + light: 'LIGHT', + dark: 'DARK', +} as const; +export const COLOR_MODES_INVERSE = 'INVERSE' as const; + +export type EuiThemeColorModeInverse = typeof COLOR_MODES_INVERSE; +export type EuiThemeColorModeStandard = ValueOf; +export type EuiThemeColorMode = + | 'light' + | 'dark' + | EuiThemeColorModeStandard + | 'inverse' + | EuiThemeColorModeInverse; + +export type ColorModeSwitch = + | { + [key in EuiThemeColorModeStandard]: T; + } + | T; + +export type StrictColorModeSwitch = { + [key in EuiThemeColorModeStandard]: T; +}; + +export type EuiThemeShape = { + colors: _EuiThemeColors; + /** - Default value: 16 */ + base: _EuiThemeBase; + /** + * @see {@link https://eui.elastic.co/#/theming/sizing | Reference} for more information + */ + size: _EuiThemeSizes; + font: _EuiThemeFont; + border: _EuiThemeBorder; + focus: _EuiThemeFocus; + animation: _EuiThemeAnimation; + breakpoint: _EuiThemeBreakpoints; + levels: _EuiThemeLevels; +}; + +export type EuiThemeSystem = { + root: EuiThemeShape & T; + model: EuiThemeShape & T; + key: string; +}; + +export type EuiThemeModifications = RecursivePartial; + +export type ComputedThemeShape< + T, + P = string | number | bigint | boolean | null | undefined +> = T extends P | ColorModeSwitch + ? T extends ColorModeSwitch + ? X extends P + ? X + : { + [K in keyof (X & + Exclude< + T, + keyof X | keyof StrictColorModeSwitch + >)]: ComputedThemeShape< + (X & Exclude)[K], + P + >; + } + : T + : { + [K in keyof T]: ComputedThemeShape; + }; + +export type EuiThemeComputed = ComputedThemeShape & { + themeName: string; +}; + +export type EuiThemeNested = { + isGlobalTheme: boolean; + hasDifferentColorFromGlobalTheme: boolean; + bodyColor: string; + colorClassName: string; + setGlobalCSSVariables: Function; + globalCSSVariables?: CSSObject; + setNearestThemeCSSVariables: Function; + themeCSSVariables?: CSSObject; +}; diff --git a/packages/eui-theme-base/src/utils.test.ts b/packages/eui-theme-base/src/utils.test.ts new file mode 100644 index 00000000000..c654e4d3c22 --- /dev/null +++ b/packages/eui-theme-base/src/utils.test.ts @@ -0,0 +1,279 @@ +/* + * 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 { + isInverseColorMode, + getColorMode, + getOn, + setOn, + computed, + Computed, + getComputed, + buildTheme, + mergeDeep, +} from './utils'; + +describe('isInverseColorMode', () => { + it("true only if 'inverse'", () => { + expect(isInverseColorMode('LIGHT')).toBe(false); + expect(isInverseColorMode('DARK')).toBe(false); + expect(isInverseColorMode('custom')).toBe(false); + expect(isInverseColorMode()).toBe(false); + expect(isInverseColorMode('INVERSE')).toBe(true); + }); +}); + +describe('getColorMode', () => { + it("defaults to 'LIGHT'", () => { + expect(getColorMode()).toEqual('LIGHT'); + }); + it('uses `parentMode` as fallback', () => { + expect(getColorMode(undefined, 'DARK')).toEqual('DARK'); + }); + it("understands 'INVERSE'", () => { + expect(getColorMode('INVERSE', 'DARK')).toEqual('LIGHT'); + expect(getColorMode('INVERSE', 'LIGHT')).toEqual('DARK'); + expect(getColorMode('INVERSE')).toEqual('LIGHT'); + }); +}); + +describe('getOn', () => { + const obj = { + parent: { + child: 'childVal', + }, + other: { + thing: { + string: 'stringVal', + nested: ['array'], + number: 0, + func: () => {}, + }, + }, + colors: { + LIGHT: { primary: '#000' }, + DARK: { primary: '#FFF' }, + }, + }; + it('gets values at the given path', () => { + expect(getOn(obj, 'parent')).toEqual({ + child: 'childVal', + }); + expect(getOn(obj, 'parent.child')).toEqual('childVal'); + expect(getOn(obj, 'other.thing.string')).toEqual('stringVal'); + }); + it('gets values of various kinds', () => { + expect(getOn(obj, 'other.thing.nested')).toEqual(['array']); + expect(getOn(obj, 'other.thing.number')).toEqual(0); + expect(getOn(obj, 'other.thing.func')).toBeInstanceOf(Function); + }); + it('can shortcut color modes', () => { + expect(getOn(obj, 'colors.primary', 'LIGHT')).toEqual('#000'); + expect(getOn(obj, 'colors.primary', 'DARK')).toEqual('#FFF'); + }); + it('will not error', () => { + expect(getOn(obj, 'nope')).toBe(undefined); + expect(getOn(obj, 'other.nope')).toBe(undefined); + expect(getOn(obj, 'other.thing.nope')).toBe(undefined); + }); +}); + +describe('setOn', () => { + let obj: {}; + beforeEach(() => { + obj = { + existing: { + nested: { + val: 'value', + }, + }, + }; + }); + it('sets values at the given path', () => { + setOn(obj, 'existing.new', 'value'); + expect(obj).toEqual({ + existing: { nested: { val: 'value' }, new: 'value' }, + }); + setOn(obj, 'existing.nested.new', 'value'); + expect(obj).toEqual({ + existing: { nested: { val: 'value', new: 'value' }, new: 'value' }, + }); + }); + it('deep arbitrary creation', () => { + setOn(obj, 'trail.blazing.happening.now', 'wow'); + expect(obj).toEqual({ + existing: { nested: { val: 'value' } }, + trail: { blazing: { happening: { now: 'wow' } } }, + }); + }); + it('overrides existing path value', () => { + setOn(obj, 'existing.nested', 'diff'); + expect(obj).toEqual({ + existing: { + nested: 'diff', + }, + }); + }); +}); + +describe('computed', () => { + it('should transform to Computed with dependencies array', () => { + const output = computed(([path]) => path, ['path.to']); + expect(output).toBeInstanceOf(Computed); + expect(output.computer).toBeInstanceOf(Function); + expect(output.dependencies).toEqual(['path.to']); + }); + it('should transform to Computed with single dependency', () => { + const output = computed((path) => path, 'path.to'); + expect(output).toBeInstanceOf(Computed); + expect(output.computer).toBeInstanceOf(Function); + expect(output.dependencies).toEqual('path.to'); + }); + it('should transform to Computed without dependencies array', () => { + const output = computed((path) => path); + expect(output).toBeInstanceOf(Computed); + }); +}); + +const theme = buildTheme( + { + colors: { + LIGHT: { + primary: '#000', + secondary: computed(([primary]) => `${primary}000`, ['colors.primary']), + }, + DARK: { + primary: '#FFF', + secondary: computed((theme) => `${theme.colors.primary}FFF`), + }, + }, + sizes: { + small: 8, + }, + }, + 'minimal' +); +describe('getComputed', () => { + it('computes all values and returns only the current color mode', () => { + // @ts-expect-error intentionally not using a full EUI theme definition + expect(getComputed(theme, {}, 'LIGHT')).toEqual({ + colors: { primary: '#000', secondary: '#000000' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + // @ts-expect-error intentionally not using a full EUI theme definition + expect(getComputed(theme, {}, 'DARK')).toEqual({ + colors: { primary: '#FFF', secondary: '#FFFFFF' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + }); + it('respects simple overrides', () => { + expect( + // @ts-expect-error intentionally not using a full EUI theme definition + getComputed(theme, buildTheme({ sizes: { small: 4 } }, ''), 'LIGHT') + ).toEqual({ + colors: { primary: '#000', secondary: '#000000' }, + sizes: { small: 4 }, + themeName: 'minimal', + }); + }); + it('respects overrides in computation', () => { + expect( + getComputed( + // @ts-expect-error intentionally not using a full EUI theme definition + theme, + buildTheme({ colors: { LIGHT: { primary: '#CCC' } } }, ''), + 'LIGHT' + ) + ).toEqual({ + colors: { primary: '#CCC', secondary: '#CCC000' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + }); + it('respects property extensions', () => { + expect( + getComputed( + // @ts-expect-error intentionally not using a full EUI theme definition + theme, + buildTheme({ colors: { LIGHT: { tertiary: '#333' } } }, ''), + 'LIGHT' + ) + ).toEqual({ + colors: { primary: '#000', secondary: '#000000', tertiary: '#333' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + }); + it('respects section extensions', () => { + expect( + getComputed( + // @ts-expect-error intentionally not using a full EUI theme definition + theme, + buildTheme({ custom: { myProp: '#333' } }, ''), + 'LIGHT' + ) + ).toEqual({ + colors: { primary: '#000', secondary: '#000000' }, + sizes: { small: 8 }, + custom: { myProp: '#333' }, + themeName: 'minimal', + }); + }); + it('respects extensions in computation', () => { + expect( + getComputed( + // @ts-expect-error intentionally not using a full EUI theme definition + theme, + buildTheme( + { + colors: { + LIGHT: { + tertiary: computed( + ([primary]) => `${primary}333`, + ['colors.primary'] + ), + }, + }, + }, + '' + ), + 'LIGHT' + ) + ).toEqual({ + colors: { primary: '#000', secondary: '#000000', tertiary: '#000333' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + }); +}); + +describe('buildTheme', () => { + it('builds an EUI theme system', () => { + // TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property 'length' which is either non-existant or configurable in the proxy target + // expect(theme).toEqual(Proxy); // get() trap returns theme.model + // expect(theme.root).toEqual(Proxy); + expect(theme.key).toEqual('minimal'); + }); +}); + +describe('mergeDeep', () => { + it('merge simple objects, second into first', () => { + expect(mergeDeep({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 }); + expect(mergeDeep({ a: 1 }, { a: 2 })).toEqual({ a: 2 }); + }); + it('merge complex objects, second into first', () => { + expect( + mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { d: 4 } } }) + ).toEqual({ a: 1, b: { c: { d: 4 } } }); + expect( + mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { e: 5 } } }) + ).toEqual({ a: 1, b: { c: { d: 3, e: 5 } } }); + }); +}); diff --git a/packages/eui-theme-base/src/utils.ts b/packages/eui-theme-base/src/utils.ts new file mode 100644 index 00000000000..06e288afd7b --- /dev/null +++ b/packages/eui-theme-base/src/utils.ts @@ -0,0 +1,392 @@ +/* + * 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 { + EuiThemeColorMode, + EuiThemeColorModeInverse, + EuiThemeColorModeStandard, + EuiThemeModifications, + EuiThemeSystem, + EuiThemeShape, + EuiThemeComputed, + COLOR_MODES_STANDARD, + COLOR_MODES_INVERSE, +} from './types'; + +export const DEFAULT_COLOR_MODE = COLOR_MODES_STANDARD.light; + +/** + * Returns whether the parameter is an object + * @param {any} obj - Anything + */ +const isObject = (obj: any) => obj && typeof obj === 'object'; + +/** + * Returns whether the provided color mode is `inverse` + * @param {string} colorMode - `light`, `dark`, or `inverse` + */ +export const isInverseColorMode = ( + colorMode?: string +): colorMode is EuiThemeColorModeInverse => { + return colorMode === COLOR_MODES_INVERSE; +}; + +/** + * Returns the color mode configured in the current EuiThemeProvider. + * Returns the parent color mode if none is explicity set. + * @param {string} colorMode - `light`, `dark`, or `inverse` + * @param {string} parentColorMode - `LIGHT` or `DARK`; used as the fallback + */ +export const getColorMode = ( + colorMode?: EuiThemeColorMode, + parentColorMode?: EuiThemeColorModeStandard +): EuiThemeColorModeStandard => { + if (colorMode == null) { + return parentColorMode || DEFAULT_COLOR_MODE; + } + const mode = colorMode.toUpperCase() as + | EuiThemeColorModeInverse + | EuiThemeColorModeStandard; + if (isInverseColorMode(mode)) { + return parentColorMode === COLOR_MODES_STANDARD.dark || + parentColorMode === undefined + ? COLOR_MODES_STANDARD.light + : COLOR_MODES_STANDARD.dark; + } else { + return mode; + } +}; + +/** + * Returns a value at a given path on an object. + * If `colorMode` is provided, will scope the value to the appropriate color mode key (LIGHT\DARK) + * @param {object} model - Object + * @param {string} _path - Dot-notated string to a path on the object + * @param {string} colorMode - `light` or `dark` + */ +export const getOn = ( + model: { [key: string]: any }, + _path: string, + colorMode?: EuiThemeColorModeStandard +) => { + const path = _path.split('.'); + let node = model; + while (path.length) { + const segment = path.shift()!; + + if (node.hasOwnProperty(segment) === false) { + if ( + colorMode && + node.hasOwnProperty(colorMode) === true && + node[colorMode].hasOwnProperty(segment) === true + ) { + if (node[colorMode][segment] instanceof Computed) { + node = node[colorMode][segment].getValue(null, {}, node, colorMode); + } else { + node = node[colorMode][segment]; + } + } else { + return undefined; + } + } else { + if (node[segment] instanceof Computed) { + node = node[segment].getValue(null, {}, node, colorMode); + } else { + node = node[segment]; + } + } + } + + return node; +}; + +/** + * Sets a value at a given path on an object. + * @param {object} model - Object + * @param {string} _path - Dot-notated string to a path on the object + * @param {any} string - The value to set + */ +export const setOn = ( + model: { [key: string]: any }, + _path: string, + value: any +) => { + const path = _path.split('.'); + const propertyName = path.pop()!; + let node = model; + + while (path.length) { + const segment = path.shift()!; + if (node.hasOwnProperty(segment) === false) { + node[segment] = {}; + } + node = node[segment]; + } + + node[propertyName] = value; + return true; +}; + +/** + * Creates a class to store the `computer` method and its eventual parameters. + * Allows for on-demand computation with up-to-date parameters via `getValue` method. + * @constructor + * @param {function} computer - Function to be computed + * @param {string | array} dependencies - Dependencies passed to the `computer` as parameters + */ +export class Computed { + constructor( + public computer: (...values: any[]) => T, + public dependencies: string | string[] = [] + ) {} + + /** + * Executes the `computer` method with the current state of the theme + * by taking into account previously computed values and modifications. + * @param {Proxy | object} base - Computed or uncomputed theme + * @param {Proxy | object} modifications - Theme value overrides + * @param {object} working - Partially computed theme + * @param {string} colorMode - `light` or `dark` + */ + getValue( + base: EuiThemeSystem | EuiThemeShape | null, + modifications: EuiThemeModifications = {}, + working: Partial, + colorMode?: EuiThemeColorModeStandard + ) { + if (!this.dependencies.length) { + return this.computer(working); + } + if (!Array.isArray(this.dependencies)) { + return this.computer( + getOn(working, this.dependencies) ?? + getOn(modifications, this.dependencies, colorMode) ?? + (base ? getOn(base, this.dependencies, colorMode) : working) + ); + } + return this.computer( + this.dependencies.map((dependency) => { + return ( + getOn(working, dependency) ?? + getOn(modifications, dependency, colorMode) ?? + (base ? getOn(base, dependency, colorMode) : working) + ); + }) + ); + } +} + +/** + * Returns a Class (`Computed`) that stores the arbitrary computer method + * and references to its optional dependecies. + * @param {function} computer - Arbitrary method to be called at compute time. + * @param {string | array} dependencies - Values that will be provided to `computer` at compute time. + */ +export function computed(computer: (value: EuiThemeComputed) => T): T; +export function computed( + computer: (value: any[]) => T, + dependencies: string[] +): T; +export function computed( + computer: (value: any) => T, + dependencies: string +): T; +export function computed( + comp: ((value: T) => T) | ((value: any) => T) | ((value: any[]) => T), + dep?: string | string[] +) { + return new Computed(comp, dep); +} + +/** + * Type guard to check for a Computed object based on object shape + * without relying on the Computed class directly + */ +const isComputedLike = (key: object): key is Computed => { + if (typeof key !== 'object' || Array.isArray(key)) return false; + + return key.hasOwnProperty('dependencies') && key.hasOwnProperty('computer'); +}; + +/** + * Takes an uncomputed theme, and computes and returns all values taking + * into consideration value overrides and configured color mode. + * Overrides take precedence, and only values in the current color mode + * are computed and returned. + * @param {Proxy} base - Object to transform into Proxy + * @param {Proxy | object} over - Unique identifier or name + * @param {string} colorMode - `light` or `dark` + */ +export const getComputed = ( + base: EuiThemeSystem, + over: Partial>, + colorMode: EuiThemeColorModeStandard +): EuiThemeComputed => { + const output: Partial = { themeName: base.key }; + + function loop( + base: { [key: string]: any }, + over: { [key: string]: any }, + checkExisting: boolean = false, + path?: string + ) { + Object.keys(base).forEach((key) => { + let newPath = path ? `${path}.${key}` : `${key}`; + // @ts-expect-error `key` is not necessarily a colorMode key + if ([...Object.values(COLOR_MODES_STANDARD), colorMode].includes(key)) { + if (key !== colorMode) { + return; + } else { + const colorModeSegment = new RegExp( + `(\\.${colorMode}\\b)|(\\b${colorMode}\\.)` + ); + newPath = newPath.replace(colorModeSegment, ''); + } + } + const existing = checkExisting && getOn(output, newPath); + if (!existing || isObject(existing)) { + // NOTE: the class type check for Computed is not true for themes created externally; + // we additionally check on the object shape to confirm a Computed value + const baseValue = + base[key] instanceof Computed || isComputedLike(base[key]) + ? base[key].getValue(base.root, over.root, output, colorMode) + : base[key]; + const overValue = + over[key] instanceof Computed || isComputedLike(over[key]) + ? over[key].getValue(base.root, over.root, output, colorMode) + : over[key]; + if (isObject(baseValue) && !Array.isArray(baseValue)) { + loop(baseValue, overValue ?? {}, checkExisting, newPath); + } else { + setOn(output, newPath, overValue ?? baseValue); + } + } + }); + } + // Compute standard theme values and apply overrides + loop(base, over); + // Compute and apply extension values only + loop(over, {}, true); + return output as EuiThemeComputed; +}; + +/** + * Builds a Proxy with a custom `handler` designed to self-reference values + * and prevent arbitrary value overrides. + * @param {object} model - Object to transform into Proxy + * @param {string} key - Unique identifier or name + */ +export const buildTheme = (model: T, key: string) => { + const handler: ProxyHandler> = { + getPrototypeOf(target) { + return Reflect.getPrototypeOf(target.model); + }, + + setPrototypeOf(target, prototype) { + return Reflect.setPrototypeOf(target.model, prototype); + }, + + isExtensible(target) { + return Reflect.isExtensible(target); + }, + + preventExtensions(target) { + return Reflect.preventExtensions(target.model); + }, + + getOwnPropertyDescriptor(target, key) { + return Reflect.getOwnPropertyDescriptor(target.model, key); + }, + + defineProperty(target, property, attributes) { + return Reflect.defineProperty(target.model, property, attributes); + }, + + has(target, property) { + return Reflect.has(target.model, property); + }, + + get(_target, property) { + if (property === 'key') { + return _target[property]; + } + + // prevent Safari from locking up when the proxy is used in dev tools + // as it doesn't support getPrototypeOf + if (property === '__proto__') return {}; + + const target = property === 'root' ? _target : _target.model || _target; + // @ts-ignore `string` index signature + const value = target[property]; + if (isObject(value) && !Array.isArray(value)) { + return new Proxy( + { + model: value, + root: _target.root, + key: `_${_target.key}`, + }, + handler + ); + } else { + return value; + } + }, + + set(target: any) { + return target; + }, + + deleteProperty(target: any) { + return target; + }, + + ownKeys(target) { + return Reflect.ownKeys(target.model); + }, + + apply(target: any) { + return target; + }, + + construct(target: any) { + return target; + }, + }; + const themeProxy = new Proxy({ model, root: model, key }, handler); + + return themeProxy; +}; + +/** + * Deeply merges two objects, using `source` values whenever possible. + * @param {object} _target - Object with fallback values + * @param {object} source - Object with desired values + */ +export const mergeDeep = ( + _target: { [key: string]: any }, + source: { [key: string]: any } = {} +) => { + const target = { ..._target }; + + if (!isObject(target) || !isObject(source)) { + return source; + } + + Object.keys(source).forEach((key) => { + const targetValue = target[key]; + const sourceValue = source[key]; + + if (isObject(targetValue) && isObject(sourceValue)) { + target[key] = mergeDeep({ ...targetValue }, { ...sourceValue }); + } else { + target[key] = sourceValue; + } + }); + + return target; +}; diff --git a/packages/eui-theme-base/src/variables/_animations.scss b/packages/eui-theme-base/src/variables/_animations.scss new file mode 100644 index 00000000000..93b9daf1641 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_animations.scss @@ -0,0 +1,13 @@ +// Animations + +$euiAnimSlightBounce: cubic-bezier(.34, 1.61, .7, 1) !default; +$euiAnimSlightResistance: cubic-bezier(.694, .0482, .335, 1) !default; + +$euiAnimSpeedExtraFast: 90ms !default; +$euiAnimSpeedFast: 150ms !default; +$euiAnimSpeedNormal: 250ms !default; +$euiAnimSpeedSlow: 350ms !default; +$euiAnimSpeedExtraSlow: 500ms !default; + +// Keyframe animation declarations can be found in +// eui/utility/animations.scss diff --git a/packages/eui-theme-base/src/variables/_borders.scss b/packages/eui-theme-base/src/variables/_borders.scss new file mode 100644 index 00000000000..6fa0216ff3b --- /dev/null +++ b/packages/eui-theme-base/src/variables/_borders.scss @@ -0,0 +1,11 @@ +// Borders + +$euiBorderWidthThin: 1px !default; +$euiBorderWidthThick: 2px !default; + +$euiBorderColor: $euiColorLightShade !default; +$euiBorderRadius: $euiSizeS * .75 !default; +$euiBorderRadiusSmall: $euiSizeS * .5 !default; +$euiBorderThick: $euiBorderWidthThick solid $euiBorderColor !default; +$euiBorderThin: $euiBorderWidthThin solid $euiBorderColor !default; +$euiBorderEditable: $euiBorderWidthThick dotted $euiBorderColor !default; diff --git a/packages/eui-theme-base/src/variables/_buttons.scss b/packages/eui-theme-base/src/variables/_buttons.scss new file mode 100644 index 00000000000..97304c0f5c0 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_buttons.scss @@ -0,0 +1,19 @@ +$euiButtonHeight: $euiSizeXXL !default; +$euiButtonHeightSmall: $euiSizeXL !default; +$euiButtonHeightXSmall: $euiSizeL !default; + +$euiButtonColorDisabled: tintOrShade($euiTextColor, 70%, 70%) !default; +// Only increase the contrast of background color to text to 2.0 for disabled +$euiButtonColorDisabledText: makeDisabledContrastColor($euiButtonColorDisabled) !default; +$euiButtonColorGhostDisabled: lightOrDarkTheme($euiColorDarkShade, $euiColorLightShade) !default; + +// Modifier naming and colors. +$euiButtonTypes: ( + primary: $euiColorPrimary, + accent: $euiColorAccent, + success: $euiColorSuccess, + warning: $euiColorWarning, + danger: $euiColorDanger, + ghost: $euiColorGhost, // Ghost is special, and does not care about theming. + text: $euiColorDarkShade, // Reserved for special use cases +) !default; diff --git a/packages/eui-theme-base/src/variables/_colors_vis.scss b/packages/eui-theme-base/src/variables/_colors_vis.scss new file mode 100644 index 00000000000..cfffdf5e55d --- /dev/null +++ b/packages/eui-theme-base/src/variables/_colors_vis.scss @@ -0,0 +1,72 @@ +// Visualization colors +// stylelint-disable color-no-hex + +// Maps allow for easier JSON usage +// Use map_merge($euiColorVisColors, $yourMap) to change individual colors after importing ths file +// The `behindText` variant is a direct copy of the hex output by the JS euiPaletteColorBlindBehindText() function +$euiPaletteColorBlind: ( + euiColorVis0: ( + graphic: #54B399, + behindText: #6DCCB1, + ), + euiColorVis1: ( + graphic: #6092C0, + behindText: #79AAD9, + ), + euiColorVis2: ( + graphic: #D36086, + behindText: #EE789D, + ), + euiColorVis3: ( + graphic: #9170B8, + behindText: #A987D1, + ), + euiColorVis4: ( + graphic: #CA8EAE, + behindText: #E4A6C7, + ), + euiColorVis5: ( + graphic: #D6BF57, + behindText: #F1D86F, + ), + euiColorVis6: ( + graphic: #B9A888, + behindText: #D2C0A0, + ), + euiColorVis7: ( + graphic: #DA8B45, + behindText: #F5A35C, + ), + euiColorVis8: ( + graphic: #AA6556, + behindText: #C47C6C, + ), + euiColorVis9: ( + graphic: #E7664C, + behindText: #FF7E62, + ) +) !default; + +$euiPaletteColorBlindKeys: map-keys($euiPaletteColorBlind); + +$euiColorVis0: map-get(map-get($euiPaletteColorBlind, 'euiColorVis0'), 'graphic') !default; +$euiColorVis1: map-get(map-get($euiPaletteColorBlind, 'euiColorVis1'), 'graphic') !default; +$euiColorVis2: map-get(map-get($euiPaletteColorBlind, 'euiColorVis2'), 'graphic') !default; +$euiColorVis3: map-get(map-get($euiPaletteColorBlind, 'euiColorVis3'), 'graphic') !default; +$euiColorVis4: map-get(map-get($euiPaletteColorBlind, 'euiColorVis4'), 'graphic') !default; +$euiColorVis5: map-get(map-get($euiPaletteColorBlind, 'euiColorVis5'), 'graphic') !default; +$euiColorVis6: map-get(map-get($euiPaletteColorBlind, 'euiColorVis6'), 'graphic') !default; +$euiColorVis7: map-get(map-get($euiPaletteColorBlind, 'euiColorVis7'), 'graphic') !default; +$euiColorVis8: map-get(map-get($euiPaletteColorBlind, 'euiColorVis8'), 'graphic') !default; +$euiColorVis9: map-get(map-get($euiPaletteColorBlind, 'euiColorVis9'), 'graphic') !default; + +$euiColorVis0_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis0'), 'behindText') !default; +$euiColorVis1_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis1'), 'behindText') !default; +$euiColorVis2_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis2'), 'behindText') !default; +$euiColorVis3_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis3'), 'behindText') !default; +$euiColorVis4_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis4'), 'behindText') !default; +$euiColorVis5_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis5'), 'behindText') !default; +$euiColorVis6_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis6'), 'behindText') !default; +$euiColorVis7_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis7'), 'behindText') !default; +$euiColorVis8_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis8'), 'behindText') !default; +$euiColorVis9_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis9'), 'behindText') !default; diff --git a/packages/eui-theme-base/src/variables/_colors_vis.ts b/packages/eui-theme-base/src/variables/_colors_vis.ts new file mode 100644 index 00000000000..4459b04ff8c --- /dev/null +++ b/packages/eui-theme-base/src/variables/_colors_vis.ts @@ -0,0 +1,62 @@ +/* + * 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. + */ + +/** + * NOTE: These were quick conversions of their Sass counterparts. + * They have yet to be used/tested. + * TODO: Make the graphic version available from `euiPaletteColorBlind()` + */ + +// Maps allow for easier JSON usage +// Use map_merge(euiColorVisColors, $yourMap) to change individual colors after importing ths file +// The `behindText` variant is a direct copy of the hex output by the JS euiPaletteColorBlindBehindText() function +const euiPaletteColorBlind = { + euiColorVis0: { + graphic: '#54B399', + }, + euiColorVis1: { + graphic: '#6092C0', + }, + euiColorVis2: { + graphic: '#D36086', + }, + euiColorVis3: { + graphic: '#9170B8', + }, + euiColorVis4: { + graphic: '#CA8EAE', + }, + euiColorVis5: { + graphic: '#D6BF57', + }, + euiColorVis6: { + graphic: '#B9A888', + }, + euiColorVis7: { + graphic: '#DA8B45', + }, + euiColorVis8: { + graphic: '#AA6556', + }, + euiColorVis9: { + graphic: '#E7664C', + }, +}; + +export const colorVis = { + euiColorVis0: euiPaletteColorBlind.euiColorVis0.graphic, + euiColorVis1: euiPaletteColorBlind.euiColorVis1.graphic, + euiColorVis2: euiPaletteColorBlind.euiColorVis2.graphic, + euiColorVis3: euiPaletteColorBlind.euiColorVis3.graphic, + euiColorVis4: euiPaletteColorBlind.euiColorVis4.graphic, + euiColorVis5: euiPaletteColorBlind.euiColorVis5.graphic, + euiColorVis6: euiPaletteColorBlind.euiColorVis6.graphic, + euiColorVis7: euiPaletteColorBlind.euiColorVis7.graphic, + euiColorVis8: euiPaletteColorBlind.euiColorVis8.graphic, + euiColorVis9: euiPaletteColorBlind.euiColorVis9.graphic, +}; diff --git a/packages/eui-theme-base/src/variables/_font_weight.scss b/packages/eui-theme-base/src/variables/_font_weight.scss new file mode 100644 index 00000000000..f5dfd287835 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_font_weight.scss @@ -0,0 +1,10 @@ +// Separated out to its own file for easy import into docs + +// Font weights +$euiFontWeightLight: 300 !default; +$euiFontWeightRegular: 400 !default; +$euiFontWeightMedium: 500 !default; +$euiFontWeightSemiBold: 600 !default; +$euiFontWeightBold: 700 !default; +$euiCodeFontWeightRegular: 400 !default; +$euiCodeFontWeightBold: 700 !default; diff --git a/packages/eui-theme-base/src/variables/_form.scss b/packages/eui-theme-base/src/variables/_form.scss new file mode 100644 index 00000000000..162cf7bdd89 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_form.scss @@ -0,0 +1,59 @@ +// Sizing +$euiFormMaxWidth: $euiSizeXXL * 10 !default; +$euiFormControlHeight: $euiSizeXXL !default; +$euiFormControlCompressedHeight: $euiSizeXL !default; +$euiFormControlPadding: $euiSizeM !default; +$euiFormControlCompressedPadding: $euiSizeS !default; +$euiFormControlBorderRadius: $euiBorderRadius !default; +$euiFormControlCompressedBorderRadius: $euiBorderRadiusSmall !default; + +// Coloring +$euiFormBackgroundColor: tintOrShade($euiColorLightestShade, 60%, 40%) !default; +$euiFormBackgroundDisabledColor: darken($euiColorLightestShade, 2%) !default; +$euiFormBackgroundReadOnlyColor: $euiColorEmptyShade !default; +$euiFormBorderOpaqueColor: shadeOrTint(desaturate(adjust-hue($euiColorPrimary, 22), 22.95), 26%, 100%) !default; +$euiFormBorderColor: transparentize($euiFormBorderOpaqueColor, .9) !default; +$euiFormBorderDisabledColor: transparentize($euiFormBorderOpaqueColor, .9) !default; +$euiFormControlDisabledColor: $euiColorMediumShade !default; +$euiFormControlBoxShadow: 0 0 transparent !default; +$euiFormControlPlaceholderText: makeHighContrastColor($euiTextSubduedColor, $euiFormBackgroundColor) !default; +$euiFormInputGroupLabelBackground: tintOrShade($euiColorLightShade, 50%, 15%) !default; +$euiFormInputGroupBorder: none !default; + +// Icons sizes +$euiFormControlIconSizes: ( + small: $euiSizeM, + medium: $euiSize, + large: $euiSizeL, + xLarge: $euiSizeXL, + xxLarge: $euiSizeXXL +); + +// Control Layout +$euiFormControlLayoutGroupInputHeight: $euiFormControlHeight - 2px !default; +$euiFormControlLayoutGroupInputCompressedHeight: $euiFormControlCompressedHeight - 2px !default; +$euiFormControlLayoutGroupInputCompressedBorderRadius: $euiFormControlCompressedBorderRadius / 2 !default; + +// Range +$euiRangeTrackColor: $euiColorLightShade !default; +$euiRangeHighlightColor: $euiColorDarkShade !default; + +$euiRangeThumbHeight: $euiSize !default; +$euiRangeThumbWidth: $euiSize !default; +$euiRangeThumbBorderColor: $euiColorEmptyShade !default; +$euiRangeThumbBackgroundColor: $euiRangeHighlightColor; + +$euiRangeTrackWidth: 100% !default; +$euiRangeTrackHeight: $euiSizeM / 2 !default; +$euiRangeTrackCompressedHeight: $euiSizeXS; +$euiRangeTrackBorderWidth: 0 !default; +$euiRangeTrackBorderColor: $euiRangeTrackColor !default; +$euiRangeTrackRadius: $euiBorderRadius !default; + +$euiRangeDisabledOpacity: .25 !default; + +$euiRangeHighlightHeight: $euiRangeTrackHeight !default; +$euiRangeHighlightCompressedHeight: $euiRangeTrackCompressedHeight !default; + +$euiRangeHeight: $euiFormControlHeight !default; +$euiRangeCompressedHeight: $euiFormControlCompressedHeight !default; diff --git a/packages/eui-theme-base/src/variables/_index.scss b/packages/eui-theme-base/src/variables/_index.scss new file mode 100644 index 00000000000..6971a19d892 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_index.scss @@ -0,0 +1,26 @@ +// -------------------------------------------------------------------------------------- +// EUI global variables +// -------------------------------------------------------------------------------------- +// This module contains all global variables available within EUI. Every variable in this +// document should be prefixed with $eui. This lets us know where the variable is +// coming from when looking inside the individual component files. Any component local +// variables should be declared at the top of those documents prefixed with $componentName. + +// Global colors are established and importer per theme, before this manifest +// Import order is important. Size, vis colors, ...etc are used in other variables. +@import 'size'; +@import 'colors_vis'; +@import 'animations'; +@import 'font_weight'; +@import 'typography'; +@import 'borders'; +@import 'responsive'; +@import 'shadows'; +@import 'states'; +@import 'z_index'; + +@import 'buttons'; +@import 'form'; +@import 'page'; +@import 'panel'; +@import 'tool_tip'; diff --git a/packages/eui-theme-base/src/variables/_page.scss b/packages/eui-theme-base/src/variables/_page.scss new file mode 100644 index 00000000000..df423080152 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_page.scss @@ -0,0 +1,2 @@ +$euiPageDefaultMaxWidth: 1000px !default; +$euiPageSidebarMinWidth: $euiSizeL * 8 !default; diff --git a/packages/eui-theme-base/src/variables/_panel.scss b/packages/eui-theme-base/src/variables/_panel.scss new file mode 100644 index 00000000000..0a2bb6a46f5 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_panel.scss @@ -0,0 +1,21 @@ +$euiPanelPaddingModifiers: ( + 'paddingSmall': $euiSizeS, + 'paddingMedium': $euiSize, + 'paddingLarge': $euiSizeL +) !default; + +$euiPanelBorderRadiusModifiers: ( + 'borderRadiusNone': 0, + 'borderRadiusMedium': $euiBorderRadius, +) !default; + +$euiPanelBackgroundColorModifiers: ( + 'transparent': transparent, + 'plain': $euiColorEmptyShade, + 'subdued': $euiPageBackgroundColor, + 'accent': tintOrShade($euiColorAccent, 90%, 70%), + 'primary': tintOrShade($euiColorPrimary, 90%, 70%), + 'success': tintOrShade($euiColorSuccess, 90%, 70%), + 'warning': tintOrShade($euiColorWarning, 90%, 70%), + 'danger': tintOrShade($euiColorDanger, 90%, 70%), +) !default; diff --git a/packages/eui-theme-base/src/variables/_responsive.scss b/packages/eui-theme-base/src/variables/_responsive.scss new file mode 100644 index 00000000000..de6e8ca5b83 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_responsive.scss @@ -0,0 +1,9 @@ +$euiBreakpoints: ( + 'xs': 0, + 's': 575px, + 'm': 768px, + 'l': 992px, + 'xl': 1200px +) !default; + +$euiBreakpointKeys: map-keys($euiBreakpoints); diff --git a/packages/eui-theme-base/src/variables/_shadows.scss b/packages/eui-theme-base/src/variables/_shadows.scss new file mode 100644 index 00000000000..05e445f27a1 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_shadows.scss @@ -0,0 +1,2 @@ +// Shadows +$euiShadowColor: $euiColorInk !default; diff --git a/packages/eui-theme-base/src/variables/_size.scss b/packages/eui-theme-base/src/variables/_size.scss new file mode 100644 index 00000000000..f07645832d1 --- /dev/null +++ b/packages/eui-theme-base/src/variables/_size.scss @@ -0,0 +1,15 @@ +$euiSize: 16px !default; + +$euiSizeXS: $euiSize * .25 !default; +$euiSizeS: $euiSize * .5 !default; +$euiSizeM: $euiSize * .75 !default; +$euiSizeL: $euiSize * 1.5 !default; +$euiSizeXL: $euiSize * 2 !default; +$euiSizeXXL: $euiSize * 2.5 !default; + +$euiButtonMinWidth: $euiSize * 7 !default; + +$euiScrollBar: $euiSize !default; +// Corner sizes are used as an inset border and therefore a smaller corner size means a larger thumb +$euiScrollBarCorner: $euiSizeXS !default; +$euiScrollBarCornerThin: $euiSizeS * .75 !default; diff --git a/packages/eui-theme-base/src/variables/_states.scss b/packages/eui-theme-base/src/variables/_states.scss new file mode 100644 index 00000000000..fba4cc59caa --- /dev/null +++ b/packages/eui-theme-base/src/variables/_states.scss @@ -0,0 +1,14 @@ +// Colors +$euiFocusRingColor: rgba($euiColorPrimary, .3) !default; +$euiFocusRingAnimStartColor: rgba($euiColorPrimary, 0) !default; +$euiFocusRingAnimStartSize: 6px !default; +$euiFocusRingAnimStartSizeLarge: 10px !default; + +// Sizing +$euiFocusRingSizeLarge: $euiSizeXS !default; +$euiFocusRingSize: $euiFocusRingSizeLarge * .75 !default; + +// Transparency +$euiFocusTransparency: lightOrDarkTheme(.1, .2) !default; +$euiFocusTransparencyPercent: lightOrDarkTheme(90%, 80%) !default; +$euiFocusBackgroundColor: tintOrShade($euiColorPrimary, $euiFocusTransparencyPercent, $euiFocusTransparencyPercent) !default; diff --git a/packages/eui-theme-base/src/variables/_tool_tip.scss b/packages/eui-theme-base/src/variables/_tool_tip.scss new file mode 100644 index 00000000000..6bf4e1e4d9c --- /dev/null +++ b/packages/eui-theme-base/src/variables/_tool_tip.scss @@ -0,0 +1,9 @@ +$euiTooltipBackgroundColor: tintOrShade($euiColorFullShade, 25%, 100%) !default; +$euiTooltipBorderColor: tintOrShade($euiColorFullShade, 35%, 80%) !default; + +$euiTooltipAnimations: ( + top: euiToolTipTop, + left: euiToolTipBottom, + bottom: euiToolTipLeft, + right: euiToolTipRight, +) !default; diff --git a/packages/eui-theme-base/src/variables/_typography.scss b/packages/eui-theme-base/src/variables/_typography.scss new file mode 100644 index 00000000000..1ca62f3248c --- /dev/null +++ b/packages/eui-theme-base/src/variables/_typography.scss @@ -0,0 +1,75 @@ +// Families +$euiFontFamily: 'Inter', BlinkMacSystemFont, Helvetica, Arial, sans-serif !default; +$euiCodeFontFamily: 'Roboto Mono', Menlo, Courier, monospace !default; + +// Careful using ligatures. Code editors like ACE will often error because of width calculations +$euiFontFeatureSettings: 'calt' 1, 'kern' 1, 'liga' 1 !default; + +// Font sizes -- scale is loosely based on Major Third (1.250) +$euiTextScale: 2.25, 1.75, 1.25, 1.125, 1, .875, .75 !default; + +$euiFontSize: $euiSize !default; // 5th position in scale +$euiFontSizeXS: $euiFontSize * nth($euiTextScale, 7) !default; // 12px +$euiFontSizeS: $euiFontSize * nth($euiTextScale, 6) !default; // 14px +$euiFontSizeM: $euiFontSize * nth($euiTextScale, 4) !default; // 18px +$euiFontSizeL: $euiFontSize * nth($euiTextScale, 3) !default; // 20px +$euiFontSizeXL: $euiFontSize * nth($euiTextScale, 2) !default; // 28px +$euiFontSizeXXL: $euiFontSize * nth($euiTextScale, 1) !default; // 36px + +// Line height +$euiLineHeight: 1.5 !default; +$euiBodyLineHeight: 1 !default; + +// Normally functions are imported before variables in `_index.scss` files +// But because they need to consume some typography variables they need to live here +@function convertToRem($size) { + @return #{$size / $euiFontSize}rem; +} + +// Our base gridline is at 1/2 the font-size, ensure line-heights stay on that gridline. +// EX: A proper line-height for text is 1.5 times the font-size. +// If our base font size (euiFontSize) is 16, our baseline is 8 (16*1.5 / 3). To ensure the +// text stays on the baseline, we pass a multiplier to calculate a line-height in rems. +@function lineHeightFromBaseline($multiplier: 3) { + @return convertToRem(($euiFontSize / 2) * $multiplier); +} + +// Titles map +// Lists all the properties per EuiTitle size that then gets looped through to create the selectors. +// The map allows for tokenization and easier customization per theme, otherwise you'd have to override the selectors themselves +$euiTitles: ( + 'xxxs': ( + 'font-size': $euiFontSizeXS, + 'line-height': lineHeightFromBaseline(3), + 'font-weight': $euiFontWeightBold, + ), + 'xxs': ( + 'font-size': $euiFontSizeS, + 'line-height': lineHeightFromBaseline(3), + 'font-weight': $euiFontWeightBold, + ), + 'xs': ( + 'font-size': $euiFontSize, + 'line-height': lineHeightFromBaseline(3), + 'font-weight': $euiFontWeightSemiBold, + 'letter-spacing': -.02em, + ), + 's': ( + 'font-size': $euiFontSizeL, + 'line-height': lineHeightFromBaseline(4), + 'font-weight': $euiFontWeightMedium, + 'letter-spacing': -.025em, + ), + 'm': ( + 'font-size': $euiFontSizeXL, + 'line-height': lineHeightFromBaseline(5), + 'font-weight': $euiFontWeightLight, + 'letter-spacing': -.04em, + ), + 'l': ( + 'font-size': $euiFontSizeXXL, + 'line-height': lineHeightFromBaseline(6), + 'font-weight': $euiFontWeightLight, + 'letter-spacing': -.03em, + ), +) !default; diff --git a/packages/eui-theme-base/src/variables/_z_index.scss b/packages/eui-theme-base/src/variables/_z_index.scss new file mode 100644 index 00000000000..2448a34c61a --- /dev/null +++ b/packages/eui-theme-base/src/variables/_z_index.scss @@ -0,0 +1,34 @@ +// Z-Index + +// Remember that z-index is relative to parent and based on the stacking context. +// z-indexes only compete against other z-indexes when they exist as children of +// that shared parent. + +// That means a popover with a settings of 2, will still show above a modal +// with a setting of 100, if it is within that modal and not besides it. + +// Generally that means it's a good idea to consider things added to this file +// as competitive only as siblings. + +// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context + +$euiZLevel0: 0; +$euiZLevel1: 1000; +$euiZLevel2: 2000; +$euiZLevel3: 3000; +$euiZLevel4: 4000; +$euiZLevel5: 5000; +$euiZLevel6: 6000; +$euiZLevel7: 7000; +$euiZLevel8: 8000; +$euiZLevel9: 9000; + +$euiZToastList: $euiZLevel9; +$euiZModal: $euiZLevel8; +$euiZMask: $euiZLevel6; +$euiZNavigation: $euiZLevel6; +$euiZContentMenu: $euiZLevel2; +$euiZHeader: $euiZLevel1; +$euiZFlyout: $euiZHeader; +$euiZMaskBelowHeader: $euiZHeader; +$euiZContent: $euiZLevel0; diff --git a/packages/eui-theme-base/src/variables/animations.ts b/packages/eui-theme-base/src/variables/animations.ts new file mode 100644 index 00000000000..46bce009c92 --- /dev/null +++ b/packages/eui-theme-base/src/variables/animations.ts @@ -0,0 +1,66 @@ +/* + * 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 { CSSProperties } from 'react'; + +/** + * A constant storing the `prefers-reduced-motion` media query + * so that when it is turned off, animations are not run. + */ +export const euiCanAnimate = + '@media screen and (prefers-reduced-motion: no-preference)'; + +/** + * A constant storing the `prefers-reduced-motion` media query that will + * only apply the content if the setting is off (reduce). + */ +export const euiCantAnimate = + '@media screen and (prefers-reduced-motion: reduce)'; + +/** + * Speeds / Durations / Delays + */ + +export const EuiThemeAnimationSpeeds = [ + 'extraFast', + 'fast', + 'normal', + 'slow', + 'extraSlow', +] as const; + +export type _EuiThemeAnimationSpeed = (typeof EuiThemeAnimationSpeeds)[number]; + +export type _EuiThemeAnimationSpeeds = { + /** - Default value: 90ms */ + extraFast: CSSProperties['animationDuration']; + /** - Default value: 150ms */ + fast: CSSProperties['animationDuration']; + /** - Default value: 250ms */ + normal: CSSProperties['animationDuration']; + /** - Default value: 350ms */ + slow: CSSProperties['animationDuration']; + /** - Default value: 500ms */ + extraSlow: CSSProperties['animationDuration']; +}; + +/** + * Easings / Timing functions + */ + +export const EuiThemeAnimationEasings = ['bounce', 'resistance'] as const; + +export type _EuiThemeAnimationEasing = + (typeof EuiThemeAnimationEasings)[number]; + +export type _EuiThemeAnimationEasings = Record< + _EuiThemeAnimationEasing, + CSSProperties['animationTimingFunction'] +>; + +export type _EuiThemeAnimation = _EuiThemeAnimationEasings & + _EuiThemeAnimationSpeeds; diff --git a/packages/eui-theme-base/src/variables/borders.ts b/packages/eui-theme-base/src/variables/borders.ts new file mode 100644 index 00000000000..3673010aba2 --- /dev/null +++ b/packages/eui-theme-base/src/variables/borders.ts @@ -0,0 +1,74 @@ +/* + * 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 { CSSProperties } from 'react'; +import { ColorModeSwitch } from '../types'; + +export interface _EuiThemeBorderWidthValues { + /** + * Thinnest width for border + * - Default value: 1px + */ + thin: CSSProperties['borderWidth']; + /** + * Thickest width for border + * - Default value: 2px + */ + thick: CSSProperties['borderWidth']; +} + +export interface _EuiThemeBorderRadiusValues { + /** + * Primary corner radius size + * - Default value: 6px + */ + medium: CSSProperties['borderRadius']; + /** + * Small corner radius size + * - Default value: 4px + */ + small: CSSProperties['borderRadius']; +} + +export interface _EuiThemeBorderColorValues { + /** + * Color for all borders; Default is `colors.lightShade` + */ + color: ColorModeSwitch; +} + +export interface _EuiThemeBorderValues extends _EuiThemeBorderColorValues { + /** + * Varied thicknesses for borders + */ + width: _EuiThemeBorderWidthValues; + /** + * Varied border radii + */ + radius: _EuiThemeBorderRadiusValues; +} + +export interface _EuiThemeBorderTypes { + /** + * Full `border` property string computed using `border.width.thin` and `border.color` + * - Default value: 1px solid [colors.lightShade] + */ + thin: CSSProperties['border']; + /** + * Full `border` property string computed using `border.width.thick` and `border.color` + * - Default value: 2px solid [colors.lightShade] + */ + thick: CSSProperties['border']; + /** + * Full editable style `border` property string computed using `border.width.thick` and `border.color` + * - Default value: 2px dotted [colors.lightShade] + */ + editable: CSSProperties['border']; +} + +export type _EuiThemeBorder = _EuiThemeBorderValues & _EuiThemeBorderTypes; diff --git a/packages/eui-theme-base/src/variables/breakpoint.ts b/packages/eui-theme-base/src/variables/breakpoint.ts new file mode 100644 index 00000000000..68aef1fba38 --- /dev/null +++ b/packages/eui-theme-base/src/variables/breakpoint.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export const EuiThemeBreakpoints = ['xs', 's', 'm', 'l', 'xl'] as const; + +// This type cannot be a string enum / must be a generic string +// in case consumers add custom breakpoint sizes, such as xxl or xxs +export type _EuiThemeBreakpoint = string; + +// Explicitly list out each key so we can document default values +// via JSDoc (which is available to devs in IDE via intellisense) +export type _EuiThemeBreakpoints = Record<_EuiThemeBreakpoint, number> & { + /** - Default value: 0 */ + xs: number; + /** - Default value: 575 */ + s: number; + /** - Default value: 768 */ + m: number; + /** - Default value: 992 */ + l: number; + /** - Default value: 1200 */ + xl: number; +}; diff --git a/packages/eui-theme-base/src/variables/colors.ts b/packages/eui-theme-base/src/variables/colors.ts new file mode 100644 index 00000000000..8604ecafba4 --- /dev/null +++ b/packages/eui-theme-base/src/variables/colors.ts @@ -0,0 +1,156 @@ +/* + * 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 { ColorModeSwitch, StrictColorModeSwitch } from '../types'; + +/** + * Top 5 colors + */ +export type _EuiThemeBrandColors = { + /** + * Main brand color and used for most **call to actions** like buttons and links. + */ + primary: ColorModeSwitch; + /** + * Pulls attention to key indicators like **notifications** or number of selections. + */ + accent: ColorModeSwitch; + /** + * Used for **positive** messages/graphics and additive actions. + */ + success: ColorModeSwitch; + /** + * Used for **warnings** and actions that have a potential to be destructive. + */ + warning: ColorModeSwitch; + /** + * Used for **negative** messages/graphics like errors and destructive actions. + */ + danger: ColorModeSwitch; +}; + +/** + * Every brand color must have a contrast computed text equivelant + */ +export type _EuiThemeBrandTextColors = { + /** + * Typically computed against `colors.primary` + */ + primaryText: ColorModeSwitch; + /** + * Typically computed against `colors.accent` + */ + accentText: ColorModeSwitch; + /** + * Typically computed against `colors.success` + */ + successText: ColorModeSwitch; + /** + * Typically computed against `colors.warning` + */ + warningText: ColorModeSwitch; + /** + * Typically computed against `colors.danger` + */ + dangerText: ColorModeSwitch; +}; + +export type _EuiThemeShadeColors = { + /** + * Used as the background color of primary **page content and panels** including modals and flyouts. + */ + emptyShade: ColorModeSwitch; + /** + * Used to lightly shade areas that contain **secondary content** or contain panel-like components. + */ + lightestShade: ColorModeSwitch; + /** + * Used for most **borders** and dividers (horizontal rules). + */ + lightShade: ColorModeSwitch; + /** + * The middle gray for all themes; this is the base for `colors.subdued`. + */ + mediumShade: ColorModeSwitch; + /** + * Slightly subtle graphic color + */ + darkShade: ColorModeSwitch; + /** + * Used as the **text** color and the background color for **inverted components** like tooltips and the control bar. + */ + darkestShade: ColorModeSwitch; + /** + * The opposite of `emptyShade` + */ + fullShade: ColorModeSwitch; +}; + +export type _EuiThemeTextColors = { + /** + * Computed against `colors.darkestShade` + */ + text: ColorModeSwitch; + /** + * Computed against `colors.text` + */ + title: ColorModeSwitch; + /** + * Computed against `colors.mediumShade` + */ + subduedText: ColorModeSwitch; + /** + * Computed against `colors.primaryText` + */ + link: ColorModeSwitch; +}; + +export type _EuiThemeSpecialColors = { + /** + * The background color for the **whole window (body)** and is a computed value of `colors.lightestShade`. + * Provides denominator (background) value for **contrast calculations**. + */ + body: ColorModeSwitch; + /** + * Used to **highlight text** when matching against search strings + */ + highlight: ColorModeSwitch; + /** + * Computed against `colors.darkestShade` + */ + disabled: ColorModeSwitch; + /** + * Computed against `colors.disabled` + */ + disabledText: ColorModeSwitch; + /** + * The base color for shadows that gets `transparentized` + * at a value based on the `colorMode` and then layered. + */ + shadow: ColorModeSwitch; +}; + +export type _EuiThemeConstantColors = { + /** + * Purest **white** + */ + ghost: string; + /** + * Purest **black** + */ + ink: string; +}; + +export type _EuiThemeColorsMode = _EuiThemeBrandColors & + _EuiThemeBrandTextColors & + _EuiThemeShadeColors & + _EuiThemeSpecialColors & + _EuiThemeTextColors; + +export type _EuiThemeColors = StrictColorModeSwitch<_EuiThemeColorsMode> & + _EuiThemeConstantColors; diff --git a/packages/eui-theme-base/src/variables/index.ts b/packages/eui-theme-base/src/variables/index.ts new file mode 100644 index 00000000000..48eacef5cbb --- /dev/null +++ b/packages/eui-theme-base/src/variables/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +export * from './animations'; +export * from './borders'; +export * from './breakpoint'; +export * from './colors'; +export * from './_colors_vis'; +export * from './levels'; +export * from './size'; +export * from './shadow'; +export * from './states'; +export * from './typography'; diff --git a/packages/eui-theme-base/src/variables/levels.ts b/packages/eui-theme-base/src/variables/levels.ts new file mode 100644 index 00000000000..7d38c71791b --- /dev/null +++ b/packages/eui-theme-base/src/variables/levels.ts @@ -0,0 +1,60 @@ +/* + * 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 { CSSProperties } from 'react'; + +/** + * Z-Index + * + * Remember that z-index is relative to parent and based on the stacking context. + * z-indexes only compete against other z-indexes when they exist as children of + * that shared parent. + * + * That means a popover with a settings of 2, will still show above a modal + * with a setting of 100, if it is within that modal and not besides it. + * + * Generally that means it's a good idea to consider things added to this file + * as competitive only as siblings. + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context + */ + +export const EuiThemeLevels = [ + 'toast', + 'modal', + 'mask', + 'navigation', + 'menu', + 'header', + 'flyout', + 'maskBelowHeader', + 'content', +] as const; + +export type _EuiThemeLevel = (typeof EuiThemeLevels)[number]; + +export type _EuiThemeLevels = { + /** - Default value: 9000 */ + toast: NonNullable; + /** - Default value: 8000 */ + modal: NonNullable; + /** - Default value: 6000 */ + mask: NonNullable; + /** - Default value: 6000 */ + navigation: NonNullable; + /** - Default value: 2000 */ + menu: NonNullable; + /** - Default value: 1000 */ + header: NonNullable; + /** - Default value: 1000 */ + flyout: NonNullable; + /** - Default value: 1000 */ + maskBelowHeader: NonNullable; + /** - Default value: 0 */ + content: NonNullable; +}; diff --git a/packages/eui-theme-base/src/variables/shadow.ts b/packages/eui-theme-base/src/variables/shadow.ts new file mode 100644 index 00000000000..7761fbdb9a0 --- /dev/null +++ b/packages/eui-theme-base/src/variables/shadow.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export const EuiThemeShadowSizes = ['xs', 's', 'm', 'l', 'xl'] as const; + +export type _EuiThemeShadowSize = (typeof EuiThemeShadowSizes)[number]; + +/** + * Shadow t-shirt sizes descriptions + */ +export const _EuiShadowSizesDescriptions: Record<_EuiThemeShadowSize, string> = + { + xs: 'Very subtle shadow used on small components.', + s: 'Adds subtle depth, usually used in conjunction with a border.', + m: 'Used on small sized portalled content like popovers.', + l: 'Primary shadow used in most cases to add visible depth.', + xl: 'Very large shadows used for large portalled style containers like modals and flyouts.', + }; + +export interface _EuiThemeShadowCustomColor { + color?: string; + property?: 'box-shadow' | 'filter'; +} diff --git a/packages/eui-theme-base/src/variables/size.ts b/packages/eui-theme-base/src/variables/size.ts new file mode 100644 index 00000000000..98428346b61 --- /dev/null +++ b/packages/eui-theme-base/src/variables/size.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +export type _EuiThemeBase = number; + +export const EuiThemeSizes = [ + 'xxs', + 'xs', + 's', + 'm', + 'base', + 'l', + 'xl', + 'xxl', + 'xxxl', + 'xxxxl', +] as const; + +export type _EuiThemeSize = (typeof EuiThemeSizes)[number]; + +export type _EuiThemeSizes = { + /** - Default value: 2px */ + xxs: string; + /** - Default value: 4px */ + xs: string; + /** - Default value: 8px */ + s: string; + /** - Default value: 12px */ + m: string; + /** - Default value: 16px */ + base: string; + /** - Default value: 24px */ + l: string; + /** - Default value: 32px */ + xl: string; + /** - Default value: 40px */ + xxl: string; + /** - Default value: 48px */ + xxxl: string; + /** - Default value: 64px */ + xxxxl: string; +}; diff --git a/packages/eui-theme-base/src/variables/states.ts b/packages/eui-theme-base/src/variables/states.ts new file mode 100644 index 00000000000..2d0283ac949 --- /dev/null +++ b/packages/eui-theme-base/src/variables/states.ts @@ -0,0 +1,33 @@ +/* + * 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 { CSSProperties } from 'react'; +import { ColorModeSwitch } from '../types'; + +export interface _EuiThemeFocus { + /** + * Default color of the focus ring, some components may override this property + * - Default value: currentColor + */ + color: ColorModeSwitch; + /** + * Thickness of the outline + * - Default value: 2px + */ + width: CSSProperties['borderWidth']; + /** + * Used to transparentize the focus background color + * - Default value: { LIGHT: 0.1, DARK: 0.2 } + */ + transparency: ColorModeSwitch; + /** + * Default focus background color. Not all components set a background color on focus + * - Default value: `colors.primary` computed with `focus.transparency` + */ + backgroundColor: ColorModeSwitch; +} diff --git a/packages/eui-theme-base/src/variables/typography.ts b/packages/eui-theme-base/src/variables/typography.ts new file mode 100644 index 00000000000..80ebbc8b1cb --- /dev/null +++ b/packages/eui-theme-base/src/variables/typography.ts @@ -0,0 +1,146 @@ +/* + * 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 { CSSProperties } from 'react'; + +/** + * Font units of measure + */ + +export const EuiThemeFontUnits = ['rem', 'px', 'em'] as const; + +export type _EuiThemeFontUnit = (typeof EuiThemeFontUnits)[number]; + +/* + * Font scale + */ + +export const EuiThemeFontScales = [ + 'xxxs', + 'xxs', + 'xs', + 's', + 'm', + 'l', + 'xl', + 'xxl', +] as const; + +export type _EuiThemeFontScale = (typeof EuiThemeFontScales)[number]; + +export type _EuiThemeFontScales = Record<_EuiThemeFontScale, number>; + +/* + * Font base settings + */ + +export type _EuiThemeFontBase = { + /** + * The whole font family stack for all parts of the UI. + * We encourage only customizing the first font in the stack. + */ + family: string; + /** + * The font family used for monospace UI elements like EuiCode + */ + familyCode?: string; + /** + * The font family used for serif UI elements like blockquotes within EuiText + */ + familySerif?: string; + /** + * Controls advanced features OpenType fonts. + * 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` + */ + baseline: number; + /** + * Establishes the ideal line-height percentage, but it is the `baseline` integer that establishes the final pixel/rem value + */ + lineHeightMultiplier: number; +}; + +/* + * Font weights + */ + +export const EuiThemeFontWeights = [ + 'light', + 'regular', + 'medium', + 'semiBold', + 'bold', +] as const; + +export type _EuiThemeFontWeight = (typeof EuiThemeFontWeights)[number]; + +export type _EuiThemeFontWeights = { + /** - Default value: 300 */ + light: CSSProperties['fontWeight']; + /** - Default value: 400 */ + regular: CSSProperties['fontWeight']; + /** - Default value: 500 */ + medium: CSSProperties['fontWeight']; + /** - Default value: 600 */ + semiBold: CSSProperties['fontWeight']; + /** - Default value: 700 */ + bold: CSSProperties['fontWeight']; +}; + +/** + * Body / Base styles + */ + +export interface _EuiThemeBody { + /** + * A sizing key from one of the font scales to set as the base body font-size + */ + scale: _EuiThemeFontScale; + /** + * A font weight key for setting the base body weight + */ + weight: keyof _EuiThemeFontWeights; +} + +/** + * Title styles + */ + +export interface _EuiThemeTitle { + /** + * A font weight key for setting the base weight for titles and headings + */ + weight: keyof _EuiThemeFontWeights; +} + +/* + * Font + */ + +export type _EuiThemeFont = _EuiThemeFontBase & { + scale: _EuiThemeFontScales; + /** + * @see {@link https://eui.elastic.co/#/theming/typography/values%23font-weight | Reference} for more information + */ + weight: _EuiThemeFontWeights; + body: _EuiThemeBody; + title: _EuiThemeTitle; +}; diff --git a/packages/eui-theme-base/tsconfig.json b/packages/eui-theme-base/tsconfig.json new file mode 100644 index 00000000000..c3190be619a --- /dev/null +++ b/packages/eui-theme-base/tsconfig.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib", + "target": "ES2020", + "lib": [ + "ESNext", + "DOM" + ], + "moduleResolution": "Node", + "declaration": true, + "sourceMap": true, + "noEmitHelpers": true, + "incremental": true, + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "tsBuildInfoFile": "lib/.tsbuildinfo" + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules" + ], +} \ No newline at end of file From 04eab8c46b90d8c6e5297f47fc505991cc8b2d9d Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Sun, 22 Sep 2024 16:02:44 +0200 Subject: [PATCH 10/32] refactor: use new module packages in eui package --- .../src/variables/_buttons.scss | 9 +- .../eui-theme-base/src/variables/_form.scss | 40 +- .../eui-theme-base/src/variables/_page.scss | 2 - .../eui-theme-base/src/variables/_panel.scss | 21 - .../src/variables/_tool_tip.scss | 9 - packages/eui/package.json | 3 + packages/eui/src/components/common.ts | 49 +-- .../eui/src/global_styling/functions/size.ts | 17 +- .../global_styling/variables/_animations.scss | 9 +- .../global_styling/variables/_borders.scss | 10 +- .../global_styling/variables/_buttons.scss | 19 +- .../global_styling/variables/_colors_vis.scss | 71 +--- .../global_styling/variables/_colors_vis.ts | 55 +-- .../variables/_font_weight.scss | 8 +- .../src/global_styling/variables/_form.scss | 23 +- .../global_styling/variables/_responsive.scss | 10 +- .../global_styling/variables/_shadows.scss | 2 +- .../src/global_styling/variables/_size.scss | 16 +- .../src/global_styling/variables/_states.scss | 15 +- .../global_styling/variables/_typography.scss | 76 +--- .../global_styling/variables/_z_index.scss | 34 +- .../global_styling/variables/animations.ts | 69 +-- .../src/global_styling/variables/borders.ts | 74 +--- .../global_styling/variables/breakpoint.ts | 25 +- .../src/global_styling/variables/colors.ts | 161 +------ .../src/global_styling/variables/levels.ts | 57 +-- .../src/global_styling/variables/shadow.ts | 26 +- .../eui/src/global_styling/variables/size.ts | 45 +- .../src/global_styling/variables/states.ts | 26 +- .../global_styling/variables/typography.ts | 152 +------ packages/eui/src/services/theme/types.ts | 116 +---- packages/eui/src/services/theme/utils.test.ts | 279 ------------ packages/eui/src/services/theme/utils.ts | 396 +----------------- 33 files changed, 118 insertions(+), 1806 deletions(-) delete mode 100644 packages/eui-theme-base/src/variables/_page.scss delete mode 100644 packages/eui-theme-base/src/variables/_panel.scss delete mode 100644 packages/eui-theme-base/src/variables/_tool_tip.scss delete mode 100644 packages/eui/src/services/theme/utils.test.ts diff --git a/packages/eui-theme-base/src/variables/_buttons.scss b/packages/eui-theme-base/src/variables/_buttons.scss index 97304c0f5c0..4d4e8a5f0b1 100644 --- a/packages/eui-theme-base/src/variables/_buttons.scss +++ b/packages/eui-theme-base/src/variables/_buttons.scss @@ -2,11 +2,6 @@ $euiButtonHeight: $euiSizeXXL !default; $euiButtonHeightSmall: $euiSizeXL !default; $euiButtonHeightXSmall: $euiSizeL !default; -$euiButtonColorDisabled: tintOrShade($euiTextColor, 70%, 70%) !default; -// Only increase the contrast of background color to text to 2.0 for disabled -$euiButtonColorDisabledText: makeDisabledContrastColor($euiButtonColorDisabled) !default; -$euiButtonColorGhostDisabled: lightOrDarkTheme($euiColorDarkShade, $euiColorLightShade) !default; - // Modifier naming and colors. $euiButtonTypes: ( primary: $euiColorPrimary, @@ -17,3 +12,7 @@ $euiButtonTypes: ( ghost: $euiColorGhost, // Ghost is special, and does not care about theming. text: $euiColorDarkShade, // Reserved for special use cases ) !default; + +// TODO: Remove this once elastic-charts no longer uses this variable +// @see https://github.com/elastic/elastic-charts/pull/2528 +$euiButtonColorDisabledText: $euiColorDisabledText; diff --git a/packages/eui-theme-base/src/variables/_form.scss b/packages/eui-theme-base/src/variables/_form.scss index 162cf7bdd89..41c5dfad04e 100644 --- a/packages/eui-theme-base/src/variables/_form.scss +++ b/packages/eui-theme-base/src/variables/_form.scss @@ -18,42 +18,4 @@ $euiFormControlDisabledColor: $euiColorMediumShade !default; $euiFormControlBoxShadow: 0 0 transparent !default; $euiFormControlPlaceholderText: makeHighContrastColor($euiTextSubduedColor, $euiFormBackgroundColor) !default; $euiFormInputGroupLabelBackground: tintOrShade($euiColorLightShade, 50%, 15%) !default; -$euiFormInputGroupBorder: none !default; - -// Icons sizes -$euiFormControlIconSizes: ( - small: $euiSizeM, - medium: $euiSize, - large: $euiSizeL, - xLarge: $euiSizeXL, - xxLarge: $euiSizeXXL -); - -// Control Layout -$euiFormControlLayoutGroupInputHeight: $euiFormControlHeight - 2px !default; -$euiFormControlLayoutGroupInputCompressedHeight: $euiFormControlCompressedHeight - 2px !default; -$euiFormControlLayoutGroupInputCompressedBorderRadius: $euiFormControlCompressedBorderRadius / 2 !default; - -// Range -$euiRangeTrackColor: $euiColorLightShade !default; -$euiRangeHighlightColor: $euiColorDarkShade !default; - -$euiRangeThumbHeight: $euiSize !default; -$euiRangeThumbWidth: $euiSize !default; -$euiRangeThumbBorderColor: $euiColorEmptyShade !default; -$euiRangeThumbBackgroundColor: $euiRangeHighlightColor; - -$euiRangeTrackWidth: 100% !default; -$euiRangeTrackHeight: $euiSizeM / 2 !default; -$euiRangeTrackCompressedHeight: $euiSizeXS; -$euiRangeTrackBorderWidth: 0 !default; -$euiRangeTrackBorderColor: $euiRangeTrackColor !default; -$euiRangeTrackRadius: $euiBorderRadius !default; - -$euiRangeDisabledOpacity: .25 !default; - -$euiRangeHighlightHeight: $euiRangeTrackHeight !default; -$euiRangeHighlightCompressedHeight: $euiRangeTrackCompressedHeight !default; - -$euiRangeHeight: $euiFormControlHeight !default; -$euiRangeCompressedHeight: $euiFormControlCompressedHeight !default; +$euiFormInputGroupBorder: none !default; \ No newline at end of file diff --git a/packages/eui-theme-base/src/variables/_page.scss b/packages/eui-theme-base/src/variables/_page.scss deleted file mode 100644 index df423080152..00000000000 --- a/packages/eui-theme-base/src/variables/_page.scss +++ /dev/null @@ -1,2 +0,0 @@ -$euiPageDefaultMaxWidth: 1000px !default; -$euiPageSidebarMinWidth: $euiSizeL * 8 !default; diff --git a/packages/eui-theme-base/src/variables/_panel.scss b/packages/eui-theme-base/src/variables/_panel.scss deleted file mode 100644 index 0a2bb6a46f5..00000000000 --- a/packages/eui-theme-base/src/variables/_panel.scss +++ /dev/null @@ -1,21 +0,0 @@ -$euiPanelPaddingModifiers: ( - 'paddingSmall': $euiSizeS, - 'paddingMedium': $euiSize, - 'paddingLarge': $euiSizeL -) !default; - -$euiPanelBorderRadiusModifiers: ( - 'borderRadiusNone': 0, - 'borderRadiusMedium': $euiBorderRadius, -) !default; - -$euiPanelBackgroundColorModifiers: ( - 'transparent': transparent, - 'plain': $euiColorEmptyShade, - 'subdued': $euiPageBackgroundColor, - 'accent': tintOrShade($euiColorAccent, 90%, 70%), - 'primary': tintOrShade($euiColorPrimary, 90%, 70%), - 'success': tintOrShade($euiColorSuccess, 90%, 70%), - 'warning': tintOrShade($euiColorWarning, 90%, 70%), - 'danger': tintOrShade($euiColorDanger, 90%, 70%), -) !default; diff --git a/packages/eui-theme-base/src/variables/_tool_tip.scss b/packages/eui-theme-base/src/variables/_tool_tip.scss deleted file mode 100644 index 6bf4e1e4d9c..00000000000 --- a/packages/eui-theme-base/src/variables/_tool_tip.scss +++ /dev/null @@ -1,9 +0,0 @@ -$euiTooltipBackgroundColor: tintOrShade($euiColorFullShade, 25%, 100%) !default; -$euiTooltipBorderColor: tintOrShade($euiColorFullShade, 35%, 80%) !default; - -$euiTooltipAnimations: ( - top: euiToolTipTop, - left: euiToolTipBottom, - bottom: euiToolTipLeft, - right: euiToolTipRight, -) !default; diff --git a/packages/eui/package.json b/packages/eui/package.json index 4996a999b65..8e568fde537 100644 --- a/packages/eui/package.json +++ b/packages/eui/package.json @@ -51,6 +51,9 @@ "url": "https://github.com/elastic/eui.git" }, "dependencies": { + "@elastic/eui-common": "workspace:^", + "@elastic/eui-theme-base": "workspace:^", + "@elastic/eui-theme-berlin": "workspace:^", "@hello-pangea/dnd": "^16.6.0", "@types/lodash": "^4.14.202", "@types/numeral": "^2.0.5", diff --git a/packages/eui/src/components/common.ts b/packages/eui/src/components/common.ts index 2f09a052349..8742d72c44f 100644 --- a/packages/eui/src/components/common.ts +++ b/packages/eui/src/components/common.ts @@ -17,6 +17,8 @@ import { } from 'react'; import { Interpolation, Theme } from '@emotion/react'; +export type { RecursivePartial, ValueOf } from '@elastic/eui-common'; + export interface CommonProps { className?: string; 'aria-label'?: string; @@ -50,13 +52,6 @@ export function keysOf(obj: T): K[] { return Object.keys(obj) as K[]; } -/** - * Like `keyof typeof`, but for getting values instead of keys - * ValueOf - * Results in `'value1' | 'value2'` - */ -export type ValueOf = T[keyof T]; - export type PropsOf = C extends FunctionComponent ? SFCProps : C extends FunctionComponent @@ -203,43 +198,3 @@ export type PropsForButton = T & { onClick?: MouseEventHandler; } & ButtonHTMLAttributes & P; - -/** - * Replaces all properties on any type as optional, includes nested types - * - * @example - * ```ts - * interface Person { - * name: string; - * age?: number; - * spouse: Person; - * children: Person[]; - * } - * type PartialPerson = RecursivePartial; - * // results in - * interface PartialPerson { - * name?: string; - * age?: number; - * spouse?: RecursivePartial; - * children?: RecursivePartial[] - * } - * ``` - */ -export type RecursivePartial = { - [P in keyof T]?: T[P] extends NonAny[] // checks for nested any[] - ? T[P] - : T[P] extends readonly NonAny[] // checks for nested ReadonlyArray - ? T[P] - : T[P] extends Array - ? Array> - : T[P] extends ReadonlyArray - ? ReadonlyArray> - : T[P] extends Set // checks for Sets - ? Set> - : T[P] extends Map // checks for Maps - ? Map> - : T[P] extends NonAny // checks for primitive values - ? T[P] - : RecursivePartial; // recurse for all non-array and non-primitive values -}; -type NonAny = number | boolean | string | symbol | null; diff --git a/packages/eui/src/global_styling/functions/size.ts b/packages/eui/src/global_styling/functions/size.ts index 66e6ab507d3..d3263020fc7 100644 --- a/packages/eui/src/global_styling/functions/size.ts +++ b/packages/eui/src/global_styling/functions/size.ts @@ -6,19 +6,4 @@ * Side Public License, v 1. */ -/** - * Calculates the `px` value based on a scale multiplier - * @param scale - The font scale multiplier - * * - * @param themeOrBase - Theme base value - * * - * @returns string - Rem unit aligned to baseline - */ - -export const sizeToPixel = - (scale: number = 1) => - (themeOrBase: number | { base: number; [key: string]: any }) => { - const base = - typeof themeOrBase === 'object' ? themeOrBase.base : themeOrBase; - return `${base * scale}px`; - }; +export { sizeToPixel } from '@elastic/eui-common'; diff --git a/packages/eui/src/global_styling/variables/_animations.scss b/packages/eui/src/global_styling/variables/_animations.scss index 0ffe44346dd..08e4098204e 100644 --- a/packages/eui/src/global_styling/variables/_animations.scss +++ b/packages/eui/src/global_styling/variables/_animations.scss @@ -1,13 +1,6 @@ // Animations -$euiAnimSlightBounce: cubic-bezier(.34, 1.61, .7, 1) !default; -$euiAnimSlightResistance: cubic-bezier(.694, .0482, .335, 1) !default; - -$euiAnimSpeedExtraFast: 90ms !default; -$euiAnimSpeedFast: 150ms !default; -$euiAnimSpeedNormal: 250ms !default; -$euiAnimSpeedSlow: 350ms !default; -$euiAnimSpeedExtraSlow: 500ms !default; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/animations' // Keyframe animation declarations can be found in // utility/animations.scss diff --git a/packages/eui/src/global_styling/variables/_borders.scss b/packages/eui/src/global_styling/variables/_borders.scss index 6fa0216ff3b..adc8666bdf4 100644 --- a/packages/eui/src/global_styling/variables/_borders.scss +++ b/packages/eui/src/global_styling/variables/_borders.scss @@ -1,11 +1,3 @@ // Borders -$euiBorderWidthThin: 1px !default; -$euiBorderWidthThick: 2px !default; - -$euiBorderColor: $euiColorLightShade !default; -$euiBorderRadius: $euiSizeS * .75 !default; -$euiBorderRadiusSmall: $euiSizeS * .5 !default; -$euiBorderThick: $euiBorderWidthThick solid $euiBorderColor !default; -$euiBorderThin: $euiBorderWidthThin solid $euiBorderColor !default; -$euiBorderEditable: $euiBorderWidthThick dotted $euiBorderColor !default; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/borders' diff --git a/packages/eui/src/global_styling/variables/_buttons.scss b/packages/eui/src/global_styling/variables/_buttons.scss index 4d4e8a5f0b1..3056f68a5d9 100644 --- a/packages/eui/src/global_styling/variables/_buttons.scss +++ b/packages/eui/src/global_styling/variables/_buttons.scss @@ -1,18 +1 @@ -$euiButtonHeight: $euiSizeXXL !default; -$euiButtonHeightSmall: $euiSizeXL !default; -$euiButtonHeightXSmall: $euiSizeL !default; - -// Modifier naming and colors. -$euiButtonTypes: ( - primary: $euiColorPrimary, - accent: $euiColorAccent, - success: $euiColorSuccess, - warning: $euiColorWarning, - danger: $euiColorDanger, - ghost: $euiColorGhost, // Ghost is special, and does not care about theming. - text: $euiColorDarkShade, // Reserved for special use cases -) !default; - -// TODO: Remove this once elastic-charts no longer uses this variable -// @see https://github.com/elastic/elastic-charts/pull/2528 -$euiButtonColorDisabledText: $euiColorDisabledText; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/buttons' diff --git a/packages/eui/src/global_styling/variables/_colors_vis.scss b/packages/eui/src/global_styling/variables/_colors_vis.scss index cfffdf5e55d..10a57baded8 100644 --- a/packages/eui/src/global_styling/variables/_colors_vis.scss +++ b/packages/eui/src/global_styling/variables/_colors_vis.scss @@ -1,72 +1,3 @@ // Visualization colors -// stylelint-disable color-no-hex -// Maps allow for easier JSON usage -// Use map_merge($euiColorVisColors, $yourMap) to change individual colors after importing ths file -// The `behindText` variant is a direct copy of the hex output by the JS euiPaletteColorBlindBehindText() function -$euiPaletteColorBlind: ( - euiColorVis0: ( - graphic: #54B399, - behindText: #6DCCB1, - ), - euiColorVis1: ( - graphic: #6092C0, - behindText: #79AAD9, - ), - euiColorVis2: ( - graphic: #D36086, - behindText: #EE789D, - ), - euiColorVis3: ( - graphic: #9170B8, - behindText: #A987D1, - ), - euiColorVis4: ( - graphic: #CA8EAE, - behindText: #E4A6C7, - ), - euiColorVis5: ( - graphic: #D6BF57, - behindText: #F1D86F, - ), - euiColorVis6: ( - graphic: #B9A888, - behindText: #D2C0A0, - ), - euiColorVis7: ( - graphic: #DA8B45, - behindText: #F5A35C, - ), - euiColorVis8: ( - graphic: #AA6556, - behindText: #C47C6C, - ), - euiColorVis9: ( - graphic: #E7664C, - behindText: #FF7E62, - ) -) !default; - -$euiPaletteColorBlindKeys: map-keys($euiPaletteColorBlind); - -$euiColorVis0: map-get(map-get($euiPaletteColorBlind, 'euiColorVis0'), 'graphic') !default; -$euiColorVis1: map-get(map-get($euiPaletteColorBlind, 'euiColorVis1'), 'graphic') !default; -$euiColorVis2: map-get(map-get($euiPaletteColorBlind, 'euiColorVis2'), 'graphic') !default; -$euiColorVis3: map-get(map-get($euiPaletteColorBlind, 'euiColorVis3'), 'graphic') !default; -$euiColorVis4: map-get(map-get($euiPaletteColorBlind, 'euiColorVis4'), 'graphic') !default; -$euiColorVis5: map-get(map-get($euiPaletteColorBlind, 'euiColorVis5'), 'graphic') !default; -$euiColorVis6: map-get(map-get($euiPaletteColorBlind, 'euiColorVis6'), 'graphic') !default; -$euiColorVis7: map-get(map-get($euiPaletteColorBlind, 'euiColorVis7'), 'graphic') !default; -$euiColorVis8: map-get(map-get($euiPaletteColorBlind, 'euiColorVis8'), 'graphic') !default; -$euiColorVis9: map-get(map-get($euiPaletteColorBlind, 'euiColorVis9'), 'graphic') !default; - -$euiColorVis0_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis0'), 'behindText') !default; -$euiColorVis1_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis1'), 'behindText') !default; -$euiColorVis2_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis2'), 'behindText') !default; -$euiColorVis3_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis3'), 'behindText') !default; -$euiColorVis4_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis4'), 'behindText') !default; -$euiColorVis5_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis5'), 'behindText') !default; -$euiColorVis6_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis6'), 'behindText') !default; -$euiColorVis7_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis7'), 'behindText') !default; -$euiColorVis8_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis8'), 'behindText') !default; -$euiColorVis9_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis9'), 'behindText') !default; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/colors_vis' diff --git a/packages/eui/src/global_styling/variables/_colors_vis.ts b/packages/eui/src/global_styling/variables/_colors_vis.ts index 4459b04ff8c..9ff03accec4 100644 --- a/packages/eui/src/global_styling/variables/_colors_vis.ts +++ b/packages/eui/src/global_styling/variables/_colors_vis.ts @@ -6,57 +6,4 @@ * Side Public License, v 1. */ -/** - * NOTE: These were quick conversions of their Sass counterparts. - * They have yet to be used/tested. - * TODO: Make the graphic version available from `euiPaletteColorBlind()` - */ - -// Maps allow for easier JSON usage -// Use map_merge(euiColorVisColors, $yourMap) to change individual colors after importing ths file -// The `behindText` variant is a direct copy of the hex output by the JS euiPaletteColorBlindBehindText() function -const euiPaletteColorBlind = { - euiColorVis0: { - graphic: '#54B399', - }, - euiColorVis1: { - graphic: '#6092C0', - }, - euiColorVis2: { - graphic: '#D36086', - }, - euiColorVis3: { - graphic: '#9170B8', - }, - euiColorVis4: { - graphic: '#CA8EAE', - }, - euiColorVis5: { - graphic: '#D6BF57', - }, - euiColorVis6: { - graphic: '#B9A888', - }, - euiColorVis7: { - graphic: '#DA8B45', - }, - euiColorVis8: { - graphic: '#AA6556', - }, - euiColorVis9: { - graphic: '#E7664C', - }, -}; - -export const colorVis = { - euiColorVis0: euiPaletteColorBlind.euiColorVis0.graphic, - euiColorVis1: euiPaletteColorBlind.euiColorVis1.graphic, - euiColorVis2: euiPaletteColorBlind.euiColorVis2.graphic, - euiColorVis3: euiPaletteColorBlind.euiColorVis3.graphic, - euiColorVis4: euiPaletteColorBlind.euiColorVis4.graphic, - euiColorVis5: euiPaletteColorBlind.euiColorVis5.graphic, - euiColorVis6: euiPaletteColorBlind.euiColorVis6.graphic, - euiColorVis7: euiPaletteColorBlind.euiColorVis7.graphic, - euiColorVis8: euiPaletteColorBlind.euiColorVis8.graphic, - euiColorVis9: euiPaletteColorBlind.euiColorVis9.graphic, -}; +export { colorVis } from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/global_styling/variables/_font_weight.scss b/packages/eui/src/global_styling/variables/_font_weight.scss index f5dfd287835..07e8c275f2f 100644 --- a/packages/eui/src/global_styling/variables/_font_weight.scss +++ b/packages/eui/src/global_styling/variables/_font_weight.scss @@ -1,10 +1,4 @@ // Separated out to its own file for easy import into docs // Font weights -$euiFontWeightLight: 300 !default; -$euiFontWeightRegular: 400 !default; -$euiFontWeightMedium: 500 !default; -$euiFontWeightSemiBold: 600 !default; -$euiFontWeightBold: 700 !default; -$euiCodeFontWeightRegular: 400 !default; -$euiCodeFontWeightBold: 700 !default; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/font_weight' diff --git a/packages/eui/src/global_styling/variables/_form.scss b/packages/eui/src/global_styling/variables/_form.scss index 49a4d620b11..6bbf8efff0b 100644 --- a/packages/eui/src/global_styling/variables/_form.scss +++ b/packages/eui/src/global_styling/variables/_form.scss @@ -1,21 +1,2 @@ -// Sizing -$euiFormMaxWidth: $euiSizeXXL * 10 !default; -$euiFormControlHeight: $euiSizeXXL !default; -$euiFormControlCompressedHeight: $euiSizeXL !default; -$euiFormControlPadding: $euiSizeM !default; -$euiFormControlCompressedPadding: $euiSizeS !default; -$euiFormControlBorderRadius: $euiBorderRadius !default; -$euiFormControlCompressedBorderRadius: $euiBorderRadiusSmall !default; - -// Coloring -$euiFormBackgroundColor: tintOrShade($euiColorLightestShade, 60%, 40%) !default; -$euiFormBackgroundDisabledColor: darken($euiColorLightestShade, 2%) !default; -$euiFormBackgroundReadOnlyColor: $euiColorEmptyShade !default; -$euiFormBorderOpaqueColor: shadeOrTint(desaturate(adjust-hue($euiColorPrimary, 22), 22.95), 26%, 100%) !default; -$euiFormBorderColor: transparentize($euiFormBorderOpaqueColor, .9) !default; -$euiFormBorderDisabledColor: transparentize($euiFormBorderOpaqueColor, .9) !default; -$euiFormControlDisabledColor: $euiColorMediumShade !default; -$euiFormControlBoxShadow: 0 0 transparent !default; -$euiFormControlPlaceholderText: makeHighContrastColor($euiTextSubduedColor, $euiFormBackgroundColor) !default; -$euiFormInputGroupLabelBackground: tintOrShade($euiColorLightShade, 50%, 15%) !default; -$euiFormInputGroupBorder: none !default; +// Form +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/form' diff --git a/packages/eui/src/global_styling/variables/_responsive.scss b/packages/eui/src/global_styling/variables/_responsive.scss index de6e8ca5b83..6c1b3355918 100644 --- a/packages/eui/src/global_styling/variables/_responsive.scss +++ b/packages/eui/src/global_styling/variables/_responsive.scss @@ -1,9 +1 @@ -$euiBreakpoints: ( - 'xs': 0, - 's': 575px, - 'm': 768px, - 'l': 992px, - 'xl': 1200px -) !default; - -$euiBreakpointKeys: map-keys($euiBreakpoints); +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/responsive' diff --git a/packages/eui/src/global_styling/variables/_shadows.scss b/packages/eui/src/global_styling/variables/_shadows.scss index 05e445f27a1..ee889447914 100644 --- a/packages/eui/src/global_styling/variables/_shadows.scss +++ b/packages/eui/src/global_styling/variables/_shadows.scss @@ -1,2 +1,2 @@ // Shadows -$euiShadowColor: $euiColorInk !default; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/shadows' diff --git a/packages/eui/src/global_styling/variables/_size.scss b/packages/eui/src/global_styling/variables/_size.scss index f07645832d1..3ad0fca24ac 100644 --- a/packages/eui/src/global_styling/variables/_size.scss +++ b/packages/eui/src/global_styling/variables/_size.scss @@ -1,15 +1 @@ -$euiSize: 16px !default; - -$euiSizeXS: $euiSize * .25 !default; -$euiSizeS: $euiSize * .5 !default; -$euiSizeM: $euiSize * .75 !default; -$euiSizeL: $euiSize * 1.5 !default; -$euiSizeXL: $euiSize * 2 !default; -$euiSizeXXL: $euiSize * 2.5 !default; - -$euiButtonMinWidth: $euiSize * 7 !default; - -$euiScrollBar: $euiSize !default; -// Corner sizes are used as an inset border and therefore a smaller corner size means a larger thumb -$euiScrollBarCorner: $euiSizeXS !default; -$euiScrollBarCornerThin: $euiSizeS * .75 !default; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/size' diff --git a/packages/eui/src/global_styling/variables/_states.scss b/packages/eui/src/global_styling/variables/_states.scss index fba4cc59caa..ee6896362de 100644 --- a/packages/eui/src/global_styling/variables/_states.scss +++ b/packages/eui/src/global_styling/variables/_states.scss @@ -1,14 +1 @@ -// Colors -$euiFocusRingColor: rgba($euiColorPrimary, .3) !default; -$euiFocusRingAnimStartColor: rgba($euiColorPrimary, 0) !default; -$euiFocusRingAnimStartSize: 6px !default; -$euiFocusRingAnimStartSizeLarge: 10px !default; - -// Sizing -$euiFocusRingSizeLarge: $euiSizeXS !default; -$euiFocusRingSize: $euiFocusRingSizeLarge * .75 !default; - -// Transparency -$euiFocusTransparency: lightOrDarkTheme(.1, .2) !default; -$euiFocusTransparencyPercent: lightOrDarkTheme(90%, 80%) !default; -$euiFocusBackgroundColor: tintOrShade($euiColorPrimary, $euiFocusTransparencyPercent, $euiFocusTransparencyPercent) !default; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/states' \ No newline at end of file diff --git a/packages/eui/src/global_styling/variables/_typography.scss b/packages/eui/src/global_styling/variables/_typography.scss index 1ca62f3248c..f7c0ee85a2d 100644 --- a/packages/eui/src/global_styling/variables/_typography.scss +++ b/packages/eui/src/global_styling/variables/_typography.scss @@ -1,75 +1 @@ -// Families -$euiFontFamily: 'Inter', BlinkMacSystemFont, Helvetica, Arial, sans-serif !default; -$euiCodeFontFamily: 'Roboto Mono', Menlo, Courier, monospace !default; - -// Careful using ligatures. Code editors like ACE will often error because of width calculations -$euiFontFeatureSettings: 'calt' 1, 'kern' 1, 'liga' 1 !default; - -// Font sizes -- scale is loosely based on Major Third (1.250) -$euiTextScale: 2.25, 1.75, 1.25, 1.125, 1, .875, .75 !default; - -$euiFontSize: $euiSize !default; // 5th position in scale -$euiFontSizeXS: $euiFontSize * nth($euiTextScale, 7) !default; // 12px -$euiFontSizeS: $euiFontSize * nth($euiTextScale, 6) !default; // 14px -$euiFontSizeM: $euiFontSize * nth($euiTextScale, 4) !default; // 18px -$euiFontSizeL: $euiFontSize * nth($euiTextScale, 3) !default; // 20px -$euiFontSizeXL: $euiFontSize * nth($euiTextScale, 2) !default; // 28px -$euiFontSizeXXL: $euiFontSize * nth($euiTextScale, 1) !default; // 36px - -// Line height -$euiLineHeight: 1.5 !default; -$euiBodyLineHeight: 1 !default; - -// Normally functions are imported before variables in `_index.scss` files -// But because they need to consume some typography variables they need to live here -@function convertToRem($size) { - @return #{$size / $euiFontSize}rem; -} - -// Our base gridline is at 1/2 the font-size, ensure line-heights stay on that gridline. -// EX: A proper line-height for text is 1.5 times the font-size. -// If our base font size (euiFontSize) is 16, our baseline is 8 (16*1.5 / 3). To ensure the -// text stays on the baseline, we pass a multiplier to calculate a line-height in rems. -@function lineHeightFromBaseline($multiplier: 3) { - @return convertToRem(($euiFontSize / 2) * $multiplier); -} - -// Titles map -// Lists all the properties per EuiTitle size that then gets looped through to create the selectors. -// The map allows for tokenization and easier customization per theme, otherwise you'd have to override the selectors themselves -$euiTitles: ( - 'xxxs': ( - 'font-size': $euiFontSizeXS, - 'line-height': lineHeightFromBaseline(3), - 'font-weight': $euiFontWeightBold, - ), - 'xxs': ( - 'font-size': $euiFontSizeS, - 'line-height': lineHeightFromBaseline(3), - 'font-weight': $euiFontWeightBold, - ), - 'xs': ( - 'font-size': $euiFontSize, - 'line-height': lineHeightFromBaseline(3), - 'font-weight': $euiFontWeightSemiBold, - 'letter-spacing': -.02em, - ), - 's': ( - 'font-size': $euiFontSizeL, - 'line-height': lineHeightFromBaseline(4), - 'font-weight': $euiFontWeightMedium, - 'letter-spacing': -.025em, - ), - 'm': ( - 'font-size': $euiFontSizeXL, - 'line-height': lineHeightFromBaseline(5), - 'font-weight': $euiFontWeightLight, - 'letter-spacing': -.04em, - ), - 'l': ( - 'font-size': $euiFontSizeXXL, - 'line-height': lineHeightFromBaseline(6), - 'font-weight': $euiFontWeightLight, - 'letter-spacing': -.03em, - ), -) !default; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/typography' \ No newline at end of file diff --git a/packages/eui/src/global_styling/variables/_z_index.scss b/packages/eui/src/global_styling/variables/_z_index.scss index 2448a34c61a..a14a30f06d1 100644 --- a/packages/eui/src/global_styling/variables/_z_index.scss +++ b/packages/eui/src/global_styling/variables/_z_index.scss @@ -1,34 +1,2 @@ // Z-Index - -// Remember that z-index is relative to parent and based on the stacking context. -// z-indexes only compete against other z-indexes when they exist as children of -// that shared parent. - -// That means a popover with a settings of 2, will still show above a modal -// with a setting of 100, if it is within that modal and not besides it. - -// Generally that means it's a good idea to consider things added to this file -// as competitive only as siblings. - -// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context - -$euiZLevel0: 0; -$euiZLevel1: 1000; -$euiZLevel2: 2000; -$euiZLevel3: 3000; -$euiZLevel4: 4000; -$euiZLevel5: 5000; -$euiZLevel6: 6000; -$euiZLevel7: 7000; -$euiZLevel8: 8000; -$euiZLevel9: 9000; - -$euiZToastList: $euiZLevel9; -$euiZModal: $euiZLevel8; -$euiZMask: $euiZLevel6; -$euiZNavigation: $euiZLevel6; -$euiZContentMenu: $euiZLevel2; -$euiZHeader: $euiZLevel1; -$euiZFlyout: $euiZHeader; -$euiZMaskBelowHeader: $euiZHeader; -$euiZContent: $euiZLevel0; +@import '../../../node_modules/@elastic/eui-theme-base/src/variables/z_index' diff --git a/packages/eui/src/global_styling/variables/animations.ts b/packages/eui/src/global_styling/variables/animations.ts index 46bce009c92..fa5600993f6 100644 --- a/packages/eui/src/global_styling/variables/animations.ts +++ b/packages/eui/src/global_styling/variables/animations.ts @@ -5,62 +5,15 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { CSSProperties } from 'react'; -/** - * A constant storing the `prefers-reduced-motion` media query - * so that when it is turned off, animations are not run. - */ -export const euiCanAnimate = - '@media screen and (prefers-reduced-motion: no-preference)'; - -/** - * A constant storing the `prefers-reduced-motion` media query that will - * only apply the content if the setting is off (reduce). - */ -export const euiCantAnimate = - '@media screen and (prefers-reduced-motion: reduce)'; - -/** - * Speeds / Durations / Delays - */ - -export const EuiThemeAnimationSpeeds = [ - 'extraFast', - 'fast', - 'normal', - 'slow', - 'extraSlow', -] as const; - -export type _EuiThemeAnimationSpeed = (typeof EuiThemeAnimationSpeeds)[number]; - -export type _EuiThemeAnimationSpeeds = { - /** - Default value: 90ms */ - extraFast: CSSProperties['animationDuration']; - /** - Default value: 150ms */ - fast: CSSProperties['animationDuration']; - /** - Default value: 250ms */ - normal: CSSProperties['animationDuration']; - /** - Default value: 350ms */ - slow: CSSProperties['animationDuration']; - /** - Default value: 500ms */ - extraSlow: CSSProperties['animationDuration']; -}; - -/** - * Easings / Timing functions - */ - -export const EuiThemeAnimationEasings = ['bounce', 'resistance'] as const; - -export type _EuiThemeAnimationEasing = - (typeof EuiThemeAnimationEasings)[number]; - -export type _EuiThemeAnimationEasings = Record< - _EuiThemeAnimationEasing, - CSSProperties['animationTimingFunction'] ->; - -export type _EuiThemeAnimation = _EuiThemeAnimationEasings & - _EuiThemeAnimationSpeeds; +export { + euiCanAnimate, + euiCantAnimate, + EuiThemeAnimationSpeeds, + EuiThemeAnimationEasings, + type _EuiThemeAnimationSpeed, + type _EuiThemeAnimationSpeeds, + type _EuiThemeAnimationEasing, + type _EuiThemeAnimationEasings, + type _EuiThemeAnimation, +} from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/global_styling/variables/borders.ts b/packages/eui/src/global_styling/variables/borders.ts index 10eda82eb9b..03b9d04bbb4 100644 --- a/packages/eui/src/global_styling/variables/borders.ts +++ b/packages/eui/src/global_styling/variables/borders.ts @@ -6,69 +6,11 @@ * Side Public License, v 1. */ -import { CSSProperties } from 'react'; -import { ColorModeSwitch } from '../../services/theme/types'; - -export interface _EuiThemeBorderWidthValues { - /** - * Thinnest width for border - * - Default value: 1px - */ - thin: CSSProperties['borderWidth']; - /** - * Thickest width for border - * - Default value: 2px - */ - thick: CSSProperties['borderWidth']; -} - -export interface _EuiThemeBorderRadiusValues { - /** - * Primary corner radius size - * - Default value: 6px - */ - medium: CSSProperties['borderRadius']; - /** - * Small corner radius size - * - Default value: 4px - */ - small: CSSProperties['borderRadius']; -} - -export interface _EuiThemeBorderColorValues { - /** - * Color for all borders; Default is `colors.lightShade` - */ - color: ColorModeSwitch; -} - -export interface _EuiThemeBorderValues extends _EuiThemeBorderColorValues { - /** - * Varied thicknesses for borders - */ - width: _EuiThemeBorderWidthValues; - /** - * Varied border radii - */ - radius: _EuiThemeBorderRadiusValues; -} - -export interface _EuiThemeBorderTypes { - /** - * Full `border` property string computed using `border.width.thin` and `border.color` - * - Default value: 1px solid [colors.lightShade] - */ - thin: CSSProperties['border']; - /** - * Full `border` property string computed using `border.width.thick` and `border.color` - * - Default value: 2px solid [colors.lightShade] - */ - thick: CSSProperties['border']; - /** - * Full editable style `border` property string computed using `border.width.thick` and `border.color` - * - Default value: 2px dotted [colors.lightShade] - */ - editable: CSSProperties['border']; -} - -export type _EuiThemeBorder = _EuiThemeBorderValues & _EuiThemeBorderTypes; +export type { + _EuiThemeBorderWidthValues, + _EuiThemeBorderRadiusValues, + _EuiThemeBorderColorValues, + _EuiThemeBorderValues, + _EuiThemeBorderTypes, + _EuiThemeBorder, +} from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/global_styling/variables/breakpoint.ts b/packages/eui/src/global_styling/variables/breakpoint.ts index 68aef1fba38..456c0f7649e 100644 --- a/packages/eui/src/global_styling/variables/breakpoint.ts +++ b/packages/eui/src/global_styling/variables/breakpoint.ts @@ -6,23 +6,8 @@ * Side Public License, v 1. */ -export const EuiThemeBreakpoints = ['xs', 's', 'm', 'l', 'xl'] as const; - -// This type cannot be a string enum / must be a generic string -// in case consumers add custom breakpoint sizes, such as xxl or xxs -export type _EuiThemeBreakpoint = string; - -// Explicitly list out each key so we can document default values -// via JSDoc (which is available to devs in IDE via intellisense) -export type _EuiThemeBreakpoints = Record<_EuiThemeBreakpoint, number> & { - /** - Default value: 0 */ - xs: number; - /** - Default value: 575 */ - s: number; - /** - Default value: 768 */ - m: number; - /** - Default value: 992 */ - l: number; - /** - Default value: 1200 */ - xl: number; -}; +export { + EuiThemeBreakpoints, + type _EuiThemeBreakpoint, + type _EuiThemeBreakpoints, +} from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/global_styling/variables/colors.ts b/packages/eui/src/global_styling/variables/colors.ts index ab15e23d166..679f5f9b27c 100644 --- a/packages/eui/src/global_styling/variables/colors.ts +++ b/packages/eui/src/global_styling/variables/colors.ts @@ -6,154 +6,13 @@ * Side Public License, v 1. */ -import { - ColorModeSwitch, - StrictColorModeSwitch, -} from '../../services/theme/types'; - -/** - * Top 5 colors - */ -export type _EuiThemeBrandColors = { - /** - * Main brand color and used for most **call to actions** like buttons and links. - */ - primary: ColorModeSwitch; - /** - * Pulls attention to key indicators like **notifications** or number of selections. - */ - accent: ColorModeSwitch; - /** - * Used for **positive** messages/graphics and additive actions. - */ - success: ColorModeSwitch; - /** - * Used for **warnings** and actions that have a potential to be destructive. - */ - warning: ColorModeSwitch; - /** - * Used for **negative** messages/graphics like errors and destructive actions. - */ - danger: ColorModeSwitch; -}; - -/** - * Every brand color must have a contrast computed text equivelant - */ -export type _EuiThemeBrandTextColors = { - /** - * Typically computed against `colors.primary` - */ - primaryText: ColorModeSwitch; - /** - * Typically computed against `colors.accent` - */ - accentText: ColorModeSwitch; - /** - * Typically computed against `colors.success` - */ - successText: ColorModeSwitch; - /** - * Typically computed against `colors.warning` - */ - warningText: ColorModeSwitch; - /** - * Typically computed against `colors.danger` - */ - dangerText: ColorModeSwitch; -}; - -export type _EuiThemeShadeColors = { - /** - * Used as the background color of primary **page content and panels** including modals and flyouts. - */ - emptyShade: ColorModeSwitch; - /** - * Used to lightly shade areas that contain **secondary content** or contain panel-like components. - */ - lightestShade: ColorModeSwitch; - /** - * Used for most **borders** and dividers (horizontal rules). - */ - lightShade: ColorModeSwitch; - /** - * The middle gray for all themes; this is the base for `colors.subdued`. - */ - mediumShade: ColorModeSwitch; - /** - * Slightly subtle graphic color - */ - darkShade: ColorModeSwitch; - /** - * Used as the **text** color and the background color for **inverted components** like tooltips and the control bar. - */ - darkestShade: ColorModeSwitch; - /** - * The opposite of `emptyShade` - */ - fullShade: ColorModeSwitch; -}; - -export type _EuiThemeTextColors = { - /** - * Computed against `colors.darkestShade` - */ - text: ColorModeSwitch; - /** - * Computed against `colors.text` - */ - title: ColorModeSwitch; - /** - * Computed against `colors.mediumShade` - */ - subduedText: ColorModeSwitch; - /** - * Computed against `colors.primaryText` - */ - link: ColorModeSwitch; -}; - -export type _EuiThemeSpecialColors = { - /** - * The background color for the **whole window (body)** and is a computed value of `colors.lightestShade`. - * Provides denominator (background) value for **contrast calculations**. - */ - body: ColorModeSwitch; - /** - * Used to **highlight text** when matching against search strings - */ - highlight: ColorModeSwitch; - /** - * Computed against `colors.darkestShade` - */ - disabled: ColorModeSwitch; - /** - * Computed against `colors.disabled` - */ - disabledText: ColorModeSwitch; - /** - * The base color for shadows that gets `transparentized` - * at a value based on the `colorMode` and then layered. - */ - shadow: ColorModeSwitch; -}; - -export type _EuiThemeConstantColors = { - /** - * Purest **white** - */ - ghost: string; - /** - * Purest **black** - */ - ink: string; -}; - -export type _EuiThemeColorsMode = _EuiThemeBrandColors & - _EuiThemeBrandTextColors & - _EuiThemeShadeColors & - _EuiThemeSpecialColors & - _EuiThemeTextColors; - -export type _EuiThemeColors = StrictColorModeSwitch<_EuiThemeColorsMode> & - _EuiThemeConstantColors; +export type { + _EuiThemeBrandColors, + _EuiThemeBrandTextColors, + _EuiThemeShadeColors, + _EuiThemeTextColors, + _EuiThemeSpecialColors, + _EuiThemeConstantColors, + _EuiThemeColorsMode, + _EuiThemeColors, +} from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/global_styling/variables/levels.ts b/packages/eui/src/global_styling/variables/levels.ts index 7d38c71791b..e6fdaed63c4 100644 --- a/packages/eui/src/global_styling/variables/levels.ts +++ b/packages/eui/src/global_styling/variables/levels.ts @@ -6,55 +6,8 @@ * Side Public License, v 1. */ -import { CSSProperties } from 'react'; - -/** - * Z-Index - * - * Remember that z-index is relative to parent and based on the stacking context. - * z-indexes only compete against other z-indexes when they exist as children of - * that shared parent. - * - * That means a popover with a settings of 2, will still show above a modal - * with a setting of 100, if it is within that modal and not besides it. - * - * Generally that means it's a good idea to consider things added to this file - * as competitive only as siblings. - * - * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context - */ - -export const EuiThemeLevels = [ - 'toast', - 'modal', - 'mask', - 'navigation', - 'menu', - 'header', - 'flyout', - 'maskBelowHeader', - 'content', -] as const; - -export type _EuiThemeLevel = (typeof EuiThemeLevels)[number]; - -export type _EuiThemeLevels = { - /** - Default value: 9000 */ - toast: NonNullable; - /** - Default value: 8000 */ - modal: NonNullable; - /** - Default value: 6000 */ - mask: NonNullable; - /** - Default value: 6000 */ - navigation: NonNullable; - /** - Default value: 2000 */ - menu: NonNullable; - /** - Default value: 1000 */ - header: NonNullable; - /** - Default value: 1000 */ - flyout: NonNullable; - /** - Default value: 1000 */ - maskBelowHeader: NonNullable; - /** - Default value: 0 */ - content: NonNullable; -}; +export { + EuiThemeLevels, + type _EuiThemeLevel, + type _EuiThemeLevels, +} from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/global_styling/variables/shadow.ts b/packages/eui/src/global_styling/variables/shadow.ts index 7761fbdb9a0..a466ecb3fc0 100644 --- a/packages/eui/src/global_styling/variables/shadow.ts +++ b/packages/eui/src/global_styling/variables/shadow.ts @@ -6,23 +6,9 @@ * Side Public License, v 1. */ -export const EuiThemeShadowSizes = ['xs', 's', 'm', 'l', 'xl'] as const; - -export type _EuiThemeShadowSize = (typeof EuiThemeShadowSizes)[number]; - -/** - * Shadow t-shirt sizes descriptions - */ -export const _EuiShadowSizesDescriptions: Record<_EuiThemeShadowSize, string> = - { - xs: 'Very subtle shadow used on small components.', - s: 'Adds subtle depth, usually used in conjunction with a border.', - m: 'Used on small sized portalled content like popovers.', - l: 'Primary shadow used in most cases to add visible depth.', - xl: 'Very large shadows used for large portalled style containers like modals and flyouts.', - }; - -export interface _EuiThemeShadowCustomColor { - color?: string; - property?: 'box-shadow' | 'filter'; -} +export { + EuiThemeShadowSizes, + _EuiShadowSizesDescriptions, + type _EuiThemeShadowSize, + type _EuiThemeShadowCustomColor, +} from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/global_styling/variables/size.ts b/packages/eui/src/global_styling/variables/size.ts index 98428346b61..bd9531337c9 100644 --- a/packages/eui/src/global_styling/variables/size.ts +++ b/packages/eui/src/global_styling/variables/size.ts @@ -6,42 +6,9 @@ * Side Public License, v 1. */ -export type _EuiThemeBase = number; - -export const EuiThemeSizes = [ - 'xxs', - 'xs', - 's', - 'm', - 'base', - 'l', - 'xl', - 'xxl', - 'xxxl', - 'xxxxl', -] as const; - -export type _EuiThemeSize = (typeof EuiThemeSizes)[number]; - -export type _EuiThemeSizes = { - /** - Default value: 2px */ - xxs: string; - /** - Default value: 4px */ - xs: string; - /** - Default value: 8px */ - s: string; - /** - Default value: 12px */ - m: string; - /** - Default value: 16px */ - base: string; - /** - Default value: 24px */ - l: string; - /** - Default value: 32px */ - xl: string; - /** - Default value: 40px */ - xxl: string; - /** - Default value: 48px */ - xxxl: string; - /** - Default value: 64px */ - xxxxl: string; -}; +export { + EuiThemeSizes, + type _EuiThemeBase, + type _EuiThemeSize, + type _EuiThemeSizes, +} from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/global_styling/variables/states.ts b/packages/eui/src/global_styling/variables/states.ts index 4ec8bf0d87d..b61f3efb3c4 100644 --- a/packages/eui/src/global_styling/variables/states.ts +++ b/packages/eui/src/global_styling/variables/states.ts @@ -6,28 +6,4 @@ * Side Public License, v 1. */ -import { ColorModeSwitch } from '../../services/theme/types'; -import { CSSProperties } from 'react'; - -export interface _EuiThemeFocus { - /** - * Default color of the focus ring, some components may override this property - * - Default value: currentColor - */ - color: ColorModeSwitch; - /** - * Thickness of the outline - * - Default value: 2px - */ - width: CSSProperties['borderWidth']; - /** - * Used to transparentize the focus background color - * - Default value: { LIGHT: 0.1, DARK: 0.2 } - */ - transparency: ColorModeSwitch; - /** - * Default focus background color. Not all components set a background color on focus - * - Default value: `colors.primary` computed with `focus.transparency` - */ - backgroundColor: ColorModeSwitch; -} +export type { _EuiThemeFocus } from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/global_styling/variables/typography.ts b/packages/eui/src/global_styling/variables/typography.ts index 80ebbc8b1cb..3792c40fe12 100644 --- a/packages/eui/src/global_styling/variables/typography.ts +++ b/packages/eui/src/global_styling/variables/typography.ts @@ -6,141 +6,17 @@ * Side Public License, v 1. */ -import { CSSProperties } from 'react'; - -/** - * Font units of measure - */ - -export const EuiThemeFontUnits = ['rem', 'px', 'em'] as const; - -export type _EuiThemeFontUnit = (typeof EuiThemeFontUnits)[number]; - -/* - * Font scale - */ - -export const EuiThemeFontScales = [ - 'xxxs', - 'xxs', - 'xs', - 's', - 'm', - 'l', - 'xl', - 'xxl', -] as const; - -export type _EuiThemeFontScale = (typeof EuiThemeFontScales)[number]; - -export type _EuiThemeFontScales = Record<_EuiThemeFontScale, number>; - -/* - * Font base settings - */ - -export type _EuiThemeFontBase = { - /** - * The whole font family stack for all parts of the UI. - * We encourage only customizing the first font in the stack. - */ - family: string; - /** - * The font family used for monospace UI elements like EuiCode - */ - familyCode?: string; - /** - * The font family used for serif UI elements like blockquotes within EuiText - */ - familySerif?: string; - /** - * Controls advanced features OpenType fonts. - * 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` - */ - baseline: number; - /** - * Establishes the ideal line-height percentage, but it is the `baseline` integer that establishes the final pixel/rem value - */ - lineHeightMultiplier: number; -}; - -/* - * Font weights - */ - -export const EuiThemeFontWeights = [ - 'light', - 'regular', - 'medium', - 'semiBold', - 'bold', -] as const; - -export type _EuiThemeFontWeight = (typeof EuiThemeFontWeights)[number]; - -export type _EuiThemeFontWeights = { - /** - Default value: 300 */ - light: CSSProperties['fontWeight']; - /** - Default value: 400 */ - regular: CSSProperties['fontWeight']; - /** - Default value: 500 */ - medium: CSSProperties['fontWeight']; - /** - Default value: 600 */ - semiBold: CSSProperties['fontWeight']; - /** - Default value: 700 */ - bold: CSSProperties['fontWeight']; -}; - -/** - * Body / Base styles - */ - -export interface _EuiThemeBody { - /** - * A sizing key from one of the font scales to set as the base body font-size - */ - scale: _EuiThemeFontScale; - /** - * A font weight key for setting the base body weight - */ - weight: keyof _EuiThemeFontWeights; -} - -/** - * Title styles - */ - -export interface _EuiThemeTitle { - /** - * A font weight key for setting the base weight for titles and headings - */ - weight: keyof _EuiThemeFontWeights; -} - -/* - * Font - */ - -export type _EuiThemeFont = _EuiThemeFontBase & { - scale: _EuiThemeFontScales; - /** - * @see {@link https://eui.elastic.co/#/theming/typography/values%23font-weight | Reference} for more information - */ - weight: _EuiThemeFontWeights; - body: _EuiThemeBody; - title: _EuiThemeTitle; -}; +export { + EuiThemeFontUnits, + EuiThemeFontScales, + EuiThemeFontWeights, + type _EuiThemeFontUnit, + type _EuiThemeFontScale, + type _EuiThemeFontScales, + type _EuiThemeFontBase, + type _EuiThemeFontWeight, + type _EuiThemeFontWeights, + type _EuiThemeBody, + type _EuiThemeTitle, + type _EuiThemeFont, +} from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/services/theme/types.ts b/packages/eui/src/services/theme/types.ts index 04b93b40f20..c4562b1ff92 100644 --- a/packages/eui/src/services/theme/types.ts +++ b/packages/eui/src/services/theme/types.ts @@ -5,104 +5,18 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - -import type { CSSObject } from '@emotion/react'; - -import { RecursivePartial, ValueOf } from '../../components/common'; -import { _EuiThemeAnimation } from '../../global_styling/variables/animations'; -import { _EuiThemeBreakpoints } from '../../global_styling/variables/breakpoint'; -import { _EuiThemeBorder } from '../../global_styling/variables/borders'; -import { _EuiThemeColors } from '../../global_styling/variables/colors'; -import { - _EuiThemeBase, - _EuiThemeSizes, -} from '../../global_styling/variables/size'; -import { _EuiThemeFont } from '../../global_styling/variables/typography'; -import { _EuiThemeFocus } from '../../global_styling/variables/states'; -import { _EuiThemeLevels } from '../../global_styling/variables/levels'; - -export const COLOR_MODES_STANDARD = { - light: 'LIGHT', - dark: 'DARK', -} as const; -export const COLOR_MODES_INVERSE = 'INVERSE' as const; - -export type EuiThemeColorModeInverse = typeof COLOR_MODES_INVERSE; -export type EuiThemeColorModeStandard = ValueOf; -export type EuiThemeColorMode = - | 'light' - | 'dark' - | EuiThemeColorModeStandard - | 'inverse' - | EuiThemeColorModeInverse; - -export type ColorModeSwitch = - | { - [key in EuiThemeColorModeStandard]: T; - } - | T; - -export type StrictColorModeSwitch = { - [key in EuiThemeColorModeStandard]: T; -}; - -export type EuiThemeShape = { - colors: _EuiThemeColors; - /** - Default value: 16 */ - base: _EuiThemeBase; - /** - * @see {@link https://eui.elastic.co/#/theming/sizing | Reference} for more information - */ - size: _EuiThemeSizes; - font: _EuiThemeFont; - border: _EuiThemeBorder; - focus: _EuiThemeFocus; - animation: _EuiThemeAnimation; - breakpoint: _EuiThemeBreakpoints; - levels: _EuiThemeLevels; -}; - -export type EuiThemeSystem = { - root: EuiThemeShape & T; - model: EuiThemeShape & T; - key: string; -}; - -export type EuiThemeModifications = RecursivePartial; - -export type ComputedThemeShape< - T, - P = string | number | bigint | boolean | null | undefined -> = T extends P | ColorModeSwitch - ? T extends ColorModeSwitch - ? X extends P - ? X - : { - [K in keyof (X & - Exclude< - T, - keyof X | keyof StrictColorModeSwitch - >)]: ComputedThemeShape< - (X & Exclude)[K], - P - >; - } - : T - : { - [K in keyof T]: ComputedThemeShape; - }; - -export type EuiThemeComputed = ComputedThemeShape & { - themeName: string; -}; - -export type EuiThemeNested = { - isGlobalTheme: boolean; - hasDifferentColorFromGlobalTheme: boolean; - bodyColor: string; - colorClassName: string; - setGlobalCSSVariables: Function; - globalCSSVariables?: CSSObject; - setNearestThemeCSSVariables: Function; - themeCSSVariables?: CSSObject; -}; +export { + COLOR_MODES_STANDARD, + COLOR_MODES_INVERSE, + type EuiThemeColorModeInverse, + type EuiThemeColorModeStandard, + type EuiThemeColorMode, + type ColorModeSwitch, + type StrictColorModeSwitch, + type EuiThemeShape, + type EuiThemeSystem, + type EuiThemeModifications, + type ComputedThemeShape, + type EuiThemeComputed, + type EuiThemeNested, +} from '@elastic/eui-theme-base'; diff --git a/packages/eui/src/services/theme/utils.test.ts b/packages/eui/src/services/theme/utils.test.ts deleted file mode 100644 index c654e4d3c22..00000000000 --- a/packages/eui/src/services/theme/utils.test.ts +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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 { - isInverseColorMode, - getColorMode, - getOn, - setOn, - computed, - Computed, - getComputed, - buildTheme, - mergeDeep, -} from './utils'; - -describe('isInverseColorMode', () => { - it("true only if 'inverse'", () => { - expect(isInverseColorMode('LIGHT')).toBe(false); - expect(isInverseColorMode('DARK')).toBe(false); - expect(isInverseColorMode('custom')).toBe(false); - expect(isInverseColorMode()).toBe(false); - expect(isInverseColorMode('INVERSE')).toBe(true); - }); -}); - -describe('getColorMode', () => { - it("defaults to 'LIGHT'", () => { - expect(getColorMode()).toEqual('LIGHT'); - }); - it('uses `parentMode` as fallback', () => { - expect(getColorMode(undefined, 'DARK')).toEqual('DARK'); - }); - it("understands 'INVERSE'", () => { - expect(getColorMode('INVERSE', 'DARK')).toEqual('LIGHT'); - expect(getColorMode('INVERSE', 'LIGHT')).toEqual('DARK'); - expect(getColorMode('INVERSE')).toEqual('LIGHT'); - }); -}); - -describe('getOn', () => { - const obj = { - parent: { - child: 'childVal', - }, - other: { - thing: { - string: 'stringVal', - nested: ['array'], - number: 0, - func: () => {}, - }, - }, - colors: { - LIGHT: { primary: '#000' }, - DARK: { primary: '#FFF' }, - }, - }; - it('gets values at the given path', () => { - expect(getOn(obj, 'parent')).toEqual({ - child: 'childVal', - }); - expect(getOn(obj, 'parent.child')).toEqual('childVal'); - expect(getOn(obj, 'other.thing.string')).toEqual('stringVal'); - }); - it('gets values of various kinds', () => { - expect(getOn(obj, 'other.thing.nested')).toEqual(['array']); - expect(getOn(obj, 'other.thing.number')).toEqual(0); - expect(getOn(obj, 'other.thing.func')).toBeInstanceOf(Function); - }); - it('can shortcut color modes', () => { - expect(getOn(obj, 'colors.primary', 'LIGHT')).toEqual('#000'); - expect(getOn(obj, 'colors.primary', 'DARK')).toEqual('#FFF'); - }); - it('will not error', () => { - expect(getOn(obj, 'nope')).toBe(undefined); - expect(getOn(obj, 'other.nope')).toBe(undefined); - expect(getOn(obj, 'other.thing.nope')).toBe(undefined); - }); -}); - -describe('setOn', () => { - let obj: {}; - beforeEach(() => { - obj = { - existing: { - nested: { - val: 'value', - }, - }, - }; - }); - it('sets values at the given path', () => { - setOn(obj, 'existing.new', 'value'); - expect(obj).toEqual({ - existing: { nested: { val: 'value' }, new: 'value' }, - }); - setOn(obj, 'existing.nested.new', 'value'); - expect(obj).toEqual({ - existing: { nested: { val: 'value', new: 'value' }, new: 'value' }, - }); - }); - it('deep arbitrary creation', () => { - setOn(obj, 'trail.blazing.happening.now', 'wow'); - expect(obj).toEqual({ - existing: { nested: { val: 'value' } }, - trail: { blazing: { happening: { now: 'wow' } } }, - }); - }); - it('overrides existing path value', () => { - setOn(obj, 'existing.nested', 'diff'); - expect(obj).toEqual({ - existing: { - nested: 'diff', - }, - }); - }); -}); - -describe('computed', () => { - it('should transform to Computed with dependencies array', () => { - const output = computed(([path]) => path, ['path.to']); - expect(output).toBeInstanceOf(Computed); - expect(output.computer).toBeInstanceOf(Function); - expect(output.dependencies).toEqual(['path.to']); - }); - it('should transform to Computed with single dependency', () => { - const output = computed((path) => path, 'path.to'); - expect(output).toBeInstanceOf(Computed); - expect(output.computer).toBeInstanceOf(Function); - expect(output.dependencies).toEqual('path.to'); - }); - it('should transform to Computed without dependencies array', () => { - const output = computed((path) => path); - expect(output).toBeInstanceOf(Computed); - }); -}); - -const theme = buildTheme( - { - colors: { - LIGHT: { - primary: '#000', - secondary: computed(([primary]) => `${primary}000`, ['colors.primary']), - }, - DARK: { - primary: '#FFF', - secondary: computed((theme) => `${theme.colors.primary}FFF`), - }, - }, - sizes: { - small: 8, - }, - }, - 'minimal' -); -describe('getComputed', () => { - it('computes all values and returns only the current color mode', () => { - // @ts-expect-error intentionally not using a full EUI theme definition - expect(getComputed(theme, {}, 'LIGHT')).toEqual({ - colors: { primary: '#000', secondary: '#000000' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - // @ts-expect-error intentionally not using a full EUI theme definition - expect(getComputed(theme, {}, 'DARK')).toEqual({ - colors: { primary: '#FFF', secondary: '#FFFFFF' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - }); - it('respects simple overrides', () => { - expect( - // @ts-expect-error intentionally not using a full EUI theme definition - getComputed(theme, buildTheme({ sizes: { small: 4 } }, ''), 'LIGHT') - ).toEqual({ - colors: { primary: '#000', secondary: '#000000' }, - sizes: { small: 4 }, - themeName: 'minimal', - }); - }); - it('respects overrides in computation', () => { - expect( - getComputed( - // @ts-expect-error intentionally not using a full EUI theme definition - theme, - buildTheme({ colors: { LIGHT: { primary: '#CCC' } } }, ''), - 'LIGHT' - ) - ).toEqual({ - colors: { primary: '#CCC', secondary: '#CCC000' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - }); - it('respects property extensions', () => { - expect( - getComputed( - // @ts-expect-error intentionally not using a full EUI theme definition - theme, - buildTheme({ colors: { LIGHT: { tertiary: '#333' } } }, ''), - 'LIGHT' - ) - ).toEqual({ - colors: { primary: '#000', secondary: '#000000', tertiary: '#333' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - }); - it('respects section extensions', () => { - expect( - getComputed( - // @ts-expect-error intentionally not using a full EUI theme definition - theme, - buildTheme({ custom: { myProp: '#333' } }, ''), - 'LIGHT' - ) - ).toEqual({ - colors: { primary: '#000', secondary: '#000000' }, - sizes: { small: 8 }, - custom: { myProp: '#333' }, - themeName: 'minimal', - }); - }); - it('respects extensions in computation', () => { - expect( - getComputed( - // @ts-expect-error intentionally not using a full EUI theme definition - theme, - buildTheme( - { - colors: { - LIGHT: { - tertiary: computed( - ([primary]) => `${primary}333`, - ['colors.primary'] - ), - }, - }, - }, - '' - ), - 'LIGHT' - ) - ).toEqual({ - colors: { primary: '#000', secondary: '#000000', tertiary: '#000333' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - }); -}); - -describe('buildTheme', () => { - it('builds an EUI theme system', () => { - // TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property 'length' which is either non-existant or configurable in the proxy target - // expect(theme).toEqual(Proxy); // get() trap returns theme.model - // expect(theme.root).toEqual(Proxy); - expect(theme.key).toEqual('minimal'); - }); -}); - -describe('mergeDeep', () => { - it('merge simple objects, second into first', () => { - expect(mergeDeep({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 }); - expect(mergeDeep({ a: 1 }, { a: 2 })).toEqual({ a: 2 }); - }); - it('merge complex objects, second into first', () => { - expect( - mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { d: 4 } } }) - ).toEqual({ a: 1, b: { c: { d: 4 } } }); - expect( - mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { e: 5 } } }) - ).toEqual({ a: 1, b: { c: { d: 3, e: 5 } } }); - }); -}); diff --git a/packages/eui/src/services/theme/utils.ts b/packages/eui/src/services/theme/utils.ts index 5cbb3c2281e..96ed31cdda5 100644 --- a/packages/eui/src/services/theme/utils.ts +++ b/packages/eui/src/services/theme/utils.ts @@ -6,387 +6,15 @@ * Side Public License, v 1. */ -import { - EuiThemeColorMode, - EuiThemeColorModeInverse, - EuiThemeColorModeStandard, - EuiThemeModifications, - EuiThemeSystem, - EuiThemeShape, - EuiThemeComputed, - COLOR_MODES_STANDARD, - COLOR_MODES_INVERSE, -} from './types'; - -export const DEFAULT_COLOR_MODE = COLOR_MODES_STANDARD.light; - -/** - * Returns whether the parameter is an object - * @param {any} obj - Anything - */ -const isObject = (obj: any) => obj && typeof obj === 'object'; - -/** - * Returns whether the provided color mode is `inverse` - * @param {string} colorMode - `light`, `dark`, or `inverse` - */ -export const isInverseColorMode = ( - colorMode?: string -): colorMode is EuiThemeColorModeInverse => { - return colorMode === COLOR_MODES_INVERSE; -}; - -/** - * Returns the color mode configured in the current EuiThemeProvider. - * Returns the parent color mode if none is explicity set. - * @param {string} colorMode - `light`, `dark`, or `inverse` - * @param {string} parentColorMode - `LIGHT` or `DARK`; used as the fallback - */ -export const getColorMode = ( - colorMode?: EuiThemeColorMode, - parentColorMode?: EuiThemeColorModeStandard -): EuiThemeColorModeStandard => { - if (colorMode == null) { - return parentColorMode || DEFAULT_COLOR_MODE; - } - const mode = colorMode.toUpperCase() as - | EuiThemeColorModeInverse - | EuiThemeColorModeStandard; - if (isInverseColorMode(mode)) { - return parentColorMode === COLOR_MODES_STANDARD.dark || - parentColorMode === undefined - ? COLOR_MODES_STANDARD.light - : COLOR_MODES_STANDARD.dark; - } else { - return mode; - } -}; - -/** - * Returns a value at a given path on an object. - * If `colorMode` is provided, will scope the value to the appropriate color mode key (LIGHT\DARK) - * @param {object} model - Object - * @param {string} _path - Dot-notated string to a path on the object - * @param {string} colorMode - `light` or `dark` - */ -export const getOn = ( - model: { [key: string]: any }, - _path: string, - colorMode?: EuiThemeColorModeStandard -) => { - const path = _path.split('.'); - let node = model; - while (path.length) { - const segment = path.shift()!; - - if (node.hasOwnProperty(segment) === false) { - if ( - colorMode && - node.hasOwnProperty(colorMode) === true && - node[colorMode].hasOwnProperty(segment) === true - ) { - if (node[colorMode][segment] instanceof Computed) { - node = node[colorMode][segment].getValue(null, null, node, colorMode); - } else { - node = node[colorMode][segment]; - } - } else { - return undefined; - } - } else { - if (node[segment] instanceof Computed) { - node = node[segment].getValue(null, null, node, colorMode); - } else { - node = node[segment]; - } - } - } - - return node; -}; - -/** - * Sets a value at a given path on an object. - * @param {object} model - Object - * @param {string} _path - Dot-notated string to a path on the object - * @param {any} string - The value to set - */ -export const setOn = ( - model: { [key: string]: any }, - _path: string, - value: any -) => { - const path = _path.split('.'); - const propertyName = path.pop()!; - let node = model; - - while (path.length) { - const segment = path.shift()!; - if (node.hasOwnProperty(segment) === false) { - node[segment] = {}; - } - node = node[segment]; - } - - node[propertyName] = value; - return true; -}; - -/** - * Creates a class to store the `computer` method and its eventual parameters. - * Allows for on-demand computation with up-to-date parameters via `getValue` method. - * @constructor - * @param {function} computer - Function to be computed - * @param {string | array} dependencies - Dependencies passed to the `computer` as parameters - */ -export class Computed { - constructor( - public computer: (...values: any[]) => T, - public dependencies: string | string[] = [] - ) {} - - /** - * Executes the `computer` method with the current state of the theme - * by taking into account previously computed values and modifications. - * @param {Proxy | object} base - Computed or uncomputed theme - * @param {Proxy | object} modifications - Theme value overrides - * @param {object} working - Partially computed theme - * @param {string} colorMode - `light` or `dark` - */ - getValue( - base: EuiThemeSystem | EuiThemeShape, - modifications: EuiThemeModifications = {}, - working: EuiThemeComputed, - colorMode: EuiThemeColorModeStandard - ) { - if (!this.dependencies.length) { - return this.computer(working); - } - if (!Array.isArray(this.dependencies)) { - return this.computer( - getOn(working, this.dependencies) ?? - getOn(modifications, this.dependencies, colorMode) ?? - getOn(base, this.dependencies, colorMode) - ); - } - return this.computer( - this.dependencies.map((dependency) => { - return ( - getOn(working, dependency) ?? - getOn(modifications, dependency, colorMode) ?? - getOn(base, dependency, colorMode) - ); - }) - ); - } -} - -/** - * Returns a Class (`Computed`) that stores the arbitrary computer method - * and references to its optional dependecies. - * @param {function} computer - Arbitrary method to be called at compute time. - * @param {string | array} dependencies - Values that will be provided to `computer` at compute time. - */ -export function computed(computer: (value: EuiThemeComputed) => T): T; -export function computed( - computer: (value: any[]) => T, - dependencies: string[] -): T; -export function computed( - computer: (value: any) => T, - dependencies: string -): T; -export function computed( - comp: ((value: T) => T) | ((value: any) => T) | ((value: any[]) => T), - dep?: string | string[] -) { - return new Computed(comp, dep); -} - -/** - * Type guard to check for a Computed object based on object shape - * without relying on the Computed class directly - */ -const isComputedLike = (key: object): key is Computed => { - if (typeof key !== 'object' || Array.isArray(key)) return false; - - return key.hasOwnProperty('dependencies') && key.hasOwnProperty('computer'); -}; - -/** - * Takes an uncomputed theme, and computes and returns all values taking - * into consideration value overrides and configured color mode. - * Overrides take precedence, and only values in the current color mode - * are computed and returned. - * @param {Proxy} base - Object to transform into Proxy - * @param {Proxy | object} over - Unique identifier or name - * @param {string} colorMode - `light` or `dark` - */ -export const getComputed = ( - base: EuiThemeSystem, - over: Partial>, - colorMode: EuiThemeColorModeStandard -): EuiThemeComputed => { - const output: Partial = { themeName: base.key }; - - function loop( - base: { [key: string]: any }, - over: { [key: string]: any }, - checkExisting: boolean = false, - path?: string - ) { - Object.keys(base).forEach((key) => { - let newPath = path ? `${path}.${key}` : `${key}`; - // @ts-expect-error `key` is not necessarily a colorMode key - if ([...Object.values(COLOR_MODES_STANDARD), colorMode].includes(key)) { - if (key !== colorMode) { - return; - } else { - const colorModeSegment = new RegExp( - `(\\.${colorMode}\\b)|(\\b${colorMode}\\.)` - ); - newPath = newPath.replace(colorModeSegment, ''); - } - } - const existing = checkExisting && getOn(output, newPath); - if (!existing || isObject(existing)) { - // NOTE: the class type check for Computed is not true for themes created externally; - // we additionally check on the object shape to confirm a Computed value - const baseValue = - base[key] instanceof Computed || isComputedLike(base[key]) - ? base[key].getValue(base.root, over.root, output, colorMode) - : base[key]; - const overValue = - over[key] instanceof Computed || isComputedLike(over[key]) - ? over[key].getValue(base.root, over.root, output, colorMode) - : over[key]; - if (isObject(baseValue) && !Array.isArray(baseValue)) { - loop(baseValue, overValue ?? {}, checkExisting, newPath); - } else { - setOn(output, newPath, overValue ?? baseValue); - } - } - }); - } - // Compute standard theme values and apply overrides - loop(base, over); - // Compute and apply extension values only - loop(over, {}, true); - return output as EuiThemeComputed; -}; - -/** - * Builds a Proxy with a custom `handler` designed to self-reference values - * and prevent arbitrary value overrides. - * @param {object} model - Object to transform into Proxy - * @param {string} key - Unique identifier or name - */ -export const buildTheme = (model: T, key: string) => { - const handler: ProxyHandler> = { - getPrototypeOf(target) { - return Reflect.getPrototypeOf(target.model); - }, - - setPrototypeOf(target, prototype) { - return Reflect.setPrototypeOf(target.model, prototype); - }, - - isExtensible(target) { - return Reflect.isExtensible(target); - }, - - preventExtensions(target) { - return Reflect.preventExtensions(target.model); - }, - - getOwnPropertyDescriptor(target, key) { - return Reflect.getOwnPropertyDescriptor(target.model, key); - }, - - defineProperty(target, property, attributes) { - return Reflect.defineProperty(target.model, property, attributes); - }, - - has(target, property) { - return Reflect.has(target.model, property); - }, - - get(_target, property) { - if (property === 'key') { - return _target[property]; - } - - // prevent Safari from locking up when the proxy is used in dev tools - // as it doesn't support getPrototypeOf - if (property === '__proto__') return {}; - - const target = property === 'root' ? _target : _target.model || _target; - // @ts-ignore `string` index signature - const value = target[property]; - if (isObject(value) && !Array.isArray(value)) { - return new Proxy( - { - model: value, - root: _target.root, - key: `_${_target.key}`, - }, - handler - ); - } else { - return value; - } - }, - - set(target: any) { - return target; - }, - - deleteProperty(target: any) { - return target; - }, - - ownKeys(target) { - return Reflect.ownKeys(target.model); - }, - - apply(target: any) { - return target; - }, - - construct(target: any) { - return target; - }, - }; - const themeProxy = new Proxy({ model, root: model, key }, handler); - - return themeProxy; -}; - -/** - * Deeply merges two objects, using `source` values whenever possible. - * @param {object} _target - Object with fallback values - * @param {object} source - Object with desired values - */ -export const mergeDeep = ( - _target: { [key: string]: any }, - source: { [key: string]: any } = {} -) => { - const target = { ..._target }; - - if (!isObject(target) || !isObject(source)) { - return source; - } - - Object.keys(source).forEach((key) => { - const targetValue = target[key]; - const sourceValue = source[key]; - - if (isObject(targetValue) && isObject(sourceValue)) { - target[key] = mergeDeep({ ...targetValue }, { ...sourceValue }); - } else { - target[key] = sourceValue; - } - }); - - return target; -}; +export { + DEFAULT_COLOR_MODE, + isInverseColorMode, + getColorMode, + getOn, + setOn, + Computed, + computed, + getComputed, + buildTheme, + mergeDeep, +} from '@elastic/eui-theme-base'; From 03b49f3819b3c8ae785c7f118bcfd7aed38ced72 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Sun, 22 Sep 2024 16:03:18 +0200 Subject: [PATCH 11/32] refactor: use eui-theme-base package in eui-theme-berlin -removes circle dependency on main eui --- packages/docusaurus-theme/package.json | 1 + packages/eui-theme-berlin/LICENSE.txt | 6 ++ packages/eui-theme-berlin/package.json | 64 ++++++++++--------- packages/eui-theme-berlin/src/index.ts | 2 +- .../src/variables/_animation.ts | 2 +- .../src/variables/_borders.ts | 3 +- .../src/variables/_breakpoint.ts | 2 +- .../eui-theme-berlin/src/variables/_colors.ts | 2 +- .../src/variables/_colors_dark.ts | 29 ++++----- .../src/variables/_colors_light.ts | 34 +++++----- .../eui-theme-berlin/src/variables/_levels.ts | 2 +- .../eui-theme-berlin/src/variables/_size.ts | 4 +- .../eui-theme-berlin/src/variables/_states.ts | 12 +--- .../src/variables/_typography.ts | 4 +- 14 files changed, 80 insertions(+), 87 deletions(-) create mode 100644 packages/eui-theme-berlin/LICENSE.txt diff --git a/packages/docusaurus-theme/package.json b/packages/docusaurus-theme/package.json index 5cfa3eece4e..91e0be85cf7 100644 --- a/packages/docusaurus-theme/package.json +++ b/packages/docusaurus-theme/package.json @@ -36,6 +36,7 @@ "@elastic/datemath": "^5.0.3", "@elastic/eui": "workspace:^", "@elastic/eui-docgen": "workspace:^", + "@elastic/eui-theme-berlin": "workspace:^", "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.4", "@types/react-window": "^1.8.8", diff --git a/packages/eui-theme-berlin/LICENSE.txt b/packages/eui-theme-berlin/LICENSE.txt new file mode 100644 index 00000000000..74327a8f6f3 --- /dev/null +++ b/packages/eui-theme-berlin/LICENSE.txt @@ -0,0 +1,6 @@ +Source code in this repository is covered by (i) a dual license under the Server +Side Public License, v 1 and the Elastic License 2.0 or (ii) an Apache License +2.0 compatible license or (iii) solely under the Elastic License 2.0, in each +case, as noted in the applicable header. The default throughout the repository +is a dual license under the Server Side Public License, v 1 and the Elastic +License 2.0, unless the header specifies another license. diff --git a/packages/eui-theme-berlin/package.json b/packages/eui-theme-berlin/package.json index 9bb3b25452f..6260b270f56 100644 --- a/packages/eui-theme-berlin/package.json +++ b/packages/eui-theme-berlin/package.json @@ -1,33 +1,35 @@ { - "name": "@elastic/eui-theme-berlin", - "version": "0.0.1", - "description": "A visual theme for EUI", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc", - "build-pack": "yarn build && npm pack" - }, - "repository": { - "type": "git", - "url": "https://github.com/elastic/eui.git", - "directory": "packages/eui-theme-berlin" - }, - "private": true, - "devDependencies": { - "typescript": "^5.6.2" - }, - "peerDependencies": { - "@elastic/eui": "^95.10.1" - }, - "main": "lib/index.js", - "exports": { - "./lib/*": "./lib/*", - ".": { - "default": "./lib/index.js" - } - }, - "files": [ - "lib/", - "README.md" - ] + "name": "@elastic/eui-theme-berlin", + "version": "0.0.1", + "description": "A visual theme for EUI", + "license": "SEE LICENSE IN LICENSE.txt", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc", + "build-pack": "yarn build && npm pack" + }, + "repository": { + "type": "git", + "url": "https://github.com/elastic/eui.git", + "directory": "packages/eui-theme-berlin" + }, + "private": true, + "dependencies": { + "@elastic/eui-common": "workspace:^", + "@elastic/eui-theme-base": "workspace:^" + }, + "devDependencies": { + "typescript": "^5.6.2" + }, + "main": "lib/index.js", + "exports": { + "./lib/*": "./lib/*", + ".": { + "default": "./lib/index.js" + } + }, + "files": [ + "lib/", + "README.md" + ] } diff --git a/packages/eui-theme-berlin/src/index.ts b/packages/eui-theme-berlin/src/index.ts index ac63b734c3a..c9884f5e7e7 100644 --- a/packages/eui-theme-berlin/src/index.ts +++ b/packages/eui-theme-berlin/src/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { buildTheme, EuiThemeShape } from '@elastic/eui'; +import { buildTheme, EuiThemeShape } from '@elastic/eui-theme-base'; import { colors } from './variables/_colors'; import { animation } from './variables/_animation'; diff --git a/packages/eui-theme-berlin/src/variables/_animation.ts b/packages/eui-theme-berlin/src/variables/_animation.ts index 7f8dfd998fd..e6c52bdaef0 100644 --- a/packages/eui-theme-berlin/src/variables/_animation.ts +++ b/packages/eui-theme-berlin/src/variables/_animation.ts @@ -10,7 +10,7 @@ import type { _EuiThemeAnimationSpeeds, _EuiThemeAnimationEasings, _EuiThemeAnimation, -} from '@elastic/eui'; +} from '@elastic/eui-theme-base'; export const animation_speed: _EuiThemeAnimationSpeeds = { extraFast: '90ms', diff --git a/packages/eui-theme-berlin/src/variables/_borders.ts b/packages/eui-theme-berlin/src/variables/_borders.ts index 8bddcf1364a..19639073715 100644 --- a/packages/eui-theme-berlin/src/variables/_borders.ts +++ b/packages/eui-theme-berlin/src/variables/_borders.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import { computed, sizeToPixel, type _EuiThemeBorder } from '@elastic/eui'; +import { computed, type _EuiThemeBorder } from '@elastic/eui-theme-base'; +import { sizeToPixel } from '@elastic/eui-common'; export const border: _EuiThemeBorder = { color: computed(([lightShade]) => lightShade, ['colors.lightShade']), diff --git a/packages/eui-theme-berlin/src/variables/_breakpoint.ts b/packages/eui-theme-berlin/src/variables/_breakpoint.ts index 503aba80aed..2b39afe5351 100644 --- a/packages/eui-theme-berlin/src/variables/_breakpoint.ts +++ b/packages/eui-theme-berlin/src/variables/_breakpoint.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { _EuiThemeBreakpoints } from '@elastic/eui'; +import type { _EuiThemeBreakpoints } from '@elastic/eui-theme-base'; export const breakpoint: _EuiThemeBreakpoints = { xl: 1200, diff --git a/packages/eui-theme-berlin/src/variables/_colors.ts b/packages/eui-theme-berlin/src/variables/_colors.ts index ebd13918486..f42e381dde0 100644 --- a/packages/eui-theme-berlin/src/variables/_colors.ts +++ b/packages/eui-theme-berlin/src/variables/_colors.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { _EuiThemeColors } from '@elastic/eui'; +import type { _EuiThemeColors } from '@elastic/eui-theme-base'; import { light_colors } from './_colors_light'; import { dark_colors } from './_colors_dark'; diff --git a/packages/eui-theme-berlin/src/variables/_colors_dark.ts b/packages/eui-theme-berlin/src/variables/_colors_dark.ts index 37961eeee41..b1586e837f8 100644 --- a/packages/eui-theme-berlin/src/variables/_colors_dark.ts +++ b/packages/eui-theme-berlin/src/variables/_colors_dark.ts @@ -8,10 +8,6 @@ import { computed, - makeHighContrastColor, - makeDisabledContrastColor, - shade, - tint, type _EuiThemeColors, type _EuiThemeBrandColors, type _EuiThemeBrandTextColors, @@ -19,14 +15,14 @@ import { type _EuiThemeSpecialColors, type _EuiThemeTextColors, type _EuiThemeColorsMode, -} from '@elastic/eui'; +} from '@elastic/eui-theme-base'; /* * DARK THEME */ export const dark_brand_colors: _EuiThemeBrandColors = { - primary: '#36A2EF', + primary: '#00aa00', // test color for distinction accent: '#F68FBE', success: '#7DDED8', warning: '#F3D371', @@ -34,11 +30,12 @@ export const dark_brand_colors: _EuiThemeBrandColors = { }; export const dark_brand_text_colors: _EuiThemeBrandTextColors = { - primaryText: computed(makeHighContrastColor('colors.primary')), - accentText: computed(makeHighContrastColor('colors.accent')), - successText: computed(makeHighContrastColor('colors.success')), - warningText: computed(makeHighContrastColor('colors.warning')), - dangerText: computed(makeHighContrastColor('colors.danger')), + // temp. static values to remove dependency on makeHighContrastColor + primaryText: '#36a2ef', + accentText: '#f68fbe', + successText: '#7dded8', + warningText: '#f3d371', + dangerText: '#f86b63', }; export const dark_shades: _EuiThemeShadeColors = { @@ -52,20 +49,18 @@ export const dark_shades: _EuiThemeShadeColors = { }; export const dark_special_colors: _EuiThemeSpecialColors = { - body: computed( - ([lightestShade]) => shade(lightestShade, 0.45), - ['colors.lightestShade'] - ), + // temp. static values to remove dependency on shade and makeDisabledContrastColor + body: '#141519', highlight: '#2E2D25', disabled: '#515761', - disabledText: computed(makeDisabledContrastColor('colors.disabled')), + disabledText: '#515761', shadow: computed(({ colors }) => colors.ink), }; export const dark_text_colors: _EuiThemeTextColors = { text: '#DFE5EF', title: computed(([text]) => text, ['colors.text']), - subduedText: computed(makeHighContrastColor('colors.mediumShade')), + subduedText: '#81858f', // temp. static value to remove dependency makeDisabledContrastColor link: computed(([primaryText]) => primaryText, ['colors.primaryText']), }; diff --git a/packages/eui-theme-berlin/src/variables/_colors_light.ts b/packages/eui-theme-berlin/src/variables/_colors_light.ts index d3411be74db..7d6a8124156 100644 --- a/packages/eui-theme-berlin/src/variables/_colors_light.ts +++ b/packages/eui-theme-berlin/src/variables/_colors_light.ts @@ -8,10 +8,6 @@ import { computed, - makeHighContrastColor, - makeDisabledContrastColor, - shade, - tint, type _EuiThemeColors, type _EuiThemeBrandColors, type _EuiThemeBrandTextColors, @@ -19,14 +15,14 @@ import { type _EuiThemeSpecialColors, type _EuiThemeTextColors, type _EuiThemeColorsMode, -} from '@elastic/eui'; +} from '@elastic/eui-theme-base'; /* * LIGHT THEME */ export const brand_colors: _EuiThemeBrandColors = { - primary: '#07C', + primary: '#00ff00', // test color for distinction accent: '#F04E98', success: '#00BFB3', warning: '#FEC514', @@ -34,11 +30,12 @@ export const brand_colors: _EuiThemeBrandColors = { }; export const brand_text_colors: _EuiThemeBrandTextColors = { - primaryText: computed(makeHighContrastColor('colors.primary')), - accentText: computed(makeHighContrastColor('colors.accent')), - successText: computed(makeHighContrastColor('colors.success')), - warningText: computed(makeHighContrastColor('colors.warning')), - dangerText: computed(makeHighContrastColor('colors.danger')), + // temp. static values to remove dependency on makeHighContrastColor + primaryText: '#006bb8', + accentText: '#ba3d76', + successText: '#00BFB3', + warningText: '#83650a', + dangerText: '#bd271e', }; export const shade_colors: _EuiThemeShadeColors = { @@ -52,20 +49,19 @@ export const shade_colors: _EuiThemeShadeColors = { }; export const special_colors: _EuiThemeSpecialColors = { - body: computed( - ([lightestShade]) => tint(lightestShade, 0.4), - ['colors.lightestShade'] - ), - highlight: computed(([warning]) => tint(warning, 0.9), ['colors.warning']), + // temp. static values to remove dependency on tint and makeDisabledContrastColor + body: '#f7f8fc', + highlight: '#fff9e8', disabled: '#ABB4C4', - disabledText: computed(makeDisabledContrastColor('colors.disabled')), + disabledText: '#a2abba', shadow: computed(({ colors }) => colors.ink), }; export const text_colors: _EuiThemeTextColors = { text: computed(([darkestShade]) => darkestShade, ['colors.darkestShade']), - title: computed(([text]) => shade(text, 0.5), ['colors.text']), - subduedText: computed(makeHighContrastColor('colors.darkShade')), + // temp. static values to remove dependency on tint and makeDisabledContrastColor + title: '#1a1c21', + subduedText: '#646a77', link: computed(([primaryText]) => primaryText, ['colors.primaryText']), }; diff --git a/packages/eui-theme-berlin/src/variables/_levels.ts b/packages/eui-theme-berlin/src/variables/_levels.ts index ea1ca2e0a03..94a26288967 100644 --- a/packages/eui-theme-berlin/src/variables/_levels.ts +++ b/packages/eui-theme-berlin/src/variables/_levels.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { _EuiThemeLevels } from '@elastic/eui'; +import type { _EuiThemeLevels } from '@elastic/eui-theme-base'; export const levels: _EuiThemeLevels = { toast: 9000, diff --git a/packages/eui-theme-berlin/src/variables/_size.ts b/packages/eui-theme-berlin/src/variables/_size.ts index 9ccb4736965..6982ef4af39 100644 --- a/packages/eui-theme-berlin/src/variables/_size.ts +++ b/packages/eui-theme-berlin/src/variables/_size.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ +import { sizeToPixel } from '@elastic/eui-common'; import { computed, - sizeToPixel, type _EuiThemeBase, type _EuiThemeSizes, -} from '@elastic/eui'; +} from '@elastic/eui-theme-base'; export const base: _EuiThemeBase = 16; diff --git a/packages/eui-theme-berlin/src/variables/_states.ts b/packages/eui-theme-berlin/src/variables/_states.ts index 757ece4cc4b..2ffe0e84efe 100644 --- a/packages/eui-theme-berlin/src/variables/_states.ts +++ b/packages/eui-theme-berlin/src/variables/_states.ts @@ -6,12 +6,8 @@ * Side Public License, v 1. */ -import { - computed, - transparentize, - sizeToPixel, - type _EuiThemeFocus, -} from '@elastic/eui'; +import { sizeToPixel } from '@elastic/eui-common'; +import { computed, type _EuiThemeFocus } from '@elastic/eui-theme-base'; export const focus: _EuiThemeFocus = { // Focus ring @@ -19,7 +15,5 @@ export const focus: _EuiThemeFocus = { width: computed(sizeToPixel(0.125)), // Focus background transparency: { LIGHT: 0.1, DARK: 0.2 }, - backgroundColor: computed(({ colors, focus }) => - transparentize(colors.primary, focus.transparency) - ), + backgroundColor: 'rgba(0, 119, 204, 0.1)', // temp. static value to remove dependency on transparentize }; diff --git a/packages/eui-theme-berlin/src/variables/_typography.ts b/packages/eui-theme-berlin/src/variables/_typography.ts index 4a7535acb5f..7d27fe803f3 100644 --- a/packages/eui-theme-berlin/src/variables/_typography.ts +++ b/packages/eui-theme-berlin/src/variables/_typography.ts @@ -12,9 +12,7 @@ import { type _EuiThemeFontBase, type _EuiThemeFontScales, type _EuiThemeFontWeights, -} from '@elastic/eui'; - -// import { computed } from '../../../eui/src/services/theme/utils'; +} from '@elastic/eui-theme-base'; // Typographic scale -- loosely based on Major Third (1.250) export const fontScale: _EuiThemeFontScales = { From 8c9ca71f0cf35a498fb0897e4a999196a9376ee8 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Sun, 22 Sep 2024 16:03:32 +0200 Subject: [PATCH 12/32] build: prevent generating i18ntokens.json when running build locally --- packages/eui/package.json | 2 +- packages/eui/scripts/compile-i18n-strings.js | 26 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 packages/eui/scripts/compile-i18n-strings.js diff --git a/packages/eui/package.json b/packages/eui/package.json index 8e568fde537..20939391baa 100644 --- a/packages/eui/package.json +++ b/packages/eui/package.json @@ -17,7 +17,7 @@ "scripts": { "start": "cross-env BABEL_MODULES=false webpack serve --config=src-docs/webpack.config.js", "build-docs": "cross-env BABEL_MODULES=false cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 webpack --config=src-docs/webpack.config.js", - "build": "yarn extract-i18n-strings && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && yarn compile-scss", + "build": "node ./scripts/compile-i18n-strings.js && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && yarn compile-scss", "build-pack": "yarn build && npm pack", "compile-icons": "node ./scripts/compile-icons.js && prettier --write --loglevel=warn \"./src/components/icon/assets/**/*.tsx\"", "compile-scss": "node ./scripts/compile-scss.js", diff --git a/packages/eui/scripts/compile-i18n-strings.js b/packages/eui/scripts/compile-i18n-strings.js new file mode 100644 index 00000000000..f948577d2fd --- /dev/null +++ b/packages/eui/scripts/compile-i18n-strings.js @@ -0,0 +1,26 @@ +/* + * 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. + */ + +const { execSync } = require('child_process'); +const chalk = require('chalk'); +const yargs = require('yargs/yargs'); +const { hideBin } = require('yargs/helpers'); + +const { NODE_ENV } = process.env; + +const info = chalk.white; +const log = chalk.grey; + +if (NODE_ENV !== 'production') return; + +const command = 'yarn extract-i18n-strings'; + +console.log(log(command)); +execSync(command, { + stdio: 'inherit', +}); From 89e722c922772dea438067f9230286641bea6c38 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 23 Sep 2024 09:28:17 +0200 Subject: [PATCH 13/32] build: add esm and cjs export for common module --- packages/eui-common/.babelrc.js | 27 +++++++++++++++++++++++ packages/eui-common/package.json | 18 ++++++++++++--- packages/eui-common/tsconfig.cjs.json | 29 +++++++++++++++++++++++++ packages/eui-common/tsconfig.json | 5 +++-- packages/eui-common/tsconfig.types.json | 13 +++++++++++ yarn.lock | 14 +++++++++++- 6 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 packages/eui-common/.babelrc.js create mode 100644 packages/eui-common/tsconfig.cjs.json create mode 100644 packages/eui-common/tsconfig.types.json diff --git a/packages/eui-common/.babelrc.js b/packages/eui-common/.babelrc.js new file mode 100644 index 00000000000..0fc74dd1fe9 --- /dev/null +++ b/packages/eui-common/.babelrc.js @@ -0,0 +1,27 @@ +module.exports = { + // We need to preserve comments as they are used by webpack for + // naming chunks during code-splitting. The compression step during + // bundling will remove them later. + comments: true, + + presets: [ + [ + '@babel/env', + { + // `targets` property set via `.browserslistrc` + useBuiltIns: process.env.NO_COREJS_POLYFILL ? false : 'usage', + corejs: !process.env.NO_COREJS_POLYFILL ? '3.6' : undefined, + modules: process.env.BABEL_MODULES + ? process.env.BABEL_MODULES === 'false' + ? false + : process.env.BABEL_MODULES + : 'commonjs', // babel's default is commonjs + }, + ], + ['@babel/react', { runtime: 'classic' }], + [ + '@babel/typescript', + { isTSX: true, allExtensions: true, allowDeclareFields: true }, + ], + ], +}; diff --git a/packages/eui-common/package.json b/packages/eui-common/package.json index 5ea8a9a5e9c..3304718b1c2 100644 --- a/packages/eui-common/package.json +++ b/packages/eui-common/package.json @@ -4,7 +4,11 @@ "description": "Common shared EUI functionality", "license": "SEE LICENSE IN LICENSE.txt", "scripts": { - "build": "tsc", + "build:clean": "rimraf lib", + "build": "yarn build:clean && yarn build:compile && yarn build:compile:cjs && yarn build:types", + "build:compile": "tsc --project tsconfig.json", + "build:compile:cjs": "NODE_ENV=production babel src --out-dir=lib/cjs --verbose --extensions .js,.ts,.tsx --source-maps", + "build:types": "NODE_ENV=production tsc --project tsconfig.types.json", "lint": "yarn tsc --noEmit && yarn lint-es", "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", "test": "jest" @@ -16,6 +20,11 @@ }, "private": true, "devDependencies": { + "@babel/cli": "^7.21.5", + "@babel/core": "^7.21.8", + "@babel/preset-env": "^7.21.5", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.5", "@types/jest": "^29.5.12", "@types/prettier": "2.7.3", "@typescript-eslint/eslint-plugin": "^5.59.7", @@ -28,14 +37,17 @@ "eslint-plugin-prettier": "^4.2.1", "jest": "^29.7.0", "prettier": "^2.8.8", + "rimraf": "^6.0.1", "typescript": "^5.6.2" }, - "main": "lib/index.js", + "main": "src/index.ts", "exports": { "./lib/*": "./lib/*", "./scripts/*": "./scripts/*", ".": { - "default": "./lib/index.js" + "require": "./lib/cjs/index.js", + "import": "./lib/esm/index.js", + "default": "./lib/esm/index.js" } }, "files": [ diff --git a/packages/eui-common/tsconfig.cjs.json b/packages/eui-common/tsconfig.cjs.json new file mode 100644 index 00000000000..6becea42efa --- /dev/null +++ b/packages/eui-common/tsconfig.cjs.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib/cjs", + "target": "es6", + "module": "CommonJS", + "lib": [ + "es6", + "DOM" + ], + "moduleResolution": "Node", + "declaration": true, + "sourceMap": true, + "noEmitHelpers": true, + "incremental": true, + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "tsBuildInfoFile": "lib/cjs/.tsbuildinfo", + "importHelpers": false, + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules" + ], +} \ No newline at end of file diff --git a/packages/eui-common/tsconfig.json b/packages/eui-common/tsconfig.json index c3190be619a..055614f8c47 100644 --- a/packages/eui-common/tsconfig.json +++ b/packages/eui-common/tsconfig.json @@ -2,8 +2,9 @@ "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { "rootDir": "src", - "outDir": "lib", + "outDir": "lib/esm", "target": "ES2020", + "module": "ESNext", "lib": [ "ESNext", "DOM" @@ -16,7 +17,7 @@ "esModuleInterop": true, "strict": true, "skipLibCheck": true, - "tsBuildInfoFile": "lib/.tsbuildinfo" + "tsBuildInfoFile": "lib/esm/.tsbuildinfo" }, "include": [ "src" diff --git a/packages/eui-common/tsconfig.types.json b/packages/eui-common/tsconfig.types.json new file mode 100644 index 00000000000..54e2031daae --- /dev/null +++ b/packages/eui-common/tsconfig.types.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.cjs.json", + "compilerOptions": { + "outDir": "lib/cjs", + "declaration": true, + "declarationMap": true, + "isolatedModules": false, + "noEmit": false, + "allowJs": false, + "emitDeclarationOnly": true + }, + "exclude": ["node_modules", "**/*.test.ts"] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 442b2ef4c5b..245f66b7f4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5700,6 +5700,11 @@ __metadata: version: 0.0.0-use.local resolution: "@elastic/eui-common@workspace:packages/eui-common" dependencies: + "@babel/cli": "npm:^7.21.5" + "@babel/core": "npm:^7.21.8" + "@babel/preset-env": "npm:^7.21.5" + "@babel/preset-react": "npm:^7.18.6" + "@babel/preset-typescript": "npm:^7.21.5" "@types/jest": "npm:^29.5.12" "@types/prettier": "npm:2.7.3" "@typescript-eslint/eslint-plugin": "npm:^5.59.7" @@ -5712,6 +5717,7 @@ __metadata: eslint-plugin-prettier: "npm:^4.2.1" jest: "npm:^29.7.0" prettier: "npm:^2.8.8" + rimraf: "npm:^6.0.1" typescript: "npm:^5.6.2" languageName: unknown linkType: soft @@ -5773,6 +5779,11 @@ __metadata: version: 0.0.0-use.local resolution: "@elastic/eui-theme-base@workspace:packages/eui-theme-base" dependencies: + "@babel/cli": "npm:^7.21.5" + "@babel/core": "npm:^7.21.8" + "@babel/preset-env": "npm:^7.21.5" + "@babel/preset-react": "npm:^7.18.6" + "@babel/preset-typescript": "npm:^7.21.5" "@elastic/eui-common": "workspace:^" "@types/jest": "npm:^29.5.12" "@types/prettier": "npm:2.7.3" @@ -5786,11 +5797,12 @@ __metadata: eslint-plugin-prettier: "npm:^4.2.1" jest: "npm:^29.7.0" prettier: "npm:^2.8.8" + rimraf: "npm:^6.0.1" stylelint: "npm:^15.7.0" stylelint-config-prettier-scss: "npm:^1.0.0" stylelint-config-standard: "npm:^33.0.0" stylelint-config-standard-scss: "npm:^9.0.0" - typescript: "npm:^5.6.2" + typescript: "npm:4.5.3" languageName: unknown linkType: soft From d481fb140ebbe9aa7d54434b771112c552580da8 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 23 Sep 2024 09:28:35 +0200 Subject: [PATCH 14/32] build: add esm and cjs export for theme-base module --- packages/eui-theme-base/.babelrc.js | 27 +++++++++++++++++++ packages/eui-theme-base/package.json | 20 +++++++++++--- packages/eui-theme-base/tsconfig.cjs.json | 29 +++++++++++++++++++++ packages/eui-theme-base/tsconfig.json | 5 ++-- packages/eui-theme-base/tsconfig.types.json | 13 +++++++++ 5 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 packages/eui-theme-base/.babelrc.js create mode 100644 packages/eui-theme-base/tsconfig.cjs.json create mode 100644 packages/eui-theme-base/tsconfig.types.json diff --git a/packages/eui-theme-base/.babelrc.js b/packages/eui-theme-base/.babelrc.js new file mode 100644 index 00000000000..0fc74dd1fe9 --- /dev/null +++ b/packages/eui-theme-base/.babelrc.js @@ -0,0 +1,27 @@ +module.exports = { + // We need to preserve comments as they are used by webpack for + // naming chunks during code-splitting. The compression step during + // bundling will remove them later. + comments: true, + + presets: [ + [ + '@babel/env', + { + // `targets` property set via `.browserslistrc` + useBuiltIns: process.env.NO_COREJS_POLYFILL ? false : 'usage', + corejs: !process.env.NO_COREJS_POLYFILL ? '3.6' : undefined, + modules: process.env.BABEL_MODULES + ? process.env.BABEL_MODULES === 'false' + ? false + : process.env.BABEL_MODULES + : 'commonjs', // babel's default is commonjs + }, + ], + ['@babel/react', { runtime: 'classic' }], + [ + '@babel/typescript', + { isTSX: true, allExtensions: true, allowDeclareFields: true }, + ], + ], +}; diff --git a/packages/eui-theme-base/package.json b/packages/eui-theme-base/package.json index b4b3052be63..d303cb50623 100644 --- a/packages/eui-theme-base/package.json +++ b/packages/eui-theme-base/package.json @@ -4,7 +4,11 @@ "description": "EUI theme base", "license": "SEE LICENSE IN LICENSE.txt", "scripts": { - "build": "tsc", + "build:clean": "rimraf lib/", + "build": "yarn build:clean && yarn build:compile && yarn build:compile:cjs && yarn build:types", + "build:compile": "tsc --project tsconfig.json", + "build:compile:cjs": "NODE_ENV=production babel src --out-dir=lib/cjs --verbose --extensions .js,.ts,.tsx --source-maps", + "build:types": "NODE_ENV=production tsc --project tsconfig.types.json", "lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-sass", "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", "lint-sass": "yarn stylelint \"**/*.scss\" --quiet-deprecation-warnings", @@ -20,6 +24,11 @@ "@elastic/eui-common": "workspace:^" }, "devDependencies": { + "@babel/cli": "^7.21.5", + "@babel/core": "^7.21.8", + "@babel/preset-env": "^7.21.5", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.5", "@types/jest": "^29.5.12", "@types/prettier": "2.7.3", "@typescript-eslint/eslint-plugin": "^5.59.7", @@ -32,17 +41,20 @@ "eslint-plugin-prettier": "^4.2.1", "jest": "^29.7.0", "prettier": "^2.8.8", + "rimraf": "^6.0.1", "stylelint": "^15.7.0", "stylelint-config-prettier-scss": "^1.0.0", "stylelint-config-standard": "^33.0.0", "stylelint-config-standard-scss": "^9.0.0", - "typescript": "^5.6.2" + "typescript": "4.5.3" }, - "main": "lib/index.js", + "main": "src/index.ts", "exports": { "./lib/*": "./lib/*", ".": { - "default": "./lib/index.js" + "require": "./lib/cjs/index.js", + "import": "./lib/esm/index.js", + "default": "./lib/esm/index.js" } }, "files": [ diff --git a/packages/eui-theme-base/tsconfig.cjs.json b/packages/eui-theme-base/tsconfig.cjs.json new file mode 100644 index 00000000000..6becea42efa --- /dev/null +++ b/packages/eui-theme-base/tsconfig.cjs.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib/cjs", + "target": "es6", + "module": "CommonJS", + "lib": [ + "es6", + "DOM" + ], + "moduleResolution": "Node", + "declaration": true, + "sourceMap": true, + "noEmitHelpers": true, + "incremental": true, + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "tsBuildInfoFile": "lib/cjs/.tsbuildinfo", + "importHelpers": false, + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules" + ], +} \ No newline at end of file diff --git a/packages/eui-theme-base/tsconfig.json b/packages/eui-theme-base/tsconfig.json index c3190be619a..055614f8c47 100644 --- a/packages/eui-theme-base/tsconfig.json +++ b/packages/eui-theme-base/tsconfig.json @@ -2,8 +2,9 @@ "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { "rootDir": "src", - "outDir": "lib", + "outDir": "lib/esm", "target": "ES2020", + "module": "ESNext", "lib": [ "ESNext", "DOM" @@ -16,7 +17,7 @@ "esModuleInterop": true, "strict": true, "skipLibCheck": true, - "tsBuildInfoFile": "lib/.tsbuildinfo" + "tsBuildInfoFile": "lib/esm/.tsbuildinfo" }, "include": [ "src" diff --git a/packages/eui-theme-base/tsconfig.types.json b/packages/eui-theme-base/tsconfig.types.json new file mode 100644 index 00000000000..54e2031daae --- /dev/null +++ b/packages/eui-theme-base/tsconfig.types.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.cjs.json", + "compilerOptions": { + "outDir": "lib/cjs", + "declaration": true, + "declarationMap": true, + "isolatedModules": false, + "noEmit": false, + "allowJs": false, + "emitDeclarationOnly": true + }, + "exclude": ["node_modules", "**/*.test.ts"] +} \ No newline at end of file From 08bef3aaafb7eebf23cbdfc58242c9c7bc636d4d Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 23 Sep 2024 10:30:23 +0200 Subject: [PATCH 15/32] build: add script for building workspace dependencies --- .buildkite/scripts/pipelines/pipeline_test.sh | 18 +++++++++--------- packages/eui/package.json | 1 + packages/eui/scripts/deploy/build_docs | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.buildkite/scripts/pipelines/pipeline_test.sh b/.buildkite/scripts/pipelines/pipeline_test.sh index 8ec1d30c660..56d3884ee77 100644 --- a/.buildkite/scripts/pipelines/pipeline_test.sh +++ b/.buildkite/scripts/pipelines/pipeline_test.sh @@ -29,53 +29,53 @@ COMMAND="" case $TEST_TYPE in lint) echo "[TASK]: Running linters" - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui lint" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui lint" ;; unit:ts) echo "[TASK]: Running .ts and .js unit tests" - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=non-react" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=non-react" ;; unit:tsx:16) echo "[TASK]: Running Jest .tsx tests against React 16" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=jest_token_react16 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=16 --testMatch=react" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=16 --testMatch=react" ;; unit:tsx:17) echo "[TASK]: Running Jest .tsx tests against React 17" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=jest_token_react17 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=17 --testMatch=react" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=17 --testMatch=react" ;; unit:tsx) echo "[TASK]: Running Jest .tsx tests against React 18" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=jest_token_react18 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=react" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=react" ;; cypress:16) echo "[TASK]: Running Cypress tests against React 16" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=cypress_token_react16 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=16" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=16" ;; cypress:17) echo "[TASK]: Running Cypress tests against React 17" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=cypress_token_react17 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=17" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=17" ;; cypress:18) echo "[TASK]: Running Cypress tests against React 18" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=cypress_token_react18 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048" ;; cypress:a11y) echo "[TASK]: Running Cypress accessibility tests against React 18" - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui run test-cypress-a11y --node-options=--max_old_space_size=2048" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui run test-cypress-a11y --node-options=--max_old_space_size=2048" ;; *) diff --git a/packages/eui/package.json b/packages/eui/package.json index 20939391baa..0cb78adb493 100644 --- a/packages/eui/package.json +++ b/packages/eui/package.json @@ -16,6 +16,7 @@ ], "scripts": { "start": "cross-env BABEL_MODULES=false webpack serve --config=src-docs/webpack.config.js", + "init:workspaces": "yarn workspaces foreach -Rpti --from @elastic/eui --exclude @elastic/eui run build", "build-docs": "cross-env BABEL_MODULES=false cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 webpack --config=src-docs/webpack.config.js", "build": "node ./scripts/compile-i18n-strings.js && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && yarn compile-scss", "build-pack": "yarn build && npm pack", diff --git a/packages/eui/scripts/deploy/build_docs b/packages/eui/scripts/deploy/build_docs index ab1207b3337..d2a6168e8ed 100755 --- a/packages/eui/scripts/deploy/build_docs +++ b/packages/eui/scripts/deploy/build_docs @@ -12,4 +12,4 @@ docker run \ --volume "$PWD":/app \ --workdir /app \ "$DOCKER_BASE_IMAGE" \ - bash -c 'yarn && yarn --cwd packages/eui build && yarn --cwd packages/eui build-docs && yarn --cwd packages/eui build-storybook' + bash -c 'yarn && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui build && yarn --cwd packages/eui build-docs && yarn --cwd packages/eui build-storybook' From b3e6f41c9e25f2f8a85b8392f80613a1e5fc42b7 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 23 Sep 2024 14:16:22 +0200 Subject: [PATCH 16/32] refactor: update sass imports --- packages/eui/src/global_styling/variables/_animations.scss | 2 +- packages/eui/src/global_styling/variables/_borders.scss | 2 +- packages/eui/src/global_styling/variables/_buttons.scss | 2 +- packages/eui/src/global_styling/variables/_colors_vis.scss | 2 +- packages/eui/src/global_styling/variables/_font_weight.scss | 2 +- packages/eui/src/global_styling/variables/_form.scss | 2 +- packages/eui/src/global_styling/variables/_responsive.scss | 2 +- packages/eui/src/global_styling/variables/_shadows.scss | 2 +- packages/eui/src/global_styling/variables/_size.scss | 2 +- packages/eui/src/global_styling/variables/_states.scss | 2 +- packages/eui/src/global_styling/variables/_typography.scss | 2 +- packages/eui/src/global_styling/variables/_z_index.scss | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/eui/src/global_styling/variables/_animations.scss b/packages/eui/src/global_styling/variables/_animations.scss index 08e4098204e..c564fe586aa 100644 --- a/packages/eui/src/global_styling/variables/_animations.scss +++ b/packages/eui/src/global_styling/variables/_animations.scss @@ -1,6 +1,6 @@ // Animations -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/animations' +@import 'node_modules/@elastic/eui-theme-base/src/variables/animations' // Keyframe animation declarations can be found in // utility/animations.scss diff --git a/packages/eui/src/global_styling/variables/_borders.scss b/packages/eui/src/global_styling/variables/_borders.scss index adc8666bdf4..779622116d0 100644 --- a/packages/eui/src/global_styling/variables/_borders.scss +++ b/packages/eui/src/global_styling/variables/_borders.scss @@ -1,3 +1,3 @@ // Borders -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/borders' +@import 'node_modules/@elastic/eui-theme-base/src/variables/borders' diff --git a/packages/eui/src/global_styling/variables/_buttons.scss b/packages/eui/src/global_styling/variables/_buttons.scss index 3056f68a5d9..f840381b2f4 100644 --- a/packages/eui/src/global_styling/variables/_buttons.scss +++ b/packages/eui/src/global_styling/variables/_buttons.scss @@ -1 +1 @@ -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/buttons' +@import 'node_modules/@elastic/eui-theme-base/src/variables/buttons' diff --git a/packages/eui/src/global_styling/variables/_colors_vis.scss b/packages/eui/src/global_styling/variables/_colors_vis.scss index 10a57baded8..ac62244423a 100644 --- a/packages/eui/src/global_styling/variables/_colors_vis.scss +++ b/packages/eui/src/global_styling/variables/_colors_vis.scss @@ -1,3 +1,3 @@ // Visualization colors -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/colors_vis' +@import 'node_modules/@elastic/eui-theme-base/src/variables/colors_vis' diff --git a/packages/eui/src/global_styling/variables/_font_weight.scss b/packages/eui/src/global_styling/variables/_font_weight.scss index 07e8c275f2f..7c21eb49d55 100644 --- a/packages/eui/src/global_styling/variables/_font_weight.scss +++ b/packages/eui/src/global_styling/variables/_font_weight.scss @@ -1,4 +1,4 @@ // Separated out to its own file for easy import into docs // Font weights -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/font_weight' +@import 'node_modules/@elastic/eui-theme-base/src/variables/font_weight' diff --git a/packages/eui/src/global_styling/variables/_form.scss b/packages/eui/src/global_styling/variables/_form.scss index 6bbf8efff0b..abc5c608816 100644 --- a/packages/eui/src/global_styling/variables/_form.scss +++ b/packages/eui/src/global_styling/variables/_form.scss @@ -1,2 +1,2 @@ // Form -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/form' +@import 'node_modules/@elastic/eui-theme-base/src/variables/form' diff --git a/packages/eui/src/global_styling/variables/_responsive.scss b/packages/eui/src/global_styling/variables/_responsive.scss index 6c1b3355918..3f187ca2d16 100644 --- a/packages/eui/src/global_styling/variables/_responsive.scss +++ b/packages/eui/src/global_styling/variables/_responsive.scss @@ -1 +1 @@ -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/responsive' +@import 'node_modules/@elastic/eui-theme-base/src/variables/responsive' diff --git a/packages/eui/src/global_styling/variables/_shadows.scss b/packages/eui/src/global_styling/variables/_shadows.scss index ee889447914..7b50faeb167 100644 --- a/packages/eui/src/global_styling/variables/_shadows.scss +++ b/packages/eui/src/global_styling/variables/_shadows.scss @@ -1,2 +1,2 @@ // Shadows -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/shadows' +@import 'node_modules/@elastic/eui-theme-base/src/variables/shadows' diff --git a/packages/eui/src/global_styling/variables/_size.scss b/packages/eui/src/global_styling/variables/_size.scss index 3ad0fca24ac..aa1b710e880 100644 --- a/packages/eui/src/global_styling/variables/_size.scss +++ b/packages/eui/src/global_styling/variables/_size.scss @@ -1 +1 @@ -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/size' +@import 'node_modules/@elastic/eui-theme-base/src/variables/size' diff --git a/packages/eui/src/global_styling/variables/_states.scss b/packages/eui/src/global_styling/variables/_states.scss index ee6896362de..332b22a7dad 100644 --- a/packages/eui/src/global_styling/variables/_states.scss +++ b/packages/eui/src/global_styling/variables/_states.scss @@ -1 +1 @@ -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/states' \ No newline at end of file +@import 'node_modules/@elastic/eui-theme-base/src/variables/states' \ No newline at end of file diff --git a/packages/eui/src/global_styling/variables/_typography.scss b/packages/eui/src/global_styling/variables/_typography.scss index f7c0ee85a2d..3750b61e117 100644 --- a/packages/eui/src/global_styling/variables/_typography.scss +++ b/packages/eui/src/global_styling/variables/_typography.scss @@ -1 +1 @@ -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/typography' \ No newline at end of file +@import 'node_modules/@elastic/eui-theme-base/src/variables/typography' \ No newline at end of file diff --git a/packages/eui/src/global_styling/variables/_z_index.scss b/packages/eui/src/global_styling/variables/_z_index.scss index a14a30f06d1..119788c6b81 100644 --- a/packages/eui/src/global_styling/variables/_z_index.scss +++ b/packages/eui/src/global_styling/variables/_z_index.scss @@ -1,2 +1,2 @@ // Z-Index -@import '../../../node_modules/@elastic/eui-theme-base/src/variables/z_index' +@import 'node_modules/@elastic/eui-theme-base/src/variables/z_index' From 7642450201577f4642dae56cb0ce87955ac92e89 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 23 Sep 2024 15:48:31 +0200 Subject: [PATCH 17/32] build: update dependencies build: ensure sass files are added to packed sub packages --- packages/eui-common/package.json | 7 ++++--- packages/eui-theme-base/package.json | 15 +++++++++------ packages/eui-theme-berlin/package.json | 11 +++++++---- packages/eui/package.json | 11 +++++++---- packages/website/package.json | 1 + yarn.lock | 8 ++++++++ 6 files changed, 36 insertions(+), 17 deletions(-) diff --git a/packages/eui-common/package.json b/packages/eui-common/package.json index 3304718b1c2..bc5dd429ba0 100644 --- a/packages/eui-common/package.json +++ b/packages/eui-common/package.json @@ -7,8 +7,9 @@ "build:clean": "rimraf lib", "build": "yarn build:clean && yarn build:compile && yarn build:compile:cjs && yarn build:types", "build:compile": "tsc --project tsconfig.json", - "build:compile:cjs": "NODE_ENV=production babel src --out-dir=lib/cjs --verbose --extensions .js,.ts,.tsx --source-maps", + "build:compile:cjs": "NODE_ENV=production babel src --out-dir=lib/cjs --extensions .js,.ts,.tsx --source-maps", "build:types": "NODE_ENV=production tsc --project tsconfig.types.json", + "build-pack": "yarn build && npm pack", "lint": "yarn tsc --noEmit && yarn lint-es", "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", "test": "jest" @@ -40,14 +41,14 @@ "rimraf": "^6.0.1", "typescript": "^5.6.2" }, - "main": "src/index.ts", + "main": "lib/cjs/index.js", "exports": { "./lib/*": "./lib/*", "./scripts/*": "./scripts/*", ".": { "require": "./lib/cjs/index.js", "import": "./lib/esm/index.js", - "default": "./lib/esm/index.js" + "default": "./lib/cjs/index.js" } }, "files": [ diff --git a/packages/eui-theme-base/package.json b/packages/eui-theme-base/package.json index d303cb50623..2f9731eab86 100644 --- a/packages/eui-theme-base/package.json +++ b/packages/eui-theme-base/package.json @@ -7,8 +7,9 @@ "build:clean": "rimraf lib/", "build": "yarn build:clean && yarn build:compile && yarn build:compile:cjs && yarn build:types", "build:compile": "tsc --project tsconfig.json", - "build:compile:cjs": "NODE_ENV=production babel src --out-dir=lib/cjs --verbose --extensions .js,.ts,.tsx --source-maps", + "build:compile:cjs": "NODE_ENV=production babel src --out-dir=lib/cjs --extensions .js,.ts,.tsx --source-maps", "build:types": "NODE_ENV=production tsc --project tsconfig.types.json", + "build-pack": "yarn build && npm pack", "lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-sass", "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", "lint-sass": "yarn stylelint \"**/*.scss\" --quiet-deprecation-warnings", @@ -20,15 +21,13 @@ "directory": "packages/eui-theme-base" }, "private": true, - "dependencies": { - "@elastic/eui-common": "workspace:^" - }, "devDependencies": { "@babel/cli": "^7.21.5", "@babel/core": "^7.21.8", "@babel/preset-env": "^7.21.5", "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.21.5", + "@elastic/eui-common": "workspace:^", "@types/jest": "^29.5.12", "@types/prettier": "2.7.3", "@typescript-eslint/eslint-plugin": "^5.59.7", @@ -48,17 +47,21 @@ "stylelint-config-standard-scss": "^9.0.0", "typescript": "4.5.3" }, - "main": "src/index.ts", + "peerDependencies": { + "@elastic/eui-common": "0.0.1" + }, + "main": "lib/cjs/index.js", "exports": { "./lib/*": "./lib/*", ".": { "require": "./lib/cjs/index.js", "import": "./lib/esm/index.js", - "default": "./lib/esm/index.js" + "default": "./lib/cjs/index.js" } }, "files": [ "lib/", + "src/**/*.scss", "README.md" ], "installConfig": { diff --git a/packages/eui-theme-berlin/package.json b/packages/eui-theme-berlin/package.json index 6260b270f56..04623fa5c68 100644 --- a/packages/eui-theme-berlin/package.json +++ b/packages/eui-theme-berlin/package.json @@ -14,13 +14,15 @@ "directory": "packages/eui-theme-berlin" }, "private": true, - "dependencies": { - "@elastic/eui-common": "workspace:^", - "@elastic/eui-theme-base": "workspace:^" - }, "devDependencies": { + "@elastic/eui-common": "workspace:^", + "@elastic/eui-theme-base": "workspace:^", "typescript": "^5.6.2" }, + "peerDependencies": { + "@elastic/eui-common": "0.0.1", + "@elastic/eui-theme-base": "0.0.1" + }, "main": "lib/index.js", "exports": { "./lib/*": "./lib/*", @@ -30,6 +32,7 @@ }, "files": [ "lib/", + "src/**/*.scss", "README.md" ] } diff --git a/packages/eui/package.json b/packages/eui/package.json index 0cb78adb493..8b0b2d5ec3d 100644 --- a/packages/eui/package.json +++ b/packages/eui/package.json @@ -16,7 +16,7 @@ ], "scripts": { "start": "cross-env BABEL_MODULES=false webpack serve --config=src-docs/webpack.config.js", - "init:workspaces": "yarn workspaces foreach -Rpti --from @elastic/eui --exclude @elastic/eui run build", + "init:workspaces": "yarn workspaces foreach -Rti --from @elastic/eui --exclude @elastic/eui run build", "build-docs": "cross-env BABEL_MODULES=false cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 webpack --config=src-docs/webpack.config.js", "build": "node ./scripts/compile-i18n-strings.js && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && yarn compile-scss", "build-pack": "yarn build && npm pack", @@ -52,9 +52,6 @@ "url": "https://github.com/elastic/eui.git" }, "dependencies": { - "@elastic/eui-common": "workspace:^", - "@elastic/eui-theme-base": "workspace:^", - "@elastic/eui-theme-berlin": "workspace:^", "@hello-pangea/dnd": "^16.6.0", "@types/lodash": "^4.14.202", "@types/numeral": "^2.0.5", @@ -107,6 +104,9 @@ "@cypress/webpack-dev-server": "^1.7.0", "@elastic/charts": "^64.1.0", "@elastic/datemath": "^5.0.3", + "@elastic/eui-common": "workspace:^", + "@elastic/eui-theme-base": "workspace:^", + "@elastic/eui-theme-berlin": "workspace:^", "@emotion/babel-preset-css-prop": "^11.11.0", "@emotion/cache": "^11.11.0", "@emotion/css": "^11.11.0", @@ -257,6 +257,9 @@ }, "peerDependencies": { "@elastic/datemath": "^5.0.2", + "@elastic/eui-common": "0.0.1", + "@elastic/eui-theme-base": "0.0.1", + "@elastic/eui-theme-berlin": "0.0.1", "@emotion/css": "11.x", "@emotion/react": "11.x", "@types/react": "^16.9 || ^17.0 || ^18.0", diff --git a/packages/website/package.json b/packages/website/package.json index 77302ccfb73..b6263ad491f 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "docusaurus": "docusaurus", + "init:workspaces": "yarn workspace @elastic/eui-common run build && yarn workspace @elastic/eui-theme-base run build && yarn workspace @elastic/eui-theme-berlin run build && yarn workspaces foreach -Rti --from @elastic/eui-website run build", "start": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus start", "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus build", "swizzle": "docusaurus swizzle", diff --git a/yarn.lock b/yarn.lock index 245f66b7f4a..b9915a8fdef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5803,6 +5803,8 @@ __metadata: stylelint-config-standard: "npm:^33.0.0" stylelint-config-standard-scss: "npm:^9.0.0" typescript: "npm:4.5.3" + peerDependencies: + "@elastic/eui-common": 0.0.1 languageName: unknown linkType: soft @@ -5813,6 +5815,9 @@ __metadata: "@elastic/eui-common": "workspace:^" "@elastic/eui-theme-base": "workspace:^" typescript: "npm:^5.6.2" + peerDependencies: + "@elastic/eui-common": 0.0.1 + "@elastic/eui-theme-base": 0.0.1 languageName: unknown linkType: soft @@ -6053,6 +6058,9 @@ __metadata: yo: "npm:^4.3.1" peerDependencies: "@elastic/datemath": ^5.0.2 + "@elastic/eui-common": 0.0.1 + "@elastic/eui-theme-base": 0.0.1 + "@elastic/eui-theme-berlin": 0.0.1 "@emotion/css": 11.x "@emotion/react": 11.x "@types/react": ^16.9 || ^17.0 || ^18.0 From b07e11076e86584f89734f8c2f2d3ef75a7afa09 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 23 Sep 2024 15:48:50 +0200 Subject: [PATCH 18/32] build: update new_docs and release scripts --- .buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh | 2 +- .buildkite/scripts/release/step_build.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh b/.buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh index ebf6a66e8a1..4af85fc6804 100644 --- a/.buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh +++ b/.buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh @@ -33,7 +33,7 @@ analytics_vault="secret/ci/elastic-eui/analytics" export DOCS_BASE_URL="/${bucket_directory}" export DOCS_GOOGLE_TAG_MANAGER_ID="$(retry 5 vault read -field=google_tag_manager_id "${analytics_vault}")" -yarn workspaces foreach -Rpt --from @elastic/eui-website run build +yarn workspace @elastic/eui-website run init:workspaces echo "+++ Configuring environment for website deployment" diff --git a/.buildkite/scripts/release/step_build.sh b/.buildkite/scripts/release/step_build.sh index 3a9251b6e28..de1196ef7f6 100755 --- a/.buildkite/scripts/release/step_build.sh +++ b/.buildkite/scripts/release/step_build.sh @@ -10,6 +10,7 @@ echo "+++ :yarn: Installing dependencies" yarn echo "+++ :yarn: Building @elastic/eui" +yarn init:workspaces yarn build echo "+++ :yarn: Built @elastic/eui" From 9bc5ca000792d17a7ab2e5736dee69fbb1372903 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Thu, 26 Sep 2024 14:17:46 +0200 Subject: [PATCH 19/32] refactor: rename script --- .../pipelines/pipeline_deploy_new_docs.sh | 2 +- .buildkite/scripts/pipelines/pipeline_test.sh | 18 +++++++++--------- .buildkite/scripts/release/step_build.sh | 2 +- packages/eui/package.json | 2 +- packages/eui/scripts/deploy/build_docs | 2 +- packages/website/package.json | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh b/.buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh index 4af85fc6804..df2598dce0b 100644 --- a/.buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh +++ b/.buildkite/scripts/pipelines/pipeline_deploy_new_docs.sh @@ -33,7 +33,7 @@ analytics_vault="secret/ci/elastic-eui/analytics" export DOCS_BASE_URL="/${bucket_directory}" export DOCS_GOOGLE_TAG_MANAGER_ID="$(retry 5 vault read -field=google_tag_manager_id "${analytics_vault}")" -yarn workspace @elastic/eui-website run init:workspaces +yarn workspace @elastic/eui-website run build:workspaces echo "+++ Configuring environment for website deployment" diff --git a/.buildkite/scripts/pipelines/pipeline_test.sh b/.buildkite/scripts/pipelines/pipeline_test.sh index 56d3884ee77..220e5313705 100644 --- a/.buildkite/scripts/pipelines/pipeline_test.sh +++ b/.buildkite/scripts/pipelines/pipeline_test.sh @@ -29,53 +29,53 @@ COMMAND="" case $TEST_TYPE in lint) echo "[TASK]: Running linters" - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui lint" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui lint" ;; unit:ts) echo "[TASK]: Running .ts and .js unit tests" - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=non-react" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=non-react" ;; unit:tsx:16) echo "[TASK]: Running Jest .tsx tests against React 16" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=jest_token_react16 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=16 --testMatch=react" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=16 --testMatch=react" ;; unit:tsx:17) echo "[TASK]: Running Jest .tsx tests against React 17" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=jest_token_react17 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=17 --testMatch=react" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --react-version=17 --testMatch=react" ;; unit:tsx) echo "[TASK]: Running Jest .tsx tests against React 18" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=jest_token_react18 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=react" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui test-unit --node-options=--max_old_space_size=2048 --testMatch=react" ;; cypress:16) echo "[TASK]: Running Cypress tests against React 16" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=cypress_token_react16 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=16" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=16" ;; cypress:17) echo "[TASK]: Running Cypress tests against React 17" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=cypress_token_react17 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=17" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048 --react-version=17" ;; cypress:18) echo "[TASK]: Running Cypress tests against React 18" DOCKER_OPTIONS+=(--env BUILDKITE_ANALYTICS_TOKEN="$(retry 5 vault read -field=cypress_token_react18 "${buildkite_analytics_vault}")") - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui test-cypress --node-options=--max_old_space_size=2048" ;; cypress:a11y) echo "[TASK]: Running Cypress accessibility tests against React 18" - COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui run test-cypress-a11y --node-options=--max_old_space_size=2048" + COMMAND="/opt/yarn*/bin/yarn --cwd packages/eui && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui cypress install && yarn --cwd packages/eui run test-cypress-a11y --node-options=--max_old_space_size=2048" ;; *) diff --git a/.buildkite/scripts/release/step_build.sh b/.buildkite/scripts/release/step_build.sh index de1196ef7f6..01d96bf62d8 100755 --- a/.buildkite/scripts/release/step_build.sh +++ b/.buildkite/scripts/release/step_build.sh @@ -10,7 +10,7 @@ echo "+++ :yarn: Installing dependencies" yarn echo "+++ :yarn: Building @elastic/eui" -yarn init:workspaces +yarn build:workspaces yarn build echo "+++ :yarn: Built @elastic/eui" diff --git a/packages/eui/package.json b/packages/eui/package.json index 8b0b2d5ec3d..a8a9d87592d 100644 --- a/packages/eui/package.json +++ b/packages/eui/package.json @@ -16,7 +16,7 @@ ], "scripts": { "start": "cross-env BABEL_MODULES=false webpack serve --config=src-docs/webpack.config.js", - "init:workspaces": "yarn workspaces foreach -Rti --from @elastic/eui --exclude @elastic/eui run build", + "build:workspaces": "yarn workspaces foreach -Rti --from @elastic/eui --exclude @elastic/eui run build", "build-docs": "cross-env BABEL_MODULES=false cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 webpack --config=src-docs/webpack.config.js", "build": "node ./scripts/compile-i18n-strings.js && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && yarn compile-scss", "build-pack": "yarn build && npm pack", diff --git a/packages/eui/scripts/deploy/build_docs b/packages/eui/scripts/deploy/build_docs index d2a6168e8ed..8e700a97b0b 100755 --- a/packages/eui/scripts/deploy/build_docs +++ b/packages/eui/scripts/deploy/build_docs @@ -12,4 +12,4 @@ docker run \ --volume "$PWD":/app \ --workdir /app \ "$DOCKER_BASE_IMAGE" \ - bash -c 'yarn && yarn --cwd packages/eui init:workspaces && yarn --cwd packages/eui build && yarn --cwd packages/eui build-docs && yarn --cwd packages/eui build-storybook' + bash -c 'yarn && yarn --cwd packages/eui build:workspaces && yarn --cwd packages/eui build && yarn --cwd packages/eui build-docs && yarn --cwd packages/eui build-storybook' diff --git a/packages/website/package.json b/packages/website/package.json index b6263ad491f..e16879931b3 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "docusaurus": "docusaurus", - "init:workspaces": "yarn workspace @elastic/eui-common run build && yarn workspace @elastic/eui-theme-base run build && yarn workspace @elastic/eui-theme-berlin run build && yarn workspaces foreach -Rti --from @elastic/eui-website run build", + "build:workspaces": "yarn workspace @elastic/eui-common run build && yarn workspace @elastic/eui-theme-base run build && yarn workspace @elastic/eui-theme-berlin run build && yarn workspaces foreach -Rti --from @elastic/eui-website run build", "start": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus start", "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus build", "swizzle": "docusaurus swizzle", From f0d424bcb19ff45147a3b39d2456be9e4d37b256 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Thu, 26 Sep 2024 14:21:47 +0200 Subject: [PATCH 20/32] build: add build:workspaces script on pre-push hook --- packages/eui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eui/package.json b/packages/eui/package.json index a8a9d87592d..6a2bc93a17d 100644 --- a/packages/eui/package.json +++ b/packages/eui/package.json @@ -31,7 +31,7 @@ "test": "yarn lint && yarn test-unit", "test-ci": "yarn test && yarn test-cypress", "test-unit": "node ./scripts/test-unit", - "test-staged": "yarn lint && node scripts/test-staged.js", + "test-staged": "yarn build:workspaces && yarn lint && node scripts/test-staged.js", "test-cypress": "node ./scripts/test-cypress", "test-cypress-dev": "yarn test-cypress --dev", "test-cypress-a11y": "yarn test-cypress --a11y", From 6e86fc002aa196ccc3271f64e09eae4d849741a1 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Thu, 26 Sep 2024 17:02:53 +0200 Subject: [PATCH 21/32] refactor: separate out scss files and resolve circular scss dependency - this is a first step, once the overall path si defined we either need to continue moving out more or reverse this partially --- .../src/global_styling/functions/_colors.scss | 138 ++++ .../src/global_styling/functions/_index.scss | 5 + .../src/global_styling/functions/_math.scss | 1 + .../global_styling/functions/_math_pow.scss | 82 ++ .../eui-common/src/global_styling/index.scss | 15 + .../src/global_styling/mixins/_button.scss | 149 ++++ .../src/global_styling/mixins/_form.scss | 273 +++++++ .../src/global_styling/mixins/_helpers.scss | 126 +++ .../src/global_styling/mixins/_index.scss | 14 + .../src/global_styling/mixins/_link.scss | 11 + .../src/global_styling/mixins/_loading.scss | 6 + .../src/global_styling/mixins/_panel.scss | 55 ++ .../src/global_styling/mixins/_range.scss | 62 ++ .../global_styling/mixins/_responsive.scss | 44 + .../src/global_styling/mixins/_shadow.scss | 108 +++ .../src/global_styling/mixins/_size.scss | 4 + .../src/global_styling/mixins/_states.scss | 50 ++ .../src/global_styling/mixins/_tool_tip.scss | 25 + .../global_styling/mixins/_typography.scss | 167 ++++ .../react_date_picker/_date_picker.scss | 772 ++++++++++++++++++ .../react_date_picker/_index.scss | 2 + .../react_date_picker/_variables.scss | 1 + .../global_styling/utility/_animations.scss | 55 ++ .../src/global_styling/utility/_index.scss | 1 + packages/eui-theme-berlin/src/theme_dark.scss | 3 +- .../eui-theme-berlin/src/theme_light.scss | 3 +- .../src/variables/_colors_dark.scss | 4 +- .../src/variables/_colors_light.scss | 4 +- .../src/variables/_index.scss | 2 +- packages/eui/src-docs/src/index.js | 6 +- packages/eui/src-docs/src/theme_new_dark.scss | 7 + .../eui/src-docs/src/theme_new_light.scss | 7 + .../src/global_styling/functions/_index.scss | 6 +- packages/eui/src/global_styling/index.scss | 18 +- 34 files changed, 2196 insertions(+), 30 deletions(-) create mode 100644 packages/eui-common/src/global_styling/functions/_colors.scss create mode 100644 packages/eui-common/src/global_styling/functions/_index.scss create mode 100644 packages/eui-common/src/global_styling/functions/_math.scss create mode 100644 packages/eui-common/src/global_styling/functions/_math_pow.scss create mode 100644 packages/eui-common/src/global_styling/index.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_button.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_form.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_helpers.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_index.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_link.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_loading.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_panel.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_range.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_responsive.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_shadow.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_size.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_states.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_tool_tip.scss create mode 100644 packages/eui-common/src/global_styling/mixins/_typography.scss create mode 100644 packages/eui-common/src/global_styling/react_date_picker/_date_picker.scss create mode 100644 packages/eui-common/src/global_styling/react_date_picker/_index.scss create mode 100644 packages/eui-common/src/global_styling/react_date_picker/_variables.scss create mode 100644 packages/eui-common/src/global_styling/utility/_animations.scss create mode 100644 packages/eui-common/src/global_styling/utility/_index.scss create mode 100644 packages/eui/src-docs/src/theme_new_dark.scss create mode 100644 packages/eui/src-docs/src/theme_new_light.scss diff --git a/packages/eui-common/src/global_styling/functions/_colors.scss b/packages/eui-common/src/global_styling/functions/_colors.scss new file mode 100644 index 00000000000..25834e10add --- /dev/null +++ b/packages/eui-common/src/global_styling/functions/_colors.scss @@ -0,0 +1,138 @@ +// Converting a normal hex color to RBG +@function hexToRGB($color) { + @return 'rgb%28#{round(red($color))}, #{round(green($color))}, #{round(blue($color))}%29'; +} + +// Mixes a provided color with white. +@function tint($color, $percent) { + @return mix($euiColorGhost, $color, $percent); +} + +// Mixes a provided color with black. +@function shade($color, $percent) { + @return mix($euiColorInk, $color, $percent); +} + +// For theming. Checks the text color and tells us whether it's light or dark. +// Based on that we either tint (add white) or shade (add black). +@function tintOrShade($color, $tint, $shade) { + @if (lightness($euiTextColor) > 50) { + @return shade($color, $shade); + } @else { + @return tint($color, $tint); + } +} + +// The reverse of the above +@function shadeOrTint($color, $shade, $tint) { + @if (lightness($euiTextColor) < 50) { + @return shade($color, $shade); + } @else { + @return tint($color, $tint); + } +} + +// Similar to above, but uses the light or dark color based +// on whether it's the light or dark theme +@function lightOrDarkTheme($lightColor, $darkColor) { + @if (lightness($euiTextColor) < 50) { + @return $lightColor; + } @else { + @return $darkColor; + } +} + +// Calculates luminance, which is better than brightness for checking colors +// pow, nth functions come from the _math.scss functions +@function luminance($color) { + // Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef + $rgba: red($color), green($color), blue($color); + $rgba2: (); + + @for $i from 1 through 3 { + $rgb: nth($rgba, $i); + $rgb: $rgb / 255; + + $rgb: if($rgb < .03928, $rgb / 12.92, pow(($rgb + .055) / 1.055, 2.4)); + + $rgba2: append($rgba2, $rgb); + } + + @return .2126 * nth($rgba2, 1) + .7152 * nth($rgba2, 2) + .0722 * nth($rgba2, 3); +} + +// Calculate contrast +@function contrastRatio($background, $foreground) { + $backgroundLum: luminance($background) + .05; + $foregroundLum: luminance($foreground) + .05; + + @return max($backgroundLum, $foregroundLum) / min($backgroundLum, $foregroundLum); +} + +// Given $color, decide whether $lightText or $darkText should be used as the text color +// ex: chooseLightOrDarkText(#EEE, #FFF, #000) would return #000 because it has +// a higher contrast than #FFF against a #EEE background. +@function chooseLightOrDarkText($background, $lightText: $euiColorGhost, $darkText: $euiColorInk) { + $lightContrast: contrastRatio($background, $lightText); + $darkContrast: contrastRatio($background, $darkText); + + @if ($lightContrast > $darkContrast) { + @return $lightText; + } @else { + @return $darkText; + } +} + +// Given a $foreground and a $background, make the $foreground AA accessibility by slightly +// adjusting it till the contrast is high enough +// By default it will compare against the page background color + +// ex: makeContrastColor($lightPink, #FFF) would continually shade the pink until +// it had higher than 4.5 contrast on a white background. +$euiContrastRatioText: 4.5; +@function makeHighContrastColor($foreground, $background: $euiPageBackgroundColor, $ratio: $euiContrastRatioText) { + $contrast: contrastRatio($foreground, $background); + + // Determine the lightness factor of the background color first to + // determine whether to shade or tint the foreground. + $brightness: lightness($background); + + $highContrastTextColor: $foreground; + + @while ($contrast < $ratio) { + @if ($brightness > 50) { + $highContrastTextColor: shade($highContrastTextColor, 5%); + } @else { + $highContrastTextColor: tint($highContrastTextColor, 5%); + } + + $contrast: contrastRatio($highContrastTextColor, $background); + + @if (lightness($highContrastTextColor) < 5) { + @warn 'High enough contrast could not be determined. Most likely your background color does not adjust for light mode.'; + @return $highContrastTextColor; + } + + @if (lightness($highContrastTextColor) > 95) { + @warn 'High enough contrast could not be determined. Most likely your background color does not adjust for dark mode.'; + @return $highContrastTextColor; + } + } + + @return $highContrastTextColor; +} + +// Graphics such as stand alone icons and pieces of a graph only need a minimum ratio of 3:1 with its background. +// Therefore, we can reuse the `makeHighContrastColor()` function but only attain a min contrast of 3.0. +// It is still recommended to use `makeHighContrastColor()` to attain a 4.5:1 ratio if the graphic is small or thinly stroked. +// https://www.w3.org/WAI/GL/low-vision-a11y-tf/wiki/Informational_Graphic_Contrast_(Minimum) +$euiContrastRatioGraphic: 3; +@function makeGraphicContrastColor($color, $background: $euiPageBackgroundColor) { + @return makeHighContrastColor($color, $background, $euiContrastRatioGraphic); +} + +// Disabled content only needs a contrast of at least 2 because there is no interaction available +$euiContrastRatioDisabled: 2; +@function makeDisabledContrastColor($color, $background: $euiPageBackgroundColor) { + @return makeHighContrastColor($color, $background, $euiContrastRatioDisabled); +} diff --git a/packages/eui-common/src/global_styling/functions/_index.scss b/packages/eui-common/src/global_styling/functions/_index.scss new file mode 100644 index 00000000000..de8260b2bba --- /dev/null +++ b/packages/eui-common/src/global_styling/functions/_index.scss @@ -0,0 +1,5 @@ +// Math needs to be first in the load order +@import 'math'; + +// Using math, we have functions to manipulate contrast / luminosity for accessibility +@import 'colors'; diff --git a/packages/eui-common/src/global_styling/functions/_math.scss b/packages/eui-common/src/global_styling/functions/_math.scss new file mode 100644 index 00000000000..cdec36f3e60 --- /dev/null +++ b/packages/eui-common/src/global_styling/functions/_math.scss @@ -0,0 +1 @@ +@import 'math_pow'; \ No newline at end of file diff --git a/packages/eui-common/src/global_styling/functions/_math_pow.scss b/packages/eui-common/src/global_styling/functions/_math_pow.scss new file mode 100644 index 00000000000..2e2d784a845 --- /dev/null +++ b/packages/eui-common/src/global_styling/functions/_math_pow.scss @@ -0,0 +1,82 @@ +/** +The MIT License (MIT) + +Copyright (c) 2015 strarsis https://github.com/strarsis/sass-math-pow + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +@function pow($number, $exp) { + $exp1: round($exp); + $result: powInt($number, $exp1); + + @if ($exp1 != $exp) { + $result: $result * mathExp(($exp - $exp1) * mathLn($number)); + } + + @return $result; +} + +@function powInt($number, $exp) { + @if $exp == 0 { + @return 1; + } @else if $exp < 0 { + @return 1 / powInt($number, -$exp); + } @else { + $e: floor($exp / 2); + $pow: pow($number, $e); + @if $e * 2 == $exp { + @return $pow * $pow; + } @else { + @return $pow * $pow * $number; + } + } +} + +@function mathExp($value) { + $item: 1; + $result: 1; + + @for $index from 1 to 100 { + $item: $item * $value / $index; + $result: $result + $item; + } + + @return $result; +} + +@function mathLn($value) { + $tenExp: 0; + $lnTen: 2.30258509; + + @while ($value > 1) { + $tenExp: $tenExp + 1; + $value: $value / 10; + } + + $item: -1; + $result: 0; + + @for $index from 1 to 100 { + $item: $item * (1 - $value); + $result: $result + $item / $index; + } + + @return $result + $tenExp * $lnTen; +} diff --git a/packages/eui-common/src/global_styling/index.scss b/packages/eui-common/src/global_styling/index.scss new file mode 100644 index 00000000000..cc27e6b91a5 --- /dev/null +++ b/packages/eui-common/src/global_styling/index.scss @@ -0,0 +1,15 @@ +// Core + +// Functions need to be first, since we use them in our variables and mixin definitions +@import 'functions/index'; + +// Mixins provide generic code expansion through helpers +@import 'mixins/index'; + +// Utility classes provide one-off selectors for common css problems +@import 'utility/index'; + +// The reset file has moved to global_styles.tsx + +// Customization of the React Date Picker +@import 'react_date_picker/index'; diff --git a/packages/eui-common/src/global_styling/mixins/_button.scss b/packages/eui-common/src/global_styling/mixins/_button.scss new file mode 100644 index 00000000000..47c87b6e742 --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_button.scss @@ -0,0 +1,149 @@ +// Provides a solid reset and base for handling sizing layout +// Does not include any visual styles +@mixin euiButtonBase { + display: inline-block; + appearance: none; + cursor: pointer; + height: $euiButtonHeight; + line-height: $euiButtonHeight; // prevents descenders from getting cut off + text-align: center; + white-space: nowrap; + max-width: 100%; + vertical-align: middle; +} + +// Adds the focus (and hover) animation for translating up 1px +@mixin euiButtonFocus { + @include euiCanAnimate { + transition: transform $euiAnimSpeedNormal ease-in-out, background-color $euiAnimSpeedNormal ease-in-out; + + &:hover:not(:disabled) { + transform: translateY(-1px); + } + + &:focus { + animation: euiButtonActive $euiAnimSpeedNormal $euiAnimSlightBounce; + } + + &:active:not(:disabled) { + transform: translateY(1px); + } + } +} + +// All of the button base styles including the base, focus, font, and initial styles +// Does not include individual alterations like color or sizes +@mixin euiButton { + @include euiButtonBase; + @include euiFont; + @include euiFontSize; + @include euiButtonFocus; + + font-weight: $euiButtonFontWeight; + text-decoration: none; + outline-offset: -1px; + + &:hover:not(:disabled), + &:focus { + text-decoration: underline; + } +} + +// Correctly lays out the contents of a button when using the proper dom elements of: +// +// 1. Apply margin to all but last item in the flex. +// 2. Margin gets flipped because of the row-reverse. +@mixin euiButtonContent($isReverse: false) { + height: 100%; + width: 100%; + vertical-align: middle; + + .euiButtonContent__icon, + .euiButtonContent__spinner { + flex-shrink: 0; // Ensures the icons/spinner don't scale down below their intended size + } + + @if ($isReverse) { + flex-direction: row-reverse; + + > * + * { + margin-inline-start: 0; // 1, 2 + margin-inline-end: $euiSizeS; // 1, 2 + } + } @else { + display: flex; + justify-content: center; + align-items: center; + + > * + * { + margin-inline-start: $euiSizeS; // 1 + } + } +} + +@mixin euiButtonContentDisabled { + pointer-events: auto; + cursor: not-allowed; + + &:hover, + &:focus, + &:focus-within { + text-decoration: none; + } + + .euiButtonContent__spinner { + border-color: euiLoadingSpinnerBorderColors(currentColor); + } +} + +/* + * Creates the Amsterdam style of button with a transparent background + */ +@mixin euiButtonDefaultStyle($color: 'primary', $includeStates: true, $transparency: $euiButtonDefaultTransparency) { + $backgroundColor: $color; + + @if (map-has-key($euiButtonTypes, $color)) { + $backgroundColor: map-get($euiButtonTypes, $color); + } + + $percentConversion: $transparency * 100%; + // This variable simulates the possibly darkest background the button could be on + // Simulates the 20% opaque color on top of the page background color + $backgroundColorSimulated: mix($euiPageBackgroundColor, $backgroundColor, $percentConversion); + // Then we can calculate the darkest text color needed + color: makeHighContrastColor($backgroundColor, $backgroundColorSimulated); + // But still use transparency + background-color: transparentize($backgroundColor, $transparency); + + @if ($includeStates) { + &:not([class*='isDisabled']) { + &:hover, + &:focus { + // Duplicated from inert state simply to override default theme + background-color: transparentize($backgroundColor, $transparency); + } + } + } +} + +/* + * Creates the Amsterdam style of fill button + */ +@mixin euiButtonFillStyle($color: 'primary') { + $backgroundColor: $color; + + @if (map-has-key($euiButtonTypes, $color)) { + $backgroundColor: map-get($euiButtonTypes, $color); + } + + background-color: $backgroundColor; + color: chooseLightOrDarkText($backgroundColor); +} + +// Keyframe animation declarations can be found in +// utility/animations.scss diff --git a/packages/eui-common/src/global_styling/mixins/_form.scss b/packages/eui-common/src/global_styling/mixins/_form.scss new file mode 100644 index 00000000000..326a8491f87 --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_form.scss @@ -0,0 +1,273 @@ +@mixin euiFormControlLayoutPadding($numOfIcons, $side: 'right', $compressed: false) { + $iconSize: $euiSize; + $iconPadding: $euiFormControlPadding; + $marginBetweenIcons: $euiFormControlPadding / 2; + + @if ($compressed) { + $iconPadding: $euiFormControlCompressedPadding; + } + + @if variable-exists(numOfIcons) == false { + @error '$numOfIcons:integer (1-3) must be provided to @mixin euiFormControlLayoutPadding().'; + } @else if $numOfIcons == 1 { + padding-#{$side}: $iconPadding + $iconSize + $iconPadding; + } @else if $numOfIcons == 2 { + padding-#{$side}: $iconPadding + $iconSize + $marginBetweenIcons + $iconSize + $iconPadding; + } @else if $numOfIcons == 3 { + padding-#{$side}: $iconPadding + $iconSize + $marginBetweenIcons + $iconSize + $marginBetweenIcons + $iconSize + $iconPadding; + } +} + +@mixin euiPlaceholderPerBrowser { + // stylelint-disable selector-no-vendor-prefix + // Each prefix must be its own content block + &::-webkit-input-placeholder { @content; opacity: 1; } + &::-moz-placeholder { @content; opacity: 1; } + &:-ms-input-placeholder { @content; opacity: 1; } + &:-moz-placeholder { @content; opacity: 1; } + &::placeholder { @content; opacity: 1; } +} + +@function euiFormControlGradient($color: $euiColorPrimary) { + @return linear-gradient(to top, + $color, + $color 2px, + transparent 2px, + transparent 100% + ); +} + +@mixin euiFormControlText { + @include euiFont; + font-size: $euiFontSizeS; + color: $euiTextColor; + + @include euiPlaceholderPerBrowser { + color: $euiFormControlPlaceholderText; + } +} + +@mixin euiFormControlSize( + $height: $euiFormControlHeight, + $includeAlternates: false +) { + // Default + max-width: $euiFormMaxWidth; + width: 100%; + height: $height; + + @if ($includeAlternates) { + &--fullWidth { + max-width: 100%; + } + + &--compressed { + height: $euiFormControlCompressedHeight; + } + + &--inGroup { + height: 100%; + } + } +} + +@mixin euiFormControlWithIcon($isIconOptional: false, $side: 'left', $compressed: false) { + @if ($isIconOptional) { + @at-root { + #{&}--withIcon { + @include euiFormControlLayoutPadding(1, $side, $compressed); + } + } + } @else { + @include euiFormControlLayoutPadding(1, $side, $compressed); + } +} + +@mixin euiFormControlIsLoading($isNextToIcon: false) { + @at-root { + #{&}-isLoading { + @if ($isNextToIcon) { + @include euiFormControlLayoutPadding(2); + } @else { + @include euiFormControlLayoutPadding(1); + } + } + + #{&}-isLoading#{&}--compressed { + @if ($isNextToIcon) { + @include euiFormControlLayoutPadding(2, $compressed: true); + } @else { + @include euiFormControlLayoutPadding(1, $compressed: true); + } + } + } +} + +// 1. Must supply both values to background-size or some browsers apply the single value to both directions + +@mixin euiFormControlDefaultShadow($borderOnly: false) { + background-color: $euiFormBackgroundColor; + background-repeat: no-repeat; + background-size: 0% 100%; // 1 + + @if ($borderOnly) { + box-shadow: inset 0 0 0 1px $euiFormBorderColor; + } @else { + box-shadow: + #{$euiFormControlBoxShadow}, + inset 0 0 0 1px $euiFormBorderColor; + } + + transition: + box-shadow $euiAnimSpeedFast ease-in, + background-image $euiAnimSpeedFast ease-in, + background-size $euiAnimSpeedFast ease-in, + background-color $euiAnimSpeedFast ease-in; + + // Fixes bug in Firefox where adding a transition to the background-color + // caused a flash of differently styled dropdown. + @supports (-moz-appearance: none) { + // List *must* be in the same order as the above. + transition-property: box-shadow, background-image, background-size; + } +} + +@mixin euiFormControlFocusStyle($borderOnly: false) { + background-color: tintOrShade($euiColorEmptyShade, 0%, 40%); + background-image: euiFormControlGradient(); + background-size: 100% 100%; // 1 + outline: none; // Blanket remove all outlines relying on our own bottom border + + @if ($borderOnly) { + box-shadow: inset 0 0 0 1px $euiFormBorderColor; + } @else { + box-shadow: inset 0 0 0 1px $euiFormBorderColor; + } +} + +@mixin euiFormControlInvalidStyle { + background-image: euiFormControlGradient($euiColorDanger); + background-size: 100%; +} + +@mixin euiFormControlDisabledTextStyle { + color: $euiFormControlDisabledColor; + -webkit-text-fill-color: $euiFormControlDisabledColor; // Required for Safari +} + +@mixin euiFormControlDisabledStyle { + @include euiFormControlDisabledTextStyle; + cursor: not-allowed; + background: $euiFormBackgroundDisabledColor; + box-shadow: inset 0 0 0 1px $euiFormBorderDisabledColor; + + @include euiPlaceholderPerBrowser { + color: $euiFormControlDisabledColor; + } +} + +@mixin euiFormControlReadOnlyStyle { + cursor: default; + color: $euiTextColor; + -webkit-text-fill-color: $euiTextColor; // Required for Safari + // Use transparency since there is no border and in case form is on a non-white background + background: $euiFormBackgroundReadOnlyColor; + border-color: transparent; + box-shadow: inset 0 0 0 1px $euiFormBorderDisabledColor; +} + +// 2. Override invalid state with focus state. + +@mixin euiFormControlStyle($borderOnly: false, $includeStates: true, $includeSizes: true) { + @include euiFormControlSize($includeAlternates: $includeSizes); + @include euiFormControlDefaultShadow; + @include euiFormControlText; + + border: none; + border-radius: $euiFormControlBorderRadius; + padding: $euiFormControlPadding; + + @if ($includeStates) { + &:invalid { // 2 + @include euiFormControlInvalidStyle; + } + + &:focus { // 2 + @include euiFormControlFocusStyle; + } + + &:disabled { + @include euiFormControlDisabledStyle; + } + + &[readOnly] { + @include euiFormControlReadOnlyStyle; + } + + // Needs to be set for autofill + &:-webkit-autofill { + -webkit-text-fill-color: lightOrDarkTheme($euiColorDarkestShade, $euiColorLightShade); + + ~ .euiFormControlLayoutIcons { + color: lightOrDarkTheme($euiColorDarkestShade, $euiColorLightShade); + } + } + } + + @if ($includeSizes) { + &--compressed { + @include euiFormControlStyleCompressed($borderOnly, $includeStates); + } + + &--inGroup { + // stylelint-disable-next-line declaration-no-important + box-shadow: none !important; + border-radius: 0; + } + } +} + +@mixin euiFormControlStyleCompressed($borderOnly: false, $includeStates: true) { + @include euiFormControlDefaultShadow($borderOnly: true); + padding: $euiFormControlCompressedPadding; + border-radius: $euiFormControlCompressedBorderRadius; + + @if ($includeStates) { + &:invalid { // 2 + @include euiFormControlInvalidStyle; + } + + &:focus { // 2 + @include euiFormControlFocusStyle($borderOnly: true); + } + + &:disabled { + @include euiFormControlDisabledStyle; + } + + &[readOnly] { + @include euiFormControlReadOnlyStyle; + } + } +} + +@mixin euiHiddenSelectableInput { + position: absolute; + // stylelint-disable-next-line declaration-no-important + opacity: 0 !important; // Make sure it's still hidden when :disabled + width: 100%; + height: 100%; + cursor: pointer; +} + +// Adjusts form controls border radius +@mixin euiFormControlSideBorderRadius($borderRadius, $side, $internal: false) { + @if $internal == true { + $borderRadius: $borderRadius - 1; + } + @if $side == 'left' { + border-radius: $borderRadius 0 0 $borderRadius; + } @else if $side == 'right' { + border-radius: 0 $borderRadius $borderRadius 0; + } +} diff --git a/packages/eui-common/src/global_styling/mixins/_helpers.scss b/packages/eui-common/src/global_styling/mixins/_helpers.scss new file mode 100644 index 00000000000..00688ef63ef --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_helpers.scss @@ -0,0 +1,126 @@ +// Helper mixins + +// Set scroll bar appearance on Chrome (and firefox). +@mixin euiScrollBar($thumbColor: $euiColorDarkShade, $trackBackgroundColor: transparent, $size: 'thin') { + // Firefox's scrollbar coloring cascades, but the sizing does not, + // so it's being added to this mixin for allowing support wherever custom scrollbars are + scrollbar-color: transparentize($thumbColor, .5) $trackBackgroundColor; // Firefox support + + @if ($size == 'thin') { + scrollbar-width: thin; + } + + // stylelint-disable selector-no-vendor-prefix + &::-webkit-scrollbar { + width: $euiScrollBar; + height: $euiScrollBar; + } + + &::-webkit-scrollbar-thumb { + background-color: transparentize($thumbColor, .5); + background-clip: content-box; + border-radius: $euiScrollBar; + + @if ($size == 'thin') { + border: $euiScrollBarCornerThin solid $trackBackgroundColor; + } @else { + border: $euiScrollBarCorner solid $trackBackgroundColor; + } + } + + &::-webkit-scrollbar-corner, + &::-webkit-scrollbar-track { + background-color: $trackBackgroundColor; + } +} + +/** + * 1. Focus rings shouldn't be visible on scrollable regions, but a11y requires them to be focusable. + * Browser's supporting `:focus-visible` will still show outline on keyboard focus only. + * Others like Safari, won't show anything at all. + * 2. Force the `:focus-visible` when the `tabindex=0` (is tabbable) + */ + +// Just overflow and scrollbars +@mixin euiYScroll { + @include euiScrollBar; + height: 100%; + overflow-y: auto; + overflow-x: hidden; + + &:focus { + outline: none; /* 1 */ + } + + &[tabindex='0']:focus:focus-visible { + outline-style: auto; /* 2 */ + } +} + +@mixin euiXScroll { + @include euiScrollBar; + overflow-x: auto; + + &:focus { + outline: none; /* 1 */ + } + + &[tabindex='0']:focus:focus-visible { + outline-style: auto; /* 2 */ + } +} + +// The full overflow with shadow +@mixin euiYScrollWithShadows { + @include euiYScroll; + @include euiOverflowShadow('y'); +} + +@mixin euiXScrollWithShadows { + @include euiXScroll; + @include euiOverflowShadow('x'); +} + +/** + * For quickly applying a full-height element whether using flex or not + */ +@mixin euiFullHeight { + height: 100%; + flex: 1 1 auto; + overflow: hidden; +} + +// Hiding elements offscreen to only be read by screen reader +// See https://github.com/elastic/eui/pull/5130 and https://github.com/elastic/eui/pull/5152 for more info +@mixin euiScreenReaderOnly { + // Take the element out of the layout + position: absolute; + // Keep it vertically inline + top: auto; + // Chrome requires a left value, and Selenium (used by Kibana's FTR) requires an off-screen position for its .getVisibleText() to not register SR-only text + left: -10000px; + // The element must have a size (for some screen readers) + width: 1px; + height: 1px; + // But reduce the visible size to nothing + clip: rect(0 0 0 0); + clip-path: inset(50%); + // And ensure no overflows occur + overflow: hidden; + // Chrome requires the negative margin to not cause overflows of parent containers + margin: -1px; +} + +// Doesn't have reduced motion turned on +@mixin euiCanAnimate { + @media screen and (prefers-reduced-motion: no-preference) { + @content; + } +} + +// Does have reduced motion turned on +@mixin euiCantAnimate { + @media screen and (prefers-reduced-motion: reduce) { + @content; + } +} diff --git a/packages/eui-common/src/global_styling/mixins/_index.scss b/packages/eui-common/src/global_styling/mixins/_index.scss new file mode 100644 index 00000000000..7d0cba8a92e --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_index.scss @@ -0,0 +1,14 @@ +@import 'responsive'; +@import 'shadow'; +@import 'size'; +@import 'typography'; +@import 'helpers'; +@import 'states'; + +@import 'button'; +@import 'form'; +@import 'loading'; +@import 'link'; +@import 'panel'; +@import 'range'; +@import 'tool_tip'; diff --git a/packages/eui-common/src/global_styling/mixins/_link.scss b/packages/eui-common/src/global_styling/mixins/_link.scss new file mode 100644 index 00000000000..98dac59b9cc --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_link.scss @@ -0,0 +1,11 @@ +@mixin euiLink { + text-align: left; + + &:hover { + text-decoration: underline; + } + + &:focus { + text-decoration: underline; + } +} diff --git a/packages/eui-common/src/global_styling/mixins/_loading.scss b/packages/eui-common/src/global_styling/mixins/_loading.scss new file mode 100644 index 00000000000..0f72a8433f7 --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_loading.scss @@ -0,0 +1,6 @@ +@function euiLoadingSpinnerBorderColors( + $main: $euiColorLightShade, + $highlight: $euiColorPrimary +) { + @return $highlight $main $main $main; +} diff --git a/packages/eui-common/src/global_styling/mixins/_panel.scss b/packages/eui-common/src/global_styling/mixins/_panel.scss new file mode 100644 index 00000000000..4eb0a5fb55a --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_panel.scss @@ -0,0 +1,55 @@ +@mixin euiPanel($selector) { + @if variable-exists(selector) == false { + @error 'A $selector must be provided to @mixin euiPanel().'; + } @else { + #{$selector} { + flex-grow: 1; + + &#{$selector}--flexGrowZero { + flex-grow: 0; + } + + &#{$selector}--hasShadow { + @include euiBottomShadowMedium; + } + + &#{$selector}--hasBorder { + border: $euiBorderThin; + box-shadow: none; + } + + &#{$selector}--isClickable { + // transition the shadow + transition: all $euiAnimSpeedFast $euiAnimSlightResistance; + + &:enabled { // This is a good selector for buttons since it doesn't exist on divs + // in case of button wrapper which inherently is inline-block and no width + display: block; + width: 100%; + text-align: left; + } + + &:hover, + &:focus { + @include euiBottomShadow; + transform: translateY(-2px); + cursor: pointer; + } + } + + // Border Radii + @each $modifier, $amount in $euiPanelBorderRadiusModifiers { + &#{$selector}--#{$modifier} { + border-radius: $amount; + } + } + + // Background colors + @each $modifier, $amount in $euiPanelBackgroundColorModifiers { + &#{$selector}--#{$modifier} { + background-color: $amount; + } + } + } + } +} diff --git a/packages/eui-common/src/global_styling/mixins/_range.scss b/packages/eui-common/src/global_styling/mixins/_range.scss new file mode 100644 index 00000000000..ec47e39e2d6 --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_range.scss @@ -0,0 +1,62 @@ +/* +The CSS in JS version of this file lives in: + - src/components/form/range/range.styles.ts + +The following files still use the Sass version: + - src/themes/amsterdam/overrides/_color_stops.scss + - src/themes/amsterdam/overrides/_hue.scss +*/ + +@mixin euiRangeTrackSize($compressed: false) { + height: $euiRangeTrackHeight; + width: $euiRangeTrackWidth; + + @if ($compressed) { + height: $euiRangeTrackCompressedHeight; + } +} + +@mixin euiRangeTrackPerBrowser { + &::-webkit-slider-runnable-track { @content; } + &::-moz-range-track { @content; } + &::-ms-fill-lower { @content; } + &::-ms-fill-upper { @content; } +} + +@mixin euiRangeThumbBorder { + border: 2px solid $euiRangeThumbBorderColor; +} + +@mixin euiRangeThumbBoxShadow { + box-shadow: + 0 0 0 1px $euiRangeThumbBorderColor, + 0 2px 2px -1px rgba($euiShadowColor, .2), + 0 1px 5px -2px rgba($euiShadowColor, .2); +} + +@mixin euiRangeThumbFocusBoxShadow { + box-shadow: 0 0 0 2px $euiFocusRingColor; +} + +@mixin euiRangeThumbStyle { + @include euiRangeThumbBoxShadow; + @include euiRangeThumbBorder; + cursor: pointer; + background-color: $euiRangeThumbBackgroundColor; + padding: 0; + height: $euiRangeThumbHeight; + width: $euiRangeThumbWidth; + box-sizing: border-box; // required for firefox or the border makes the width and height to increase +} + +@mixin euiRangeThumbPerBrowser { + &::-webkit-slider-thumb { @content; } + &::-moz-range-thumb { @content; } + &::-ms-thumb { @content; } +} + +@mixin euiRangeThumbFocus { + @include euiRangeThumbBorder; + @include euiRangeThumbFocusBoxShadow; + background-color: $euiColorPrimary; +} diff --git a/packages/eui-common/src/global_styling/mixins/_responsive.scss b/packages/eui-common/src/global_styling/mixins/_responsive.scss new file mode 100644 index 00000000000..0fa3a9b08a8 --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_responsive.scss @@ -0,0 +1,44 @@ +// A sem-complicated mixin for breakpoints, that takes any number of +// named breakpoints that exists in $euiBreakpoints. + +@mixin euiBreakpoint($sizes...) { + // Loop through each size parameter + @each $size in $sizes { + // Store the location of the size in the list to check against + $index: index($euiBreakpointKeys, $size); + + // Check to make sure it exists in the allowed breakpoint names + @if ( $index ) { + + // Set the min size to the value of the size + $minSize: map-get($euiBreakpoints, $size); + + // If it is the last item, don't give it a max-width + @if ( $index == length($euiBreakpointKeys) ) { + @media only screen and (min-width: $minSize) { + @content; + } + // If it's not the last item, add a max-width + } @else { + + // Set the max size to the value of the next size (-1px as to not overlap) + $maxSize: map-get($euiBreakpoints, nth($euiBreakpointKeys, $index + 1)) - 1px; + + // If it's the the first item, don't set a min-width + @if ( $index == 1 ) { + @media only screen and (max-width: $maxSize) { + @content; + } + // Otherwise it should have a min and max width + } @else { + @media only screen and (min-width: $minSize) and (max-width: $maxSize) { + @content; + } + } + } + // If it's not a known breakpoint, throw a warning + } @else { + @warn "euiBreakpoint(): '#{$size}' is not a valid size in $euiBreakpoints. Accepted values are '#{$euiBreakpointKeys}'"; + } + } +} diff --git a/packages/eui-common/src/global_styling/mixins/_shadow.scss b/packages/eui-common/src/global_styling/mixins/_shadow.scss new file mode 100644 index 00000000000..1bc64eb085b --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_shadow.scss @@ -0,0 +1,108 @@ +@function shadowOpacity($opacity) { + @if (lightness($euiTextColor) < 50) { + @return $opacity * 1; + } @else { + @return $opacity * 2.5; + } +} + +@mixin euiSlightShadow($color: $euiShadowColor) { + box-shadow: + 0 .8px .8px rgba($color, shadowOpacity(.04)), + 0 2.3px 2px rgba($color, shadowOpacity(.03)); +} + +@mixin euiBottomShadowSmall($color: $euiShadowColor) { + box-shadow: + 0 .7px 1.4px rgba($color, shadowOpacity(.07)), + 0 1.9px 4px rgba($color, shadowOpacity(.05)), + 0 4.5px 10px rgba($color, shadowOpacity(.05)); +} + +@mixin euiBottomShadowMedium($color: $euiShadowColor) { + box-shadow: + 0 .9px 4px -1px rgba($color, shadowOpacity(.08)), + 0 2.6px 8px -1px rgba($color, shadowOpacity(.06)), + 0 5.7px 12px -1px rgba($color, shadowOpacity(.05)), + 0 15px 15px -1px rgba($color, shadowOpacity(.04)); +} + +// Similar to shadow medium but without the bottom depth. Useful for popovers +// that drop UP rather than DOWN. +@mixin euiBottomShadowFlat($color: $euiShadowColor) { + box-shadow: + 0 0 .8px rgba($color, shadowOpacity(.06)), + 0 0 2px rgba($color, shadowOpacity(.04)), + 0 0 5px rgba($color, shadowOpacity(.04)), + 0 0 17px rgba($color, shadowOpacity(.03)); +} + +@mixin euiBottomShadow($color: $euiShadowColor) { + box-shadow: + 0 1px 5px rgba($color, shadowOpacity(.1)), + 0 3.6px 13px rgba($color, shadowOpacity(.07)), + 0 8.4px 23px rgba($color, shadowOpacity(.06)), + 0 23px 35px rgba($color, shadowOpacity(.05)); +} + +@mixin euiBottomShadowLarge( + $color: $euiShadowColor, + $opacity: 0, + $reverse: false +) { + @if ($reverse) { + box-shadow: + 0 -2.7px 9px rgba($color, shadowOpacity(.13)), + 0 -9.4px 24px rgba($color, shadowOpacity(.09)), + 0 -21.8px 43px rgba($color, shadowOpacity(.08)); + } @else { + box-shadow: + 0 2.7px 9px rgba($color, shadowOpacity(.13)), + 0 9.4px 24px rgba($color, shadowOpacity(.09)), + 0 21.8px 43px rgba($color, shadowOpacity(.08)); + } +} + +@mixin euiSlightShadowHover($color: $euiShadowColor) { + box-shadow: + 0 1px 5px rgba($color, shadowOpacity(.1)), + 0 3.6px 13px rgba($color, shadowOpacity(.07)), + 0 8.4px 23px rgba($color, shadowOpacity(.06)), + 0 23px 35px rgba($color, shadowOpacity(.05)); +} + +// stylelint-disable color-named +@mixin euiOverflowShadow($direction: 'y', $side: 'both') { + $hideHeight: $euiScrollBarCornerThin * 1.25; + $gradient: null; + $gradientStart: + transparentize(red, .9) 0%, + transparentize(red, 0) $hideHeight; + $gradientEnd: + transparentize(red, 0) calc(100% - #{$hideHeight}), + transparentize(red, .9) 100%; + @if ($side == 'both' or $side == 'start' or $side == 'end') { + @if ($side == 'both') { + $gradient: $gradientStart, $gradientEnd; + } @else if ($side == 'start') { + $gradient: $gradientStart; + } @else { + $gradient: $gradientEnd; + } + } @else { + @warn "euiOverflowShadow() expects side to be 'both', 'start' or 'end' but got '#{$side}'"; + } + + @if ($direction == 'y') { + mask-image: linear-gradient(to bottom, #{$gradient}); + } @else if ($direction == 'x') { + mask-image: linear-gradient(to right, #{$gradient}); + } @else { + @warn "euiOverflowShadow() expects direction to be 'y' or 'x' but got '#{$direction}'"; + } + + // Chrome+Edge has a very bizarre edge case bug where `mask-image` stops working + // This workaround forces a stacking context on the scrolling container, which + // hopefully addresses the bug. @see https://github.com/elastic/eui/pull/7855 + transform: translateZ(0); +} diff --git a/packages/eui-common/src/global_styling/mixins/_size.scss b/packages/eui-common/src/global_styling/mixins/_size.scss new file mode 100644 index 00000000000..809dc870bf8 --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_size.scss @@ -0,0 +1,4 @@ +@mixin size($size) { + width: $size; + height: $size; +} diff --git a/packages/eui-common/src/global_styling/mixins/_states.scss b/packages/eui-common/src/global_styling/mixins/_states.scss new file mode 100644 index 00000000000..a2d1bc83aef --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_states.scss @@ -0,0 +1,50 @@ +@mixin euiFocusRing($size: 'small', $amsterdamOnlyProp: null) { + @if $size == 'large' { + // It's always OK to use the focus animation. This will take precedence over times we turn it off individually like EuiButtonEmpty + // stylelint-disable-next-line declaration-no-important + animation: $euiAnimSpeedSlow $euiAnimSlightResistance 1 normal forwards focusRingAnimateLarge !important; + } @else { + // stylelint-disable-next-line declaration-no-important + animation: $euiAnimSpeedSlow $euiAnimSlightResistance 1 normal forwards focusRingAnimate !important; + } +} + +// Keyframe animation declarations can be found in +// utility/animations.scss + +@mixin euiFocusBackground($color: $euiColorPrimary) { + background-color: tintOrShade($euiColorPrimary, ((1 - $euiFocusTransparency) * 100%), ((1 - $euiFocusTransparency) * 100%)); +} + +@mixin euiHoverState { + cursor: pointer; + text-decoration: underline; +} + +@mixin euiFocusState($color: $euiColorPrimary) { + @include euiHoverState; + @include euiFocusBackground($color); +} + +@mixin euiDisabledState($color: $euiButtonColorDisabledText) { + cursor: not-allowed; + text-decoration: none; + + @if ($color) { + color: $color; + } +} + +@mixin euiInteractiveStates($focusColor: $euiColorPrimary, $disabledColor: $euiButtonColorDisabledText) { + &:hover { + @include euiHoverState; + } + + &:focus { + @include euiFocusState($focusColor); + } + + &:disabled { + @include euiDisabledState($disabledColor); + } +} diff --git a/packages/eui-common/src/global_styling/mixins/_tool_tip.scss b/packages/eui-common/src/global_styling/mixins/_tool_tip.scss new file mode 100644 index 00000000000..83b062274dc --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_tool_tip.scss @@ -0,0 +1,25 @@ +@mixin euiToolTipStyle($size: null) { + @include euiBottomShadow($color: $euiColorInk); + border-radius: $euiBorderRadius; + background-color: $euiTooltipBackgroundColor; + color: $euiColorGhost; + z-index: $euiZLevel9; + max-width: 256px; + overflow-wrap: break-word; + padding: $euiSizeS; + + .euiHorizontalRule { + background-color: $euiTooltipBorderColor; + } +} + +@mixin euiToolTipTitle { + font-weight: $euiFontWeightBold; + border-bottom: solid $euiBorderWidthThin $euiTooltipBorderColor; + padding-bottom: $euiSizeXS; + margin-bottom: $euiSizeXS; +} + +@mixin euiToolTipAnimation($side: 'top') { + animation: #{map-get($euiTooltipAnimations, $side)} $euiAnimSpeedSlow ease-out 0s forwards; +} diff --git a/packages/eui-common/src/global_styling/mixins/_typography.scss b/packages/eui-common/src/global_styling/mixins/_typography.scss new file mode 100644 index 00000000000..7090f0e2371 --- /dev/null +++ b/packages/eui-common/src/global_styling/mixins/_typography.scss @@ -0,0 +1,167 @@ +// stylelint-disable property-no-vendor-prefix +// stylelint-disable declaration-no-important + +@function fontSizeToRemOrEm($size, $sizingMethod: 'rem') { + @if ($sizingMethod == 'rem') { + @return #{$size / $euiFontSize}rem; + } @else if ($sizingMethod == 'em') { + @return #{$size / $euiFontSize}em; + } +} + +// It can also be applied to calculate paddings +@function marginToRemOrEm($elementSize, $elementFontSize, $sizingMethod: 'rem') { + @if ($sizingMethod == 'rem') { + @return #{$elementSize / $euiFontSize}rem; + } @else if ($sizingMethod == 'em') { + @return #{$elementSize / $elementFontSize}em; + } +} + +// Spit out rem and px +@mixin fontSize($size: $euiFontSize, $sizingMethod: 'rem') { + @if ($sizingMethod == 'rem') { + font-size: $size; + font-size: fontSizeToRemOrEm($size, 'rem'); + } @else if ($sizingMethod == 'em') { + font-size: fontSizeToRemOrEm($size, 'em'); + } +} + +@mixin lineHeightFromBaseline($multiplier: 3) { + line-height: lineHeightFromBaseline($multiplier); +} + +// Some mixins that help us deal with browser scaling of text more consistently. +// Essentially, fonts across eui should scale against the root html element, not +// against parent inheritance. + +// Our base fonts + +@mixin euiFont { + font-family: $euiFontFamily; + font-weight: $euiFontWeightRegular; + letter-spacing: -.005em; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + font-kerning: normal; +} + +@mixin euiCodeFont { + font-family: $euiCodeFontFamily; + letter-spacing: normal; +} + +@mixin euiText { + color: $euiTextColor; + font-weight: $euiFontWeightRegular; +} + +@mixin euiTitle($size: 'm') { + @include euiTextBreakWord; + color: $euiTitleColor; + + @if (map-has-key($euiTitles, $size)) { + @each $property, $value in map-get($euiTitles, $size) { + @if ($property == 'font-size') { + @include fontSize($value); + } @else { + #{$property}: $value; + } + } + } @else { + @include fontSize($size); + @include lineHeightFromBaseline(3); + } +} + +// Font sizing extends, using rem mixin + +@mixin euiFontSizeXS { + @include fontSize($euiFontSizeXS); + line-height: $euiLineHeight; +} + +@mixin euiFontSizeS { + @include fontSize($euiFontSizeS); + line-height: $euiLineHeight; +} + +@mixin euiFontSize { + @include fontSize($euiFontSize); + line-height: $euiLineHeight; +} + +@mixin euiFontSizeM { + @include fontSize($euiFontSizeM); + line-height: $euiLineHeight; +} + +@mixin euiFontSizeL { + @include fontSize($euiFontSizeL); + line-height: $euiLineHeight; +} + +@mixin euiFontSizeXL { + @each $property, $value in map-get($euiTitles, 'm') { + @if ($property == 'font-size') { + @include fontSize($value); + } @else { + #{$property}: $value; + } + } + line-height: 1.25; +} + +@mixin euiFontSizeXXL { + @each $property, $value in map-get($euiTitles, 'l') { + @if ($property == 'font-size') { + @include fontSize($value); + } @else { + #{$property}: $value; + } + } + line-height: 1.25; +} + +@mixin euiTextBreakWord { + // https://css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/ + overflow-wrap: break-word !important; // makes sure the long string will wrap and not bust out of the container + word-break: break-word; +} + +/** + * Text truncation + * + * Prevent text from wrapping onto multiple lines, and truncate with an ellipsis. + * + * 1. Ensure that the node has a maximum width after which truncation can occur. + */ +@mixin euiTextTruncate { + max-width: 100%; // 1 + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +@mixin euiNumberFormat { + font-feature-settings: $euiFontFeatureSettings, 'tnum' 1; // Fixed-width numbers for tabular data +} + +/** + * Text weight shifting + * + * When changing the font-weight based the state of the component + * this mixin will ensure that the sizing is dependent on the boldest + * weight so it doesn't shifter sibling content. + */ +@mixin euiTextShift($fontWeight: $euiFontWeightBold, $attr: 'data-text') { + &::after { + display: block; + content: attr(#{$attr}); + font-weight: $fontWeight; + height: 0; + overflow: hidden; + visibility: hidden; + } +} diff --git a/packages/eui-common/src/global_styling/react_date_picker/_date_picker.scss b/packages/eui-common/src/global_styling/react_date_picker/_date_picker.scss new file mode 100644 index 00000000000..84208a3a648 --- /dev/null +++ b/packages/eui-common/src/global_styling/react_date_picker/_date_picker.scss @@ -0,0 +1,772 @@ +/* This file is a heavy retheme of react-datepicker's Sass as of v1.4.0 +** https://github.com/Hacker0x01/react-datepicker +** +** In places where features were disabled, I've commented out the original Sass +** selectors rather than removing it so we can better understand what's changed. +** Commented out selectors that don't have properties indicate that we are not +** using those dom elements for styling of any kind. For example, react-datepicker +** has lots of pointer arrows attached to its popovers, but we choose not to render +** then in any way. +** +** Similarly, you will also find several times where we use display: none to +** completely remove extraneous UI (they had some overly obvious legends for example). +*/ + + +// Because we don't have control over react-datepicker's dom we use SVG URIs for the navigation arrows. +// There is one for light and dark. +@mixin datePickerArrow { + background-position: center; + @if (lightness($euiColorEmptyShade) > 50) { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiI+ICA8ZGVmcz4gICAgPHBhdGggaWQ9ImFycm93X2Rvd24tYSIgZD0iTTEzLjA2ODg1MDgsNS4xNTcyNTAzOCBMOC4zODQyMzk3NSw5Ljc2ODI3NDI4IEM4LjE3MDU0NDE1LDkuOTc4NjEzMDggNy44Mjk5OTIxNCw5Ljk3OTE0MDk1IDcuNjE1NzYwMjUsOS43NjgyNzQyOCBMMi45MzExNDkxNSw1LjE1NzI1MDM4IEMyLjcxODEzNTksNC45NDc1ODMyMSAyLjM3Mjc3MzE5LDQuOTQ3NTgzMjEgMi4xNTk3NTk5NCw1LjE1NzI1MDM4IEMxLjk0Njc0NjY5LDUuMzY2OTE3NTYgMS45NDY3NDY2OSw1LjcwNjg1NTIyIDIuMTU5NzU5OTQsNS45MTY1MjI0IEw2Ljg0NDM3MTA0LDEwLjUyNzU0NjMgQzcuNDg1MTc0MjQsMTEuMTU4MjgzNiA4LjUxNjQ0OTc5LDExLjE1NjY4NTEgOS4xNTU2Mjg5NiwxMC41Mjc1NDYzIEwxMy44NDAyNDAxLDUuOTE2NTIyNCBDMTQuMDUzMjUzMyw1LjcwNjg1NTIyIDE0LjA1MzI1MzMsNS4zNjY5MTc1NiAxMy44NDAyNDAxLDUuMTU3MjUwMzggQzEzLjYyNzIyNjgsNC45NDc1ODMyMSAxMy4yODE4NjQxLDQuOTQ3NTgzMjEgMTMuMDY4ODUwOCw1LjE1NzI1MDM4IFoiLz4gIDwvZGVmcz4gIDxnIGZpbGwtcnVsZT0iZXZlbm9kZCI+ICAgIDx1c2UgZmlsbC1ydWxlPSJub256ZXJvIiB4bGluazpocmVmPSIjYXJyb3dfZG93bi1hIi8+ICA8L2c+PC9zdmc+); + } @else { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiI+ICA8ZGVmcz4gICAgPHBhdGggaWQ9ImRvd25hcnJvd3doaXRlLWEiIGQ9Ik0xMy4wNjg4NTA4LDUuMTU3MjUwMzggTDguMzg0MjM5NzUsOS43NjgyNzQyOCBDOC4xNzA1NDQxNSw5Ljk3ODYxMzA4IDcuODI5OTkyMTQsOS45NzkxNDA5NSA3LjYxNTc2MDI1LDkuNzY4Mjc0MjggTDIuOTMxMTQ5MTUsNS4xNTcyNTAzOCBDMi43MTgxMzU5LDQuOTQ3NTgzMjEgMi4zNzI3NzMxOSw0Ljk0NzU4MzIxIDIuMTU5NzU5OTQsNS4xNTcyNTAzOCBDMS45NDY3NDY2OSw1LjM2NjkxNzU2IDEuOTQ2NzQ2NjksNS43MDY4NTUyMiAyLjE1OTc1OTk0LDUuOTE2NTIyNCBMNi44NDQzNzEwNCwxMC41Mjc1NDYzIEM3LjQ4NTE3NDI0LDExLjE1ODI4MzYgOC41MTY0NDk3OSwxMS4xNTY2ODUxIDkuMTU1NjI4OTYsMTAuNTI3NTQ2MyBMMTMuODQwMjQwMSw1LjkxNjUyMjQgQzE0LjA1MzI1MzMsNS43MDY4NTUyMiAxNC4wNTMyNTMzLDUuMzY2OTE3NTYgMTMuODQwMjQwMSw1LjE1NzI1MDM4IEMxMy42MjcyMjY4LDQuOTQ3NTgzMjEgMTMuMjgxODY0MSw0Ljk0NzU4MzIxIDEzLjA2ODg1MDgsNS4xNTcyNTAzOCBaIi8+ICA8L2RlZnM+ICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICA8dXNlIGZpbGw9IiNGRkYiIGZpbGwtcnVsZT0ibm9uemVybyIgeGxpbms6aHJlZj0iI2Rvd25hcnJvd3doaXRlLWEiLz4gIDwvZz48L3N2Zz4=); + } +} + +// The only "new" css in this component is a wrapper class for dealing with shadows. +// This is mostly here so that we can provide an inline version that doesn't have the +// shadows and depth. +.euiDatePicker { + .euiFormControlLayout { + height: auto; + } + + &.euiDatePicker--shadow { + .react-datepicker-popper { + @include euiBottomShadowMedium; + + border: $euiBorderThin; + background-color: $euiColorEmptyShade; + border-radius: 0 0 $euiBorderRadius $euiBorderRadius; + } + + // If the shadow is on, and it is inline, we need to put the shadow on the datepicker + // itself rather than the popper. + &.euiDatePicker--inline { + .react-datepicker { + @include euiBottomShadowMedium; + + border: $euiBorderThin; + background-color: $euiColorEmptyShade; + border-radius: $euiBorderRadius; + } + } + } +} + +// .react-datepicker-wrapper { +// } + +.react-datepicker { + @include euiFont; + font-size: $euiFontSizeXS; + color: $euiColorFullShade; + display: flex; + position: relative; + border-radius: $euiBorderRadius; +} + +// When in time only mode we make the dropdown look more like the combo box styling. +.react-datepicker--time-only { + + .react-datepicker__time-container { + + .react-datepicker__time { + + .react-datepicker__time-box { + width: 100%; + + .react-datepicker__time-list li.react-datepicker__time-list-item { + font-size: $euiFontSizeS; + text-align: left; + padding-left: $euiSizeXL + $euiSizeXS; + padding-right: $euiSizeXL + $euiSizeXS; + color: $euiTextColor; + + &.react-datepicker__time-list-item--selected { + color: $euiColorGhost; + } + + &.react-datepicker__time-list-item--disabled{ + color: $euiColorDisabledText + } + } + } + } + } + + + .react-datepicker__time-container { + border-left: 0; + } + + // .react-datepicker__triangle { + // } + // .react-datepicker__time { + // } + // .react-datepicker__time-box { + // } +} + +// .react-datepicker__triangle { +// } + +.euiDatePicker.euiDatePicker--shadow .react-datepicker-popper { + z-index: $euiZContentMenu; + animation: euiAnimFadeIn $euiAnimSpeedFast ease-in; + + &[data-placement^="bottom"] { + + // .react-datepicker__triangle { + // } + } + + &[data-placement^="top"] { + @include euiBottomShadowFlat; + + border-radius: $euiBorderRadius $euiBorderRadius 0 0; + + // .react-datepicker__triangle { + // } + } + + &[data-placement^="right"] { + margin-left: 0; + + // .react-datepicker__triangle { + // } + } + + &[data-placement^="left"] { + margin-right: 0; + + // .react-datepicker__triangle { + // } + } +} + +.react-datepicker__header { + text-align: center; + border-top-left-radius: $euiBorderRadius; + border-top-right-radius: $euiBorderRadius; + + &--time { + display: none; + } +} + +.react-datepicker__header__dropdown { + padding: $euiSize 0 $euiSizeS 0; +} + +.react-datepicker__year-dropdown-container--select, +.react-datepicker__month-dropdown-container--select, +.react-datepicker__month-year-dropdown-container--select, +.react-datepicker__year-dropdown-container--scroll, +.react-datepicker__month-dropdown-container--scroll, +.react-datepicker__month-year-dropdown-container--scroll { + display: inline-block; + margin: 0 $euiSizeXS; +} + +.react-datepicker__current-month, +.react-datepicker-time__header { + display: none; +} + +.react-datepicker-time__header { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.react-datepicker__navigation { + cursor: pointer; + position: absolute; + // Pixel pushing because these are icons against text + top: $euiSize + ($euiSizeXS / 2); + width: 0; + padding: 0; + z-index: 1; + text-indent: -999em; + overflow: hidden; + + &--previous { + @include datePickerArrow; + left: $euiSize + $euiSizeXS; + height: $euiSize; + width: $euiSize; + transform: rotate(90deg); + transition: transform $euiAnimSpeedExtraFast ease-in-out; + + &:hover, &:focus { + border-radius: $euiBorderRadius; + transform: scale(1.2) rotate(90deg); + } + + &:hover { + background-color: $euiColorLightestShade; + box-shadow: 0 0 0 ($euiSizeXS / 2) $euiColorLightestShade; + } + + &:focus { + background-color: $euiFocusBackgroundColor; + box-shadow: 0 0 0 ($euiSizeXS / 2) $euiFocusBackgroundColor; + } + + &--disabled, + &--disabled:hover { + cursor: not-allowed ; + opacity: .2; + } + } + + &--next { + @include datePickerArrow; + // Pixel value because of some padding on the icon + right: 20px; + height: $euiSize; + width: $euiSize; + transform: rotate(-90deg); + + &--with-time:not(&--with-today-button) { + // This a pixel value against the width of the cal. It needs + // to be left because the timepicker adds more width + left: 248px; + } + + &:hover, &:focus { + border-radius: $euiBorderRadius; + transform: scale(1.2) rotate(-90deg); + } + + &:hover { + background-color: $euiColorLightestShade; + box-shadow: 0 0 0 ($euiSizeXS / 2) $euiColorLightestShade; + } + + &:focus { + background-color: $euiFocusBackgroundColor; + box-shadow: 0 0 0 ($euiSizeXS / 2) $euiFocusBackgroundColor; + } + + &--disabled, + &--disabled:hover { + cursor: not-allowed ; + opacity: .2; + } + } + + &--years { + position: relative; + top: 0; + display: block; + margin-left: auto; + margin-right: auto; + + &-previous { + top: $euiSizeXS; + border-top-color: $euiColorLightestShade; + + &:hover { + border-top-color: darken($euiColorLightestShade, 10%); + } + } + + &-upcoming { + top: -$euiSizeXS; + border-bottom-color: $euiColorLightestShade; + + &:hover { + border-bottom-color: darken($euiColorLightestShade, 10%); + } + } + } +} + +// .react-datepicker__month-container { +// } + +.react-datepicker__month { + margin: 0 $euiSize $euiSize $euiSize; + text-align: center; + border-radius: $euiBorderRadius; +} + +.react-datepicker__time-container { + border-left: $euiBorderColor; + width: auto; + display: flex; + padding: $euiSize 0; + border-radius: 0 $euiBorderRadius $euiBorderRadius 0; + flex-grow: 1; + + // &--with-today-button { + // } + + .react-datepicker__time { + position: relative; + flex-grow: 1; + display: flex; + padding-left: $euiSizeXS; + flex-direction: column; + + .react-datepicker__time-box { + width: auto; + display: flex; + flex-direction: column; + flex-grow: 1; + + ul.react-datepicker__time-list { + @include euiScrollBar; + height: 204px !important; + display: flex; + flex-direction: column; + flex-grow: 1; + overflow-y: auto; + align-items: center; + + li.react-datepicker__time-list-item { + padding: $euiSizeXS $euiSizeS; + margin-bottom: $euiSizeXS; + text-align: right; + color: $euiColorDarkShade; + white-space: nowrap; + // IE needs this to fix collapsing flex + line-height: $euiSizeM; + + &:hover, + &:focus { + cursor: pointer; + text-decoration: underline; + } + &--selected { + background-color: $euiColorPrimary; + color: white; + border-radius: $euiBorderRadius / 2; + &:hover { + background-color: $euiColorPrimary; + } + } + &--disabled { + color: $euiColorLightShade; + + &:hover { + cursor: not-allowed; + text-decoration: none; + background-color: transparent; + } + } + } + } + } + } +} + +.react-datepicker__week-number { + color: $euiColorLightestShade; + display: inline-block; + width: $euiSizeXL; + line-height: $euiSizeXL - $euiSizeXS; + text-align: center; + margin: 0 $euiSizeXS; + &.react-datepicker__week-number--clickable { + cursor: pointer; + &:hover { + border-radius: $euiBorderRadius; + background-color: $euiColorEmptyShade; + } + } +} + +.react-datepicker__day-names, +.react-datepicker__week { + white-space: nowrap; +} + +.react-datepicker__day-name, +.react-datepicker__day, +.react-datepicker__time-name { + color: $euiColorFullShade; + display: inline-block; + width: $euiSizeXL; + line-height: $euiSizeXL - $euiSizeXS; + text-align: center; + margin: 0 $euiSizeXS / 2; +} + +.react-datepicker__day-name { + color: $euiColorDarkShade; + text-transform: uppercase; +} + +.react-datepicker__day { + cursor: pointer; + border: solid 2px transparent; + transition: transform $euiAnimSpeedExtraFast ease-in-out; + + &:hover:not(&--disabled) { + text-decoration: underline; + font-weight: $euiFontWeightBold; + transform: scale(1.2); + } + + &--today { + font-weight: bold; + color: $euiColorPrimary; + } + &--outside-month { + color: $euiColorDarkShade; + } + + &--highlighted { + border-radius: $euiBorderRadius; + background-color: $euiColorSuccess; + color: $euiColorGhost; + + &:hover { + background-color: darken($euiColorSuccess, 5%); + } + } + + &--in-range { + background-color: transparentize($euiColorPrimary, .9); + color: $euiColorFullShade; + border-radius: 0; + border-top: solid 6px $euiColorEmptyShade; + border-bottom: solid 6px $euiColorEmptyShade; + border-right: none; + border-left: none; + line-height: $euiSizeL - $euiSizeXS; + } + + &--selected, + &--in-selecting-range { + height: $euiSizeXL; + margin: 0 $euiSizeXS / 2; + border-radius: $euiBorderRadius; + background-color: $euiColorPrimary; + line-height: $euiSizeL + $euiSizeXS; + border: solid $euiSizeXS / 2 $euiColorPrimary; + color: $euiColorGhost; + + &:hover { + background-color: darken($euiColorPrimary, 5%); + } + } + + &--keyboard-selected { + border-radius: $euiBorderRadius; + border: solid $euiSizeXS / 2 $euiColorPrimary; + font-weight: $euiFontWeightBold; + + &:hover { + background-color: darken($euiColorPrimary, 5%); + color: $euiColorGhost; + } + } + + &--in-selecting-range:not(&--in-range) { + background-color: rgba($euiColorPrimary, 0.5); + } + + &--in-range:not(&--in-selecting-range) { + .react-datepicker__month--selecting-range & { + background-color: $euiColorEmptyShade; + color: $euiColorFullShade; + } + } + + &--disabled { + cursor: not-allowed; + color: $euiColorLightShade; + + &:hover { + background-color: transparent; + } + } +} + +.react-datepicker__input-container { + position: relative; +} + +.react-datepicker__year-read-view { + font-weight: $euiFontWeightLight; + color: $euiColorDarkShade; +} + +.react-datepicker__month-read-view { + font-weight: $euiFontWeightMedium; +} + +.react-datepicker__year-read-view, +.react-datepicker__month-read-view, +.react-datepicker__month-year-read-view { + font-size: $euiFontSizeL; + + &:hover { + cursor: pointer; + color: $euiColorPrimary; + + .react-datepicker__year-read-view--down-arrow, + .react-datepicker__month-read-view--down-arrow { + border-top-color: darken($euiColorLightestShade, 10%); + } + } + + &--down-arrow { + display: none; + } +} + +.react-datepicker__year-dropdown, +.react-datepicker__month-dropdown, +.react-datepicker__month-year-dropdown { + background-color: $euiColorEmptyShade; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + bottom: 0; + right: 0; + z-index: 1; + text-align: center; + border-radius: $euiBorderRadius; + display: flex; + flex-wrap: wrap; + animation: euiAnimFadeIn $euiAnimSpeedFast ease-in; + align-content: space-around; + align-items: center; + padding: $euiSizeS; + + + &:hover { + cursor: pointer; + } + + // &--scrollable { + // height: 150px; + // overflow-y: scroll; + // } +} + +// Strike that, reverse it Willy Wonka style +.react-datepicker__year-dropdown { + flex-wrap: wrap-reverse; + flex-direction: row-reverse; + justify-content: flex-end; +} + +.react-datepicker__year-option, +.react-datepicker__month-option, +.react-datepicker__month-year-option { + font-size: $euiFontSizeXS; + padding: $euiSizeS; + color: $euiColorDarkestShade; + flex-basis: 33.3%; + + &:first-of-type { + border-top-left-radius: $euiBorderRadius; + border-top-right-radius: $euiBorderRadius; + } + + &:last-of-type { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-bottom-left-radius: $euiBorderRadius; + border-bottom-right-radius: $euiBorderRadius; + } + + &:hover { + background-color: $euiColorLightestShade; + + .react-datepicker__navigation--years-upcoming { + border-bottom-color: darken($euiColorLightestShade, 10%); + } + + .react-datepicker__navigation--years-previous { + border-top-color: darken($euiColorLightestShade, 10%); + } + } + + &--selected { + display: none; + } +} + +.react-datepicker__screenReaderOnly { + position: absolute; + left: -10000px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; +} + +.react-datepicker__year-option--preselected, +.react-datepicker__month-option--preselected { + background: $euiFocusBackgroundColor; +} + +.react-datepicker__year-option--selected_year.react-datepicker__year-option--preselected, +.react-datepicker__month-option--selected_month.react-datepicker__month-option--preselected{ + background: $euiColorPrimary; +} + +.react-datepicker__time-list-item--preselected, +.react-datepicker__year-option--preselected, +.react-datepicker__month-option--preselected { + background: darken($euiFocusBackgroundColor, 5%); +} + +.react-datepicker__time-container--focus { + background: $euiFocusBackgroundColor; +} + +.react-datepicker__month-read-view:focus, +.react-datepicker__year-read-view:focus { + text-decoration: underline; +} + +.react-datepicker__month--accessible:focus { + background: $euiFocusBackgroundColor; + + .react-datepicker__day--in-range:not(.react-datepicker__day--selected) { + border-top-color: $euiFocusBackgroundColor; + border-bottom-color: $euiFocusBackgroundColor; + } +} +.react-datepicker__navigation:focus { + background-color: $euiFocusBackgroundColor; +} + +// These selectors are not a typo. react-datepicker has a bug where these selectors +// output as "--selected_year". Sass has trouble compiling .--selected_year, so instead +// we use this generic selector get around it. +.react-datepicker__year-option--selected_year, +.react-datepicker__month-option--selected_month { + background: $euiColorPrimary; + color: $euiColorEmptyShade; + font-weight: $euiFontWeightBold; + border-radius: $euiBorderRadius; +} + +.react-datepicker__focusTrap { + display: flex; +} + +// The below is for the portal version of react-datepicker which we do not use. +// It is shown here just to know what their baseline includes. + +// .react-datepicker__close-icon { +// background-color: transparent; +// border: 0; +// cursor: pointer; +// display: inline-block; +// height: 0; +// outline: 0; +// padding: 0; +// vertical-align: middle; +// +// &::after { +// background-color: $euiColorPrimary; +// border-radius: 50%; +// bottom: 0; +// box-sizing: border-box; +// color: #fff; +// content: "\00d7"; +// cursor: pointer; +// font-size: 12px; +// height: 16px; +// width: 16px; +// line-height: 1; +// margin: -8px auto 0; +// padding: 2px; +// position: absolute; +// right: 7px; +// text-align: center; +// top: 50%; +// } +// } +// +// .react-datepicker__today-button { +// background: $euiColorEmptyShade; +// border-top: 1px solid $euiBorderColor; +// cursor: pointer; +// text-align: center; +// font-weight: bold; +// padding: 5px 0; +// clear: left; +// } +// +// .react-datepicker__portal { +// position: fixed; +// width: 100vw; +// height: 100vh; +// background-color: rgba(0, 0, 0, 0.8); +// left: 0; +// top: 0; +// justify-content: center; +// align-items: center; +// display: flex; +// z-index: 2147483647; +// +// .react-datepicker__day-name, +// .react-datepicker__day, +// .react-datepicker__time-name { +// width: 3rem; +// line-height: 3rem; +// } +// +// // Resize for small screens +// @media (max-width: 400px), (max-height: 550px) { +// .react-datepicker__day-name, +// .react-datepicker__day, +// .react-datepicker__time-name { +// width: 2rem; +// line-height: 2rem; +// } +// } +// +// .react-datepicker__current-month, +// .react-datepicker-time__header { +// font-size: $euiFontSizeXS * 1.8; +// } +// +// .react-datepicker__navigation { +// border: 1.8 * $euiSize solid transparent; +// } +// +// .react-datepicker__navigation--previous { +// border-right-color: $euiColorLightestShade; +// +// &:hover { +// border-right-color: darken($euiColorLightestShade, 10%); +// } +// +// &--disabled, +// &--disabled:hover { +// border-right-color: $datepicker__navigation-disabled-color; +// cursor: default; +// } +// } +// +// .react-datepicker__navigation--next { +// border-left-color: $euiColorLightestShade; +// +// &:hover { +// border-left-color: darken($euiColorLightestShade, 10%); +// } +// +// &--disabled, +// &--disabled:hover { +// border-left-color: $datepicker__navigation-disabled-color; +// cursor: default; +// } +// } +// } diff --git a/packages/eui-common/src/global_styling/react_date_picker/_index.scss b/packages/eui-common/src/global_styling/react_date_picker/_index.scss new file mode 100644 index 00000000000..48ea2f99771 --- /dev/null +++ b/packages/eui-common/src/global_styling/react_date_picker/_index.scss @@ -0,0 +1,2 @@ +@import 'variables'; +@import 'date_picker'; diff --git a/packages/eui-common/src/global_styling/react_date_picker/_variables.scss b/packages/eui-common/src/global_styling/react_date_picker/_variables.scss new file mode 100644 index 00000000000..6a5abd4e528 --- /dev/null +++ b/packages/eui-common/src/global_styling/react_date_picker/_variables.scss @@ -0,0 +1 @@ +$euiDatePickerCalendarWidth: 284px; \ No newline at end of file diff --git a/packages/eui-common/src/global_styling/utility/_animations.scss b/packages/eui-common/src/global_styling/utility/_animations.scss new file mode 100644 index 00000000000..c0cb6e7365a --- /dev/null +++ b/packages/eui-common/src/global_styling/utility/_animations.scss @@ -0,0 +1,55 @@ +// Animations as utility so they don't get duplicated in compiled CSS + +@keyframes euiAnimFadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes euiGrow { + 0% { + opacity: 0; + } + + 1% { + opacity: 0; + transform: scale(0); + } + + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes focusRingAnimate { + 0% { + box-shadow: 0 0 0 $euiFocusRingAnimStartSize $euiFocusRingAnimStartColor; + } + + 100% { + box-shadow: 0 0 0 $euiFocusRingSize $euiFocusRingColor; + } +} + +@keyframes focusRingAnimateLarge { + 0% { + box-shadow: 0 0 0 $euiFocusRingAnimStartSizeLarge $euiFocusRingAnimStartColor; + } + + 100% { + box-shadow: 0 0 0 $euiFocusRingSizeLarge $euiFocusRingColor; + } +} + +// Component specific + +@keyframes euiButtonActive { + 50% { + transform: translateY(1px); + } +} diff --git a/packages/eui-common/src/global_styling/utility/_index.scss b/packages/eui-common/src/global_styling/utility/_index.scss new file mode 100644 index 00000000000..5c978807848 --- /dev/null +++ b/packages/eui-common/src/global_styling/utility/_index.scss @@ -0,0 +1 @@ +@import 'animations'; diff --git a/packages/eui-theme-berlin/src/theme_dark.scss b/packages/eui-theme-berlin/src/theme_dark.scss index d5710063a18..52507d8984a 100644 --- a/packages/eui-theme-berlin/src/theme_dark.scss +++ b/packages/eui-theme-berlin/src/theme_dark.scss @@ -2,4 +2,5 @@ @import './variables/colors_dark'; // Global styling -@import './variables/index'; \ No newline at end of file +@import './variables/index'; +@import 'node_modules/@elastic/eui-common/src/global_styling/index'; \ No newline at end of file diff --git a/packages/eui-theme-berlin/src/theme_light.scss b/packages/eui-theme-berlin/src/theme_light.scss index ce7d45f4ef7..19216cf89aa 100644 --- a/packages/eui-theme-berlin/src/theme_light.scss +++ b/packages/eui-theme-berlin/src/theme_light.scss @@ -2,4 +2,5 @@ @import './variables/colors_light'; // Global styling -@import './variables/index'; \ No newline at end of file +@import './variables/index'; +@import 'node_modules/@elastic/eui-common/src/global_styling/index'; \ No newline at end of file diff --git a/packages/eui-theme-berlin/src/variables/_colors_dark.scss b/packages/eui-theme-berlin/src/variables/_colors_dark.scss index bd24f0d3c34..af75f9df34f 100644 --- a/packages/eui-theme-berlin/src/variables/_colors_dark.scss +++ b/packages/eui-theme-berlin/src/variables/_colors_dark.scss @@ -1,14 +1,14 @@ // stylelint-disable color-no-hex // This extra import allows any variables that are created via functions to work when loaded into JS -@import '@elastic/eui/global_styling/functions/index'; +@import 'node_modules/@elastic/eui-common/src/global_styling/functions/index'; // These colors stay the same no matter the theme $euiColorGhost: #FFF !default; $euiColorInk: #000 !default; // Core -$euiColorPrimary: #36A2EF !default; +$euiColorPrimary: #00aa00 !default; // test color for distinction $euiColorAccent: #F68FBE !default; // Status diff --git a/packages/eui-theme-berlin/src/variables/_colors_light.scss b/packages/eui-theme-berlin/src/variables/_colors_light.scss index fe763206579..4588ef5e096 100644 --- a/packages/eui-theme-berlin/src/variables/_colors_light.scss +++ b/packages/eui-theme-berlin/src/variables/_colors_light.scss @@ -1,14 +1,14 @@ // stylelint-disable color-no-hex // This extra import allows any variables that are created via functions to work when loaded into JS -@import '@elastic/eui/global_styling/functions/index'; +@import 'node_modules/@elastic/eui-common/src/global_styling/functions/index'; // These colors stay the same no matter the theme $euiColorGhost: #FFF !default; $euiColorInk: #000 !default; // Core -$euiColorPrimary: #07C !default; +$euiColorPrimary: #00ff00 !default; // test color for distinction $euiColorAccent: #F04E98 !default; // Status diff --git a/packages/eui-theme-berlin/src/variables/_index.scss b/packages/eui-theme-berlin/src/variables/_index.scss index 563251ca270..77409be2e50 100644 --- a/packages/eui-theme-berlin/src/variables/_index.scss +++ b/packages/eui-theme-berlin/src/variables/_index.scss @@ -1,5 +1,5 @@ // Import base theme first, then override -@import '@elastic/eui/global_styling/variables/index'; +@import 'node_modules/@elastic/eui-theme-base/src/variables/index'; @import 'states'; @import 'buttons'; diff --git a/packages/eui/src-docs/src/index.js b/packages/eui/src-docs/src/index.js index d9cd2b13c35..d9b072fccf4 100644 --- a/packages/eui/src-docs/src/index.js +++ b/packages/eui/src-docs/src/index.js @@ -23,13 +23,15 @@ import { // TODO: update SCSS files for new theme once available import themeLight from './theme_light.scss'; import themeDark from './theme_dark.scss'; +import themeNewLight from './theme_new_light.scss'; +import themeNewDark from './theme_new_dark.scss'; registerTheme('light', [themeLight]); registerTheme('dark', [themeDark]); if (isExperimentalThemeEnabled()) { - registerTheme(AVAILABLE_THEMES[2].value, [themeLight]); - registerTheme(AVAILABLE_THEMES[3].value, [themeDark]); + registerTheme(AVAILABLE_THEMES[2].value, [themeNewLight]); + registerTheme(AVAILABLE_THEMES[3].value, [themeNewDark]); } // Set up app diff --git a/packages/eui/src-docs/src/theme_new_dark.scss b/packages/eui/src-docs/src/theme_new_dark.scss new file mode 100644 index 00000000000..5a857d8e147 --- /dev/null +++ b/packages/eui/src-docs/src/theme_new_dark.scss @@ -0,0 +1,7 @@ +@import 'node_modules/@elastic/eui-theme-berlin/src/theme_dark'; +@import './components/index'; +@import './services/playground/index'; +@import './views/index'; + +// Elastic charts +@import '~@elastic/charts/dist/theme'; diff --git a/packages/eui/src-docs/src/theme_new_light.scss b/packages/eui/src-docs/src/theme_new_light.scss new file mode 100644 index 00000000000..03912eecaf3 --- /dev/null +++ b/packages/eui/src-docs/src/theme_new_light.scss @@ -0,0 +1,7 @@ +@import 'node_modules/@elastic/eui-theme-berlin/src/theme_light'; +@import './components/index'; +@import './services/playground/index'; +@import './views/index'; + +// Elastic charts +@import '~@elastic/charts/dist/theme'; diff --git a/packages/eui/src/global_styling/functions/_index.scss b/packages/eui/src/global_styling/functions/_index.scss index de8260b2bba..dde124f0e17 100644 --- a/packages/eui/src/global_styling/functions/_index.scss +++ b/packages/eui/src/global_styling/functions/_index.scss @@ -1,5 +1 @@ -// Math needs to be first in the load order -@import 'math'; - -// Using math, we have functions to manipulate contrast / luminosity for accessibility -@import 'colors'; +@import 'node_modules/@elastic/eui-common/src/global_styling/functions/index'; diff --git a/packages/eui/src/global_styling/index.scss b/packages/eui/src/global_styling/index.scss index 5c29e0435a5..dc799ce26b6 100644 --- a/packages/eui/src/global_styling/index.scss +++ b/packages/eui/src/global_styling/index.scss @@ -1,18 +1,4 @@ // Core -// Functions need to be first, since we use them in our variables and mixin definitions -@import 'functions/index'; - -// Variables come next, and are used in some mixins -@import 'variables/index'; - -// Mixins provide generic code expansion through helpers -@import 'mixins/index'; - -// Utility classes provide one-off selectors for common css problems -@import 'utility/index'; - -// The reset file has moved to global_styles.tsx - -// Customization of the React Date Picker -@import 'react_date_picker/index'; +@import 'node_modules/@elastic/eui-theme-base/src/variables/index'; +@import 'node_modules/@elastic/eui-common/src/global_styling/index'; \ No newline at end of file From 43c9a3b73c912a5e90003abd168270c3bc8a4201 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 30 Sep 2024 14:09:53 +0200 Subject: [PATCH 22/32] build: ensure common scss is part of package --- packages/eui-common/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/eui-common/package.json b/packages/eui-common/package.json index bc5dd429ba0..7b3e8b3f420 100644 --- a/packages/eui-common/package.json +++ b/packages/eui-common/package.json @@ -53,6 +53,7 @@ }, "files": [ "lib/", + "src/**/*.scss", "README.md" ], "installConfig": { From 75e2ad6f777039adf6e86e5315161fccc3d9004d Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 30 Sep 2024 15:18:14 +0200 Subject: [PATCH 23/32] chore: rebase cleanup --- .../src/global_styling/mixins/_tool_tip.scss | 10 +++++----- packages/eui-theme-base/src/variables/_index.scss | 3 --- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/eui-common/src/global_styling/mixins/_tool_tip.scss b/packages/eui-common/src/global_styling/mixins/_tool_tip.scss index 83b062274dc..d8feb0d4258 100644 --- a/packages/eui-common/src/global_styling/mixins/_tool_tip.scss +++ b/packages/eui-common/src/global_styling/mixins/_tool_tip.scss @@ -1,5 +1,9 @@ @mixin euiToolTipStyle($size: null) { @include euiBottomShadow($color: $euiColorInk); + + $euiTooltipBackgroundColor: tintOrShade($euiColorFullShade, 25%, 100%) !default; + $euiTooltipBorderColor: tintOrShade($euiColorFullShade, 35%, 80%) !default; + border-radius: $euiBorderRadius; background-color: $euiTooltipBackgroundColor; color: $euiColorGhost; @@ -18,8 +22,4 @@ border-bottom: solid $euiBorderWidthThin $euiTooltipBorderColor; padding-bottom: $euiSizeXS; margin-bottom: $euiSizeXS; -} - -@mixin euiToolTipAnimation($side: 'top') { - animation: #{map-get($euiTooltipAnimations, $side)} $euiAnimSpeedSlow ease-out 0s forwards; -} +} \ No newline at end of file diff --git a/packages/eui-theme-base/src/variables/_index.scss b/packages/eui-theme-base/src/variables/_index.scss index 6971a19d892..993979a78a5 100644 --- a/packages/eui-theme-base/src/variables/_index.scss +++ b/packages/eui-theme-base/src/variables/_index.scss @@ -21,6 +21,3 @@ @import 'buttons'; @import 'form'; -@import 'page'; -@import 'panel'; -@import 'tool_tip'; From c4410e4c27ccb46d4423bfae2d0cc6a9f6fe1a0e Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Wed, 2 Oct 2024 13:25:36 +0200 Subject: [PATCH 24/32] refactor: rename theme --- packages/docusaurus-theme/package.json | 2 +- .../src/components/theme_context/index.tsx | 8 ++++---- packages/eui-theme-berlin/README.md | 1 - .../.gitignore | 0 .../LICENSE.txt | 0 packages/eui-theme-borealis/README.md | 1 + .../package.json | 4 ++-- .../src/index.ts | 9 ++++++--- .../src/theme_dark.scss | 0 .../src/theme_light.scss | 0 .../src/variables/_animation.ts | 0 .../src/variables/_borders.ts | 0 .../src/variables/_breakpoint.ts | 0 .../src/variables/_buttons.scss | 0 .../src/variables/_colors.ts | 0 .../src/variables/_colors_dark.scss | 0 .../src/variables/_colors_dark.ts | 0 .../src/variables/_colors_light.scss | 0 .../src/variables/_colors_light.ts | 0 .../src/variables/_index.scss | 0 .../src/variables/_levels.ts | 0 .../src/variables/_page.scss | 0 .../src/variables/_size.ts | 0 .../src/variables/_states.scss | 0 .../src/variables/_states.ts | 0 .../src/variables/_typography.scss | 0 .../src/variables/_typography.ts | 0 .../tsconfig.json | 0 packages/eui/.storybook/decorator.tsx | 10 +++++----- packages/eui/package.json | 4 ++-- .../src/components/with_theme/theme_context.tsx | 14 +++++++------- packages/eui/src-docs/src/theme_new_dark.scss | 2 +- packages/eui/src-docs/src/theme_new_light.scss | 2 +- packages/website/package.json | 2 +- yarn.lock | 10 +++++----- 35 files changed, 36 insertions(+), 33 deletions(-) delete mode 100644 packages/eui-theme-berlin/README.md rename packages/{eui-theme-berlin => eui-theme-borealis}/.gitignore (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/LICENSE.txt (100%) create mode 100644 packages/eui-theme-borealis/README.md rename packages/{eui-theme-berlin => eui-theme-borealis}/package.json (90%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/index.ts (81%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/theme_dark.scss (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/theme_light.scss (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_animation.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_borders.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_breakpoint.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_buttons.scss (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_colors.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_colors_dark.scss (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_colors_dark.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_colors_light.scss (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_colors_light.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_index.scss (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_levels.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_page.scss (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_size.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_states.scss (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_states.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_typography.scss (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/src/variables/_typography.ts (100%) rename packages/{eui-theme-berlin => eui-theme-borealis}/tsconfig.json (100%) diff --git a/packages/docusaurus-theme/package.json b/packages/docusaurus-theme/package.json index 91e0be85cf7..7f0eeef3a8c 100644 --- a/packages/docusaurus-theme/package.json +++ b/packages/docusaurus-theme/package.json @@ -36,7 +36,7 @@ "@elastic/datemath": "^5.0.3", "@elastic/eui": "workspace:^", "@elastic/eui-docgen": "workspace:^", - "@elastic/eui-theme-berlin": "workspace:^", + "@elastic/eui-theme-borealis": "workspace:^", "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.4", "@types/react-window": "^1.8.8", diff --git a/packages/docusaurus-theme/src/components/theme_context/index.tsx b/packages/docusaurus-theme/src/components/theme_context/index.tsx index 19b92505ccd..d1fe2208f15 100644 --- a/packages/docusaurus-theme/src/components/theme_context/index.tsx +++ b/packages/docusaurus-theme/src/components/theme_context/index.tsx @@ -10,15 +10,15 @@ import { EuiThemeAmsterdam, EuiThemeColorMode, } from '@elastic/eui'; -import { EuiThemeBerlin } from '@elastic/eui-theme-berlin'; +import { EuiThemeBorealis } from '@elastic/eui-theme-borealis'; import { EuiThemeOverrides } from './theme_overrides'; const EXPERIMENTAL_THEMES = [ { - text: 'Berlin', - value: EuiThemeBerlin.key, - provider: EuiThemeBerlin, + text: 'Borealis', + value: EuiThemeBorealis.key, + provider: EuiThemeBorealis, }, ]; diff --git a/packages/eui-theme-berlin/README.md b/packages/eui-theme-berlin/README.md deleted file mode 100644 index fbfeb8dcba3..00000000000 --- a/packages/eui-theme-berlin/README.md +++ /dev/null @@ -1 +0,0 @@ -# `eui-theme-berlin` - A visual EUI theme \ No newline at end of file diff --git a/packages/eui-theme-berlin/.gitignore b/packages/eui-theme-borealis/.gitignore similarity index 100% rename from packages/eui-theme-berlin/.gitignore rename to packages/eui-theme-borealis/.gitignore diff --git a/packages/eui-theme-berlin/LICENSE.txt b/packages/eui-theme-borealis/LICENSE.txt similarity index 100% rename from packages/eui-theme-berlin/LICENSE.txt rename to packages/eui-theme-borealis/LICENSE.txt diff --git a/packages/eui-theme-borealis/README.md b/packages/eui-theme-borealis/README.md new file mode 100644 index 00000000000..f015fcd893a --- /dev/null +++ b/packages/eui-theme-borealis/README.md @@ -0,0 +1 @@ +# `eui-theme-borealis` - A visual EUI theme \ No newline at end of file diff --git a/packages/eui-theme-berlin/package.json b/packages/eui-theme-borealis/package.json similarity index 90% rename from packages/eui-theme-berlin/package.json rename to packages/eui-theme-borealis/package.json index 04623fa5c68..dcd766e3984 100644 --- a/packages/eui-theme-berlin/package.json +++ b/packages/eui-theme-borealis/package.json @@ -1,5 +1,5 @@ { - "name": "@elastic/eui-theme-berlin", + "name": "@elastic/eui-theme-borealis", "version": "0.0.1", "description": "A visual theme for EUI", "license": "SEE LICENSE IN LICENSE.txt", @@ -11,7 +11,7 @@ "repository": { "type": "git", "url": "https://github.com/elastic/eui.git", - "directory": "packages/eui-theme-berlin" + "directory": "packages/eui-theme-borealis" }, "private": true, "devDependencies": { diff --git a/packages/eui-theme-berlin/src/index.ts b/packages/eui-theme-borealis/src/index.ts similarity index 81% rename from packages/eui-theme-berlin/src/index.ts rename to packages/eui-theme-borealis/src/index.ts index c9884f5e7e7..be797a62519 100644 --- a/packages/eui-theme-berlin/src/index.ts +++ b/packages/eui-theme-borealis/src/index.ts @@ -17,9 +17,9 @@ import { levels } from './variables/_levels'; import { font } from './variables/_typography'; import { focus } from './variables/_states'; -export const EUI_THEME_BERLIN_KEY = 'EUI_THEME_BERLIN'; +export const EUI_THEME_BOREALIS_KEY = 'EUI_THEME_BOREALIS'; -export const euiThemeBerlin: EuiThemeShape = { +export const euiThemeBorealis: EuiThemeShape = { colors, base, size, @@ -31,4 +31,7 @@ export const euiThemeBerlin: EuiThemeShape = { focus, }; -export const EuiThemeBerlin = buildTheme(euiThemeBerlin, EUI_THEME_BERLIN_KEY); +export const EuiThemeBorealis = buildTheme( + euiThemeBorealis, + EUI_THEME_BOREALIS_KEY +); diff --git a/packages/eui-theme-berlin/src/theme_dark.scss b/packages/eui-theme-borealis/src/theme_dark.scss similarity index 100% rename from packages/eui-theme-berlin/src/theme_dark.scss rename to packages/eui-theme-borealis/src/theme_dark.scss diff --git a/packages/eui-theme-berlin/src/theme_light.scss b/packages/eui-theme-borealis/src/theme_light.scss similarity index 100% rename from packages/eui-theme-berlin/src/theme_light.scss rename to packages/eui-theme-borealis/src/theme_light.scss diff --git a/packages/eui-theme-berlin/src/variables/_animation.ts b/packages/eui-theme-borealis/src/variables/_animation.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_animation.ts rename to packages/eui-theme-borealis/src/variables/_animation.ts diff --git a/packages/eui-theme-berlin/src/variables/_borders.ts b/packages/eui-theme-borealis/src/variables/_borders.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_borders.ts rename to packages/eui-theme-borealis/src/variables/_borders.ts diff --git a/packages/eui-theme-berlin/src/variables/_breakpoint.ts b/packages/eui-theme-borealis/src/variables/_breakpoint.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_breakpoint.ts rename to packages/eui-theme-borealis/src/variables/_breakpoint.ts diff --git a/packages/eui-theme-berlin/src/variables/_buttons.scss b/packages/eui-theme-borealis/src/variables/_buttons.scss similarity index 100% rename from packages/eui-theme-berlin/src/variables/_buttons.scss rename to packages/eui-theme-borealis/src/variables/_buttons.scss diff --git a/packages/eui-theme-berlin/src/variables/_colors.ts b/packages/eui-theme-borealis/src/variables/_colors.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_colors.ts rename to packages/eui-theme-borealis/src/variables/_colors.ts diff --git a/packages/eui-theme-berlin/src/variables/_colors_dark.scss b/packages/eui-theme-borealis/src/variables/_colors_dark.scss similarity index 100% rename from packages/eui-theme-berlin/src/variables/_colors_dark.scss rename to packages/eui-theme-borealis/src/variables/_colors_dark.scss diff --git a/packages/eui-theme-berlin/src/variables/_colors_dark.ts b/packages/eui-theme-borealis/src/variables/_colors_dark.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_colors_dark.ts rename to packages/eui-theme-borealis/src/variables/_colors_dark.ts diff --git a/packages/eui-theme-berlin/src/variables/_colors_light.scss b/packages/eui-theme-borealis/src/variables/_colors_light.scss similarity index 100% rename from packages/eui-theme-berlin/src/variables/_colors_light.scss rename to packages/eui-theme-borealis/src/variables/_colors_light.scss diff --git a/packages/eui-theme-berlin/src/variables/_colors_light.ts b/packages/eui-theme-borealis/src/variables/_colors_light.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_colors_light.ts rename to packages/eui-theme-borealis/src/variables/_colors_light.ts diff --git a/packages/eui-theme-berlin/src/variables/_index.scss b/packages/eui-theme-borealis/src/variables/_index.scss similarity index 100% rename from packages/eui-theme-berlin/src/variables/_index.scss rename to packages/eui-theme-borealis/src/variables/_index.scss diff --git a/packages/eui-theme-berlin/src/variables/_levels.ts b/packages/eui-theme-borealis/src/variables/_levels.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_levels.ts rename to packages/eui-theme-borealis/src/variables/_levels.ts diff --git a/packages/eui-theme-berlin/src/variables/_page.scss b/packages/eui-theme-borealis/src/variables/_page.scss similarity index 100% rename from packages/eui-theme-berlin/src/variables/_page.scss rename to packages/eui-theme-borealis/src/variables/_page.scss diff --git a/packages/eui-theme-berlin/src/variables/_size.ts b/packages/eui-theme-borealis/src/variables/_size.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_size.ts rename to packages/eui-theme-borealis/src/variables/_size.ts diff --git a/packages/eui-theme-berlin/src/variables/_states.scss b/packages/eui-theme-borealis/src/variables/_states.scss similarity index 100% rename from packages/eui-theme-berlin/src/variables/_states.scss rename to packages/eui-theme-borealis/src/variables/_states.scss diff --git a/packages/eui-theme-berlin/src/variables/_states.ts b/packages/eui-theme-borealis/src/variables/_states.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_states.ts rename to packages/eui-theme-borealis/src/variables/_states.ts diff --git a/packages/eui-theme-berlin/src/variables/_typography.scss b/packages/eui-theme-borealis/src/variables/_typography.scss similarity index 100% rename from packages/eui-theme-berlin/src/variables/_typography.scss rename to packages/eui-theme-borealis/src/variables/_typography.scss diff --git a/packages/eui-theme-berlin/src/variables/_typography.ts b/packages/eui-theme-borealis/src/variables/_typography.ts similarity index 100% rename from packages/eui-theme-berlin/src/variables/_typography.ts rename to packages/eui-theme-borealis/src/variables/_typography.ts diff --git a/packages/eui-theme-berlin/tsconfig.json b/packages/eui-theme-borealis/tsconfig.json similarity index 100% rename from packages/eui-theme-berlin/tsconfig.json rename to packages/eui-theme-borealis/tsconfig.json diff --git a/packages/eui/.storybook/decorator.tsx b/packages/eui/.storybook/decorator.tsx index d6e9657d997..d30f8df311d 100644 --- a/packages/eui/.storybook/decorator.tsx +++ b/packages/eui/.storybook/decorator.tsx @@ -15,7 +15,7 @@ import React, { } from 'react'; import { css } from '@emotion/react'; import type { Preview } from '@storybook/react'; -import { EuiThemeBerlin } from '@elastic/eui-theme-berlin'; +import { EuiThemeBorealis } from '@elastic/eui-theme-borealis'; import { EuiThemeColorMode } from '../src/services'; import { EuiProvider, EuiProviderProps } from '../src/components/provider'; @@ -23,9 +23,9 @@ import { EuiThemeAmsterdam } from '../src/themes'; const EXPERIMENTAL_THEMES = [ { - text: 'Berlin', - value: EuiThemeBerlin.key, - provider: EuiThemeBerlin, + text: 'Borealis', + value: EuiThemeBorealis.key, + provider: EuiThemeBorealis, }, ]; @@ -177,7 +177,7 @@ export const euiProviderDecoratorGlobalsExperimental = { title: 'Theme', items: [ { value: EuiThemeAmsterdam.key, title: 'Amsterdam', icon: 'box' }, - { value: EuiThemeBerlin.key, title: 'Berlin', icon: 'box' }, + { value: EuiThemeBorealis.key, title: 'Borealis', icon: 'box' }, ], dynamicTitle: true, }, diff --git a/packages/eui/package.json b/packages/eui/package.json index 6a2bc93a17d..d680d995bb6 100644 --- a/packages/eui/package.json +++ b/packages/eui/package.json @@ -106,7 +106,7 @@ "@elastic/datemath": "^5.0.3", "@elastic/eui-common": "workspace:^", "@elastic/eui-theme-base": "workspace:^", - "@elastic/eui-theme-berlin": "workspace:^", + "@elastic/eui-theme-borealis": "workspace:^", "@emotion/babel-preset-css-prop": "^11.11.0", "@emotion/cache": "^11.11.0", "@emotion/css": "^11.11.0", @@ -259,7 +259,7 @@ "@elastic/datemath": "^5.0.2", "@elastic/eui-common": "0.0.1", "@elastic/eui-theme-base": "0.0.1", - "@elastic/eui-theme-berlin": "0.0.1", + "@elastic/eui-theme-borealis": "0.0.1", "@emotion/css": "11.x", "@emotion/react": "11.x", "@types/react": "^16.9 || ^17.0 || ^18.0", diff --git a/packages/eui/src-docs/src/components/with_theme/theme_context.tsx b/packages/eui/src-docs/src/components/with_theme/theme_context.tsx index e8ac2d88b7e..2fac3a5c545 100644 --- a/packages/eui/src-docs/src/components/with_theme/theme_context.tsx +++ b/packages/eui/src-docs/src/components/with_theme/theme_context.tsx @@ -1,5 +1,5 @@ import React, { PropsWithChildren } from 'react'; -import { EuiThemeBerlin } from '@elastic/eui-theme-berlin'; +import { EuiThemeBorealis } from '@elastic/eui-theme-borealis'; import { EUI_THEMES, @@ -15,14 +15,14 @@ const URL_PARAM_KEY = 'themeLanguage'; const EXPERIMENTAL_THEMES: EUI_THEME[] = isExperimentalThemeEnabled() ? [ { - text: 'Berlin (Light)', - value: `${EuiThemeBerlin.key}_LIGHT`, - provider: EuiThemeBerlin, + text: 'Borealis (Light)', + value: `${EuiThemeBorealis.key}_LIGHT`, + provider: EuiThemeBorealis, }, { - text: 'Berlin (Dark)', - value: `${EuiThemeBerlin.key}_DARK`, - provider: EuiThemeBerlin, + text: 'Borealis (Dark)', + value: `${EuiThemeBorealis.key}_DARK`, + provider: EuiThemeBorealis, }, ] : []; diff --git a/packages/eui/src-docs/src/theme_new_dark.scss b/packages/eui/src-docs/src/theme_new_dark.scss index 5a857d8e147..7c76c518a04 100644 --- a/packages/eui/src-docs/src/theme_new_dark.scss +++ b/packages/eui/src-docs/src/theme_new_dark.scss @@ -1,4 +1,4 @@ -@import 'node_modules/@elastic/eui-theme-berlin/src/theme_dark'; +@import 'node_modules/@elastic/eui-theme-borealis/src/theme_dark'; @import './components/index'; @import './services/playground/index'; @import './views/index'; diff --git a/packages/eui/src-docs/src/theme_new_light.scss b/packages/eui/src-docs/src/theme_new_light.scss index 03912eecaf3..1bee3ff7412 100644 --- a/packages/eui/src-docs/src/theme_new_light.scss +++ b/packages/eui/src-docs/src/theme_new_light.scss @@ -1,4 +1,4 @@ -@import 'node_modules/@elastic/eui-theme-berlin/src/theme_light'; +@import 'node_modules/@elastic/eui-theme-borealis/src/theme_light'; @import './components/index'; @import './services/playground/index'; @import './views/index'; diff --git a/packages/website/package.json b/packages/website/package.json index e16879931b3..566442cf74f 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "docusaurus": "docusaurus", - "build:workspaces": "yarn workspace @elastic/eui-common run build && yarn workspace @elastic/eui-theme-base run build && yarn workspace @elastic/eui-theme-berlin run build && yarn workspaces foreach -Rti --from @elastic/eui-website run build", + "build:workspaces": "yarn workspace @elastic/eui-common run build && yarn workspace @elastic/eui-theme-base run build && yarn workspace @elastic/eui-theme-borealis run build && yarn workspaces foreach -Rti --from @elastic/eui-website run build", "start": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus start", "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus build", "swizzle": "docusaurus swizzle", diff --git a/yarn.lock b/yarn.lock index b9915a8fdef..6a22de6c8e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5747,7 +5747,7 @@ __metadata: "@elastic/datemath": "npm:^5.0.3" "@elastic/eui": "workspace:^" "@elastic/eui-docgen": "workspace:^" - "@elastic/eui-theme-berlin": "workspace:^" + "@elastic/eui-theme-borealis": "workspace:^" "@emotion/css": "npm:^11.11.2" "@emotion/react": "npm:^11.11.4" "@types/react": "npm:^18.3.3" @@ -5808,9 +5808,9 @@ __metadata: languageName: unknown linkType: soft -"@elastic/eui-theme-berlin@workspace:^, @elastic/eui-theme-berlin@workspace:packages/eui-theme-berlin": +"@elastic/eui-theme-borealis@workspace:^, @elastic/eui-theme-borealis@workspace:packages/eui-theme-borealis": version: 0.0.0-use.local - resolution: "@elastic/eui-theme-berlin@workspace:packages/eui-theme-berlin" + resolution: "@elastic/eui-theme-borealis@workspace:packages/eui-theme-borealis" dependencies: "@elastic/eui-common": "workspace:^" "@elastic/eui-theme-base": "workspace:^" @@ -5875,7 +5875,7 @@ __metadata: "@elastic/datemath": "npm:^5.0.3" "@elastic/eui-common": "workspace:^" "@elastic/eui-theme-base": "workspace:^" - "@elastic/eui-theme-berlin": "workspace:^" + "@elastic/eui-theme-borealis": "workspace:^" "@emotion/babel-preset-css-prop": "npm:^11.11.0" "@emotion/cache": "npm:^11.11.0" "@emotion/css": "npm:^11.11.0" @@ -6060,7 +6060,7 @@ __metadata: "@elastic/datemath": ^5.0.2 "@elastic/eui-common": 0.0.1 "@elastic/eui-theme-base": 0.0.1 - "@elastic/eui-theme-berlin": 0.0.1 + "@elastic/eui-theme-borealis": 0.0.1 "@emotion/css": 11.x "@emotion/react": 11.x "@types/react": ^16.9 || ^17.0 || ^18.0 From f263cd768d06a6b9a6bff61b8f78167fe72c9ca2 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Tue, 8 Oct 2024 17:19:58 +0200 Subject: [PATCH 25/32] add eui-theme-common package - update references --- packages/eui-theme-borealis/.eslintcache | 1 + packages/eui-theme-borealis/.eslintignore | 9 + packages/eui-theme-borealis/.eslintplugin.js | 3 + packages/eui-theme-borealis/.eslintrc.js | 114 +++ packages/eui-theme-borealis/.prettierrc | 7 + packages/eui-theme-borealis/.stylelintrc.js | 163 ++++ packages/eui-theme-borealis/package.json | 35 +- packages/eui-theme-borealis/src/index.ts | 2 +- .../eui-theme-borealis/src/theme_dark.scss | 2 +- .../eui-theme-borealis/src/theme_light.scss | 2 +- .../src/variables/_animation.ts | 2 +- .../src/variables/_borders.ts | 7 +- .../src/variables/_breakpoint.ts | 2 +- .../src/variables/_colors.ts | 2 +- .../src/variables/_colors_dark.scss | 4 +- .../src/variables/_colors_dark.ts | 3 +- .../src/variables/_colors_light.scss | 4 +- .../src/variables/_colors_light.ts | 3 +- .../src/variables/_index.scss | 2 +- .../src/variables/_levels.ts | 2 +- .../eui-theme-borealis/src/variables/_size.ts | 4 +- .../src/variables/_states.ts | 7 +- .../src/variables/_typography.ts | 2 +- packages/eui-theme-common/.babelrc.js | 27 + packages/eui-theme-common/.eslintignore | 10 + packages/eui-theme-common/.eslintplugin.js | 3 + packages/eui-theme-common/.eslintrc.js | 114 +++ packages/eui-theme-common/.gitignore | 11 + packages/eui-theme-common/.prettierrc | 7 + packages/eui-theme-common/.stylelintrc.js | 163 ++++ packages/eui-theme-common/LICENSE.txt | 6 + packages/eui-theme-common/README.md | 1 + packages/eui-theme-common/babel.config.js | 6 + packages/eui-theme-common/jest.config.js | 7 + packages/eui-theme-common/package.json | 67 ++ .../require_license_header.js | 132 +++ .../require_license_header.test.js | 177 ++++ .../src/global_styling/functions/_colors.scss | 138 ++++ .../src/global_styling/functions/_index.scss | 5 + .../src/global_styling/functions/_math.scss | 1 + .../global_styling/functions/_math_pow.scss | 82 ++ .../src/global_styling/functions/index.ts | 9 + .../src/global_styling/functions/size.ts | 26 + .../src/global_styling/index.scss | 18 + .../src/global_styling/index.ts | 11 + .../src/global_styling/mixins/_button.scss | 149 ++++ .../src/global_styling/mixins/_form.scss | 273 +++++++ .../src/global_styling/mixins/_helpers.scss | 126 +++ .../src/global_styling/mixins/_index.scss | 14 + .../src/global_styling/mixins/_link.scss | 11 + .../src/global_styling/mixins/_loading.scss | 6 + .../src/global_styling/mixins/_panel.scss | 55 ++ .../src/global_styling/mixins/_range.scss | 62 ++ .../global_styling/mixins/_responsive.scss | 44 + .../src/global_styling/mixins/_shadow.scss | 108 +++ .../src/global_styling/mixins/_size.scss | 4 + .../src/global_styling/mixins/_states.scss | 50 ++ .../src/global_styling/mixins/_tool_tip.scss | 25 + .../global_styling/mixins/_typography.scss | 167 ++++ .../react_date_picker/_date_picker.scss | 772 ++++++++++++++++++ .../react_date_picker/_index.scss | 2 + .../react_date_picker/_variables.scss | 1 + .../src/global_styling/types.ts | 106 +++ .../global_styling/utility/_animations.scss | 55 ++ .../src/global_styling/utility/_index.scss | 1 + .../global_styling/variables/_animations.scss | 13 + .../global_styling/variables/_borders.scss | 11 + .../global_styling/variables/_buttons.scss | 18 + .../global_styling/variables/_colors_vis.scss | 72 ++ .../global_styling/variables/_colors_vis.ts | 62 ++ .../variables/_font_weight.scss | 10 + .../src/global_styling/variables/_form.scss | 21 + .../src/global_styling/variables/_index.scss | 23 + .../global_styling/variables/_responsive.scss | 9 + .../global_styling/variables/_shadows.scss | 2 + .../src/global_styling/variables/_size.scss | 15 + .../src/global_styling/variables/_states.scss | 14 + .../global_styling/variables/_typography.scss | 75 ++ .../global_styling/variables/_z_index.scss | 34 + .../global_styling/variables/animations.ts | 66 ++ .../src/global_styling/variables/borders.ts | 74 ++ .../global_styling/variables/breakpoint.ts | 28 + .../src/global_styling/variables/colors.ts | 156 ++++ .../src/global_styling/variables/index.ts | 18 + .../src/global_styling/variables/levels.ts | 60 ++ .../src/global_styling/variables/shadow.ts | 28 + .../src/global_styling/variables/size.ts | 47 ++ .../src/global_styling/variables/states.ts | 33 + .../global_styling/variables/typography.ts | 146 ++++ packages/eui-theme-common/src/index.ts | 12 + packages/eui-theme-common/src/types.ts | 56 ++ packages/eui-theme-common/src/utils.test.ts | 279 +++++++ packages/eui-theme-common/src/utils.ts | 392 +++++++++ packages/eui-theme-common/tsconfig.cjs.json | 29 + packages/eui-theme-common/tsconfig.json | 28 + packages/eui-theme-common/tsconfig.types.json | 13 + packages/eui/package.json | 6 +- packages/eui/src/components/common.ts | 2 +- .../src/global_styling/functions/_index.scss | 2 +- .../eui/src/global_styling/functions/size.ts | 2 +- packages/eui/src/global_styling/index.scss | 3 +- .../global_styling/variables/_animations.scss | 2 +- .../global_styling/variables/_borders.scss | 2 +- .../global_styling/variables/_buttons.scss | 2 +- .../global_styling/variables/_colors_vis.scss | 2 +- .../global_styling/variables/_colors_vis.ts | 2 +- .../variables/_font_weight.scss | 2 +- .../src/global_styling/variables/_form.scss | 2 +- .../global_styling/variables/_responsive.scss | 2 +- .../global_styling/variables/_shadows.scss | 2 +- .../src/global_styling/variables/_size.scss | 2 +- .../src/global_styling/variables/_states.scss | 2 +- .../global_styling/variables/_typography.scss | 2 +- .../global_styling/variables/_z_index.scss | 2 +- .../global_styling/variables/animations.ts | 2 +- .../src/global_styling/variables/borders.ts | 2 +- .../global_styling/variables/breakpoint.ts | 2 +- .../src/global_styling/variables/colors.ts | 2 +- .../src/global_styling/variables/levels.ts | 2 +- .../src/global_styling/variables/shadow.ts | 2 +- .../eui/src/global_styling/variables/size.ts | 2 +- .../src/global_styling/variables/states.ts | 2 +- .../global_styling/variables/typography.ts | 2 +- packages/eui/src/services/theme/types.ts | 2 +- packages/eui/src/services/theme/utils.ts | 2 +- packages/website/package.json | 2 +- yarn.lock | 76 +- 127 files changed, 5307 insertions(+), 112 deletions(-) create mode 100644 packages/eui-theme-borealis/.eslintcache create mode 100644 packages/eui-theme-borealis/.eslintignore create mode 100644 packages/eui-theme-borealis/.eslintplugin.js create mode 100644 packages/eui-theme-borealis/.eslintrc.js create mode 100644 packages/eui-theme-borealis/.prettierrc create mode 100644 packages/eui-theme-borealis/.stylelintrc.js create mode 100644 packages/eui-theme-common/.babelrc.js create mode 100644 packages/eui-theme-common/.eslintignore create mode 100644 packages/eui-theme-common/.eslintplugin.js create mode 100644 packages/eui-theme-common/.eslintrc.js create mode 100644 packages/eui-theme-common/.gitignore create mode 100644 packages/eui-theme-common/.prettierrc create mode 100644 packages/eui-theme-common/.stylelintrc.js create mode 100644 packages/eui-theme-common/LICENSE.txt create mode 100644 packages/eui-theme-common/README.md create mode 100644 packages/eui-theme-common/babel.config.js create mode 100644 packages/eui-theme-common/jest.config.js create mode 100644 packages/eui-theme-common/package.json create mode 100644 packages/eui-theme-common/scripts/eslint-plugin-local/require_license_header.js create mode 100644 packages/eui-theme-common/scripts/eslint-plugin-local/require_license_header.test.js create mode 100644 packages/eui-theme-common/src/global_styling/functions/_colors.scss create mode 100644 packages/eui-theme-common/src/global_styling/functions/_index.scss create mode 100644 packages/eui-theme-common/src/global_styling/functions/_math.scss create mode 100644 packages/eui-theme-common/src/global_styling/functions/_math_pow.scss create mode 100644 packages/eui-theme-common/src/global_styling/functions/index.ts create mode 100644 packages/eui-theme-common/src/global_styling/functions/size.ts create mode 100644 packages/eui-theme-common/src/global_styling/index.scss create mode 100644 packages/eui-theme-common/src/global_styling/index.ts create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_button.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_form.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_helpers.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_index.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_link.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_loading.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_panel.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_range.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_responsive.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_shadow.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_size.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_states.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_tool_tip.scss create mode 100644 packages/eui-theme-common/src/global_styling/mixins/_typography.scss create mode 100644 packages/eui-theme-common/src/global_styling/react_date_picker/_date_picker.scss create mode 100644 packages/eui-theme-common/src/global_styling/react_date_picker/_index.scss create mode 100644 packages/eui-theme-common/src/global_styling/react_date_picker/_variables.scss create mode 100644 packages/eui-theme-common/src/global_styling/types.ts create mode 100644 packages/eui-theme-common/src/global_styling/utility/_animations.scss create mode 100644 packages/eui-theme-common/src/global_styling/utility/_index.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_animations.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_borders.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_buttons.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_colors_vis.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_colors_vis.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/_font_weight.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_form.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_index.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_responsive.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_shadows.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_size.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_states.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_typography.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/_z_index.scss create mode 100644 packages/eui-theme-common/src/global_styling/variables/animations.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/borders.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/breakpoint.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/colors.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/index.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/levels.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/shadow.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/size.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/states.ts create mode 100644 packages/eui-theme-common/src/global_styling/variables/typography.ts create mode 100644 packages/eui-theme-common/src/index.ts create mode 100644 packages/eui-theme-common/src/types.ts create mode 100644 packages/eui-theme-common/src/utils.test.ts create mode 100644 packages/eui-theme-common/src/utils.ts create mode 100644 packages/eui-theme-common/tsconfig.cjs.json create mode 100644 packages/eui-theme-common/tsconfig.json create mode 100644 packages/eui-theme-common/tsconfig.types.json diff --git a/packages/eui-theme-borealis/.eslintcache b/packages/eui-theme-borealis/.eslintcache new file mode 100644 index 00000000000..5231400c151 --- /dev/null +++ b/packages/eui-theme-borealis/.eslintcache @@ -0,0 +1 @@ +[{"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/index.ts":"1","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_animation.ts":"2","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_borders.ts":"3","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_breakpoint.ts":"4","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors.ts":"5","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors_dark.ts":"6","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors_light.ts":"7","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_levels.ts":"8","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_size.ts":"9","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_states.ts":"10","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_typography.ts":"11"},{"size":1110,"mtime":1728391334458,"results":"12","hashOfConfig":"13"},{"size":896,"mtime":1728391334459,"results":"14","hashOfConfig":"13"},{"size":1074,"mtime":1728391334459,"results":"15","hashOfConfig":"13"},{"size":531,"mtime":1728391334460,"results":"16","hashOfConfig":"13"},{"size":637,"mtime":1728391334460,"results":"17","hashOfConfig":"13"},{"size":2144,"mtime":1728391334461,"results":"18","hashOfConfig":"13"},{"size":2143,"mtime":1728391334461,"results":"19","hashOfConfig":"13"},{"size":615,"mtime":1728391334462,"results":"20","hashOfConfig":"13"},{"size":895,"mtime":1728391334462,"results":"21","hashOfConfig":"13"},{"size":744,"mtime":1728391334463,"results":"22","hashOfConfig":"13"},{"size":1576,"mtime":1728391334463,"results":"23","hashOfConfig":"13"},{"filePath":"24","messages":"25","suppressedMessages":"26","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1h5kx7l",{"filePath":"27","messages":"28","suppressedMessages":"29","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"30","messages":"31","suppressedMessages":"32","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"33","messages":"34","suppressedMessages":"35","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"36","messages":"37","suppressedMessages":"38","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"39","messages":"40","suppressedMessages":"41","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"42","messages":"43","suppressedMessages":"44","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"45","messages":"46","suppressedMessages":"47","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"48","messages":"49","suppressedMessages":"50","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"51","messages":"52","suppressedMessages":"53","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"54","messages":"55","suppressedMessages":"56","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/index.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_animation.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_borders.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_breakpoint.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors_dark.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors_light.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_levels.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_size.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_states.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_typography.ts",[],[]] \ No newline at end of file diff --git a/packages/eui-theme-borealis/.eslintignore b/packages/eui-theme-borealis/.eslintignore new file mode 100644 index 00000000000..4874b17b0b8 --- /dev/null +++ b/packages/eui-theme-borealis/.eslintignore @@ -0,0 +1,9 @@ +dist +node_modules +lib +types +**/*.d.ts +package.json +scripts +.eslintrc.js +babel.config.js diff --git a/packages/eui-theme-borealis/.eslintplugin.js b/packages/eui-theme-borealis/.eslintplugin.js new file mode 100644 index 00000000000..88d38f7aa99 --- /dev/null +++ b/packages/eui-theme-borealis/.eslintplugin.js @@ -0,0 +1,3 @@ +exports.rules = { + 'require-license-header': require('@elastic/eui-theme-common/scripts/eslint-plugin-local/require_license_header.js'), +}; diff --git a/packages/eui-theme-borealis/.eslintrc.js b/packages/eui-theme-borealis/.eslintrc.js new file mode 100644 index 00000000000..e33853c0255 --- /dev/null +++ b/packages/eui-theme-borealis/.eslintrc.js @@ -0,0 +1,114 @@ +const SSPL_ELASTIC_2_0_LICENSE_HEADER = ` +/* + * 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. + */ +`; + +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: ['./tsconfig.json'], + ecmaFeatures: { + jsx: true, + }, + }, + settings: { + 'import/resolver': { + node: { + extensions: ['.ts', '.tsx', '.js', '.json'], + }, + }, + }, + extends: [ + 'plugin:@typescript-eslint/recommended', + // Prettier options need to come last, in order to override other style rules + 'plugin:prettier/recommended', + ], + plugins: ['local', 'import'], + rules: { + 'block-scoped-var': 'error', + camelcase: 'off', + 'dot-notation': ['error', { allowKeywords: true }], + eqeqeq: ['error', 'always', { null: 'ignore' }], + 'guard-for-in': 'error', + 'new-cap': ['error', { capIsNewExceptions: ['Private'] }], + 'no-caller': 'error', + 'no-const-assign': 'error', + 'no-debugger': 'error', + 'no-empty': ['error', { allowEmptyCatch: true }], + 'no-eval': 'error', + 'no-extend-native': 'error', + 'no-global-assign': 'error', + 'no-loop-func': 'error', + 'no-restricted-globals': ['error', 'context'], + 'no-script-url': 'error', + 'no-sequences': 'error', + 'no-var': 'error', + 'no-with': 'error', + 'prefer-const': 'error', + 'prefer-template': 'error', + strict: ['error', 'never'], + 'valid-typeof': 'error', + + 'local/require-license-header': [ + 'warn', + { + license: SSPL_ELASTIC_2_0_LICENSE_HEADER, + }, + ], + + 'import/no-unresolved': ['error', { amd: true, commonjs: true }], + 'import/namespace': 'error', + 'import/default': 'error', + 'import/export': 'error', + 'import/no-named-as-default': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-duplicates': 'error', + + '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-member-accessibility': 'off', + '@typescript-eslint/indent': 'off', + '@typescript-eslint/ban-tslint-comment': 'error', + '@typescript-eslint/no-empty-interface': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-parameter-properties': 'off', + '@typescript-eslint/no-triple-slash-reference': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { argsIgnorePattern: '^_', ignoreRestSiblings: true }, + ], + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-empty-function': 'off', + // It"s all very well saying that some types are trivially inferrable, + // but being explicit is still clearer. + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-ignore': 'allow-with-description', + 'ts-expect-error': 'allow-with-description', + }, + ], + '@typescript-eslint/consistent-type-exports': [ + 'error', + { fixMixedExportsWithInlineTypeSpecifier: false }, + ], + }, + overrides: [ + { + files: ['*.d.ts'], + rules: { + 'react/prefer-es6-class': 'off', + }, + }, + ], +}; diff --git a/packages/eui-theme-borealis/.prettierrc b/packages/eui-theme-borealis/.prettierrc new file mode 100644 index 00000000000..b2f0fa8f00e --- /dev/null +++ b/packages/eui-theme-borealis/.prettierrc @@ -0,0 +1,7 @@ +{ + "parser": "typescript", + "printWidth": 80, + "semi": true, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/packages/eui-theme-borealis/.stylelintrc.js b/packages/eui-theme-borealis/.stylelintrc.js new file mode 100644 index 00000000000..42adc41f28c --- /dev/null +++ b/packages/eui-theme-borealis/.stylelintrc.js @@ -0,0 +1,163 @@ +const camelCaseRegex = '^[a-z][\\w-]*$'; // Note: also allows `_` as part of BEM naming +const camelCaseValueRegex = '/^[a-z][\\w.]*$/'; // Note: also allows `.` for JS objects +const cssInJsVarRegex = '/\\${[a-zA-Z]+/'; + +module.exports = { + // @see https://stylelint.io/user-guide/rules + rules: { + // Enforce camelCase naming + 'selector-class-pattern': camelCaseRegex, + 'keyframes-name-pattern': camelCaseRegex, + 'custom-property-pattern': camelCaseRegex, + + // Opinionated rules + 'declaration-no-important': true, + 'max-nesting-depth': [ + 2, + { + ignore: ['blockless-at-rules', 'pseudo-classes'], + }, + ], + 'block-no-empty': true, + 'selector-no-qualifying-type': [ + true, + { + ignore: ['attribute'], // Allows input[type=search] + }, + ], + + // Non-Prettier newline rules + // Put a line-break between sections of CSS, but allow quick one-liners for legibility + 'rule-empty-line-before': [ + 'always-multi-line', + { + ignore: ['first-nested', 'after-comment'], + }, + ], + 'comment-empty-line-before': null, + 'declaration-empty-line-before': null, + + // Value preferences + 'number-max-precision': null, + // Attempt to catch/flag non-variable color values + 'color-named': 'never', + 'color-no-hex': true, + // Prefer lowercase values, except for font names and currentColor + 'value-keyword-case': [ + 'lower', + { + ignoreProperties: ['font-family', '/^\\$eui[\\w]+/'], // Allow fonts and Sass variables + ignoreKeywords: ['currentColor'], + }, + ], + 'declaration-block-no-duplicate-properties': [ + true, + { + ignore: ['consecutive-duplicates'], // We occasionally use duplicate property values for cross-browser fallbacks + }, + ], + + // TODO: It may be worth investigating and updating these rules to their more modern counterparts + 'color-function-notation': 'legacy', + 'alpha-value-notation': 'number', + + // Disable various opinionated extended stylelint rules that EUI has not previously enforced + 'no-descending-specificity': null, + 'keyframe-selector-notation': null, + 'declaration-block-no-redundant-longhand-properties': null, + }, + overrides: [ + { + // TODO: Remove Sass-specific config & rules once we're completely off Sass + files: ['**/*.scss'], + ignoreFiles: [ + 'generator-eui/**/*.scss', + 'src/global_styling/react_date_picker/**/*.scss', + 'src/themes/amsterdam/global_styling/react_date_picker/**/*.scss', + 'src/components/date_picker/react-datepicker/**/*.scss', + ], + extends: [ + 'stylelint-config-standard-scss', + 'stylelint-config-prettier-scss', + ], + // @see https://github.com/stylelint-scss/stylelint-scss#list-of-rules + rules: { + // Casing + 'scss/dollar-variable-pattern': camelCaseRegex, + 'scss/at-mixin-pattern': camelCaseRegex, + 'scss/at-function-pattern': camelCaseRegex, + 'function-name-case': [ + 'lower', + { + ignoreFunctions: [`/${camelCaseRegex}/`, 'MIN'], + }, + ], + + // Whitespace/newlines + 'scss/at-if-closing-brace-space-after': 'always-intermediate', + 'scss/operator-no-unspaced': true, + + // Formatting rules deprecated as of v15 - keep them in Sass styles just in case until end of migration + // @see https://github.com/stylelint/stylelint/blob/main/docs/user-guide/rules.md#deprecated + 'color-hex-case': 'upper', + 'string-quotes': 'single', + // 2 spaces for indentation + indentation: [2, { indentInsideParens: 'once-at-root-twice-in-block' }], + // Mimic 1tbs `} else {` brace style, like our JS + 'block-opening-brace-space-before': 'always', + 'block-closing-brace-newline-before': 'always-multi-line', + // Ensure multiple selectors on one line each + 'selector-list-comma-newline-before': 'never-multi-line', + 'selector-list-comma-newline-after': 'always', + // Trim unnecessary newlines/whitespace + 'block-closing-brace-empty-line-before': 'never', + 'max-empty-lines': 1, + 'no-eol-whitespace': true, + // Enforce spacing around various syntax symbols (colons, operators, etc.) + 'declaration-colon-space-after': 'always-single-line', + 'declaration-colon-space-before': 'never', + 'function-calc-no-unspaced-operator': true, + 'selector-combinator-space-before': 'always', + 'selector-combinator-space-after': 'always', + // Ensure trailing semicolons are always present on non-oneliners + 'declaration-block-semicolon-newline-after': 'always-multi-line', + + // Disable various opinionated extended stylelint rules that EUI has not previously enforced + 'scss/no-global-function-names': null, + 'scss/dollar-variable-empty-line-before': null, + 'scss/at-rule-conditional-no-parentheses': null, + 'scss/double-slash-comment-empty-line-before': null, + 'scss/at-if-no-null': null, + 'selector-not-notation': null, // Enforce comma notation for CSS-in-JS moving forward + }, + }, + { + files: ['**/*.styles.ts', '**/*.ts', '**/*.tsx'], + extends: ['stylelint-config-standard'], + customSyntax: 'postcss-styled-syntax', + rules: { + // Unfortunately, double slash comments must be replaced with standard CSS /* */ comments + // Otherwise we get a parsing error - see https://github.com/hudochenkov/postcss-styled-syntax#known-issues + 'no-invalid-double-slash-comments': true, + // Empty style keys should be allowed, as Emotion still uses them for generating classNames + 'no-empty-source': null, + // Don't lint casing on interpolated JS vars + 'function-name-case': ['lower', { ignoreFunctions: [cssInJsVarRegex] }], + 'function-no-unknown': [true, { ignoreFunctions: [cssInJsVarRegex] }], + 'value-keyword-case': [ + 'lower', + { + ignoreProperties: ['font-family'], + ignoreKeywords: [camelCaseValueRegex], + }, + ], + // This is set to deprecate after stylelint v16, but in the meanwhile, is helpful + // for finding extraneous semicolons after utils that already output semicolons (e.g. logicalCSS()) + 'no-extra-semicolons': true, + + // Emotion uses the `label` property to generate the output className string + 'property-no-unknown': [true, { ignoreProperties: 'label' }], + }, + }, + ], +}; diff --git a/packages/eui-theme-borealis/package.json b/packages/eui-theme-borealis/package.json index dcd766e3984..9b9151acb60 100644 --- a/packages/eui-theme-borealis/package.json +++ b/packages/eui-theme-borealis/package.json @@ -4,9 +4,13 @@ "description": "A visual theme for EUI", "license": "SEE LICENSE IN LICENSE.txt", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "build:workspaces": "yarn workspaces foreach -Rti --from @elastic/eui-theme-borealis --exclude @elastic/eui-theme-borealis run build", "build": "tsc", - "build-pack": "yarn build && npm pack" + "build-pack": "yarn build && npm pack", + "lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-sass", + "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", + "lint-sass": "yarn stylelint \"**/*.scss\" --quiet-deprecation-warnings", + "test": "jest" }, "repository": { "type": "git", @@ -15,13 +19,27 @@ }, "private": true, "devDependencies": { - "@elastic/eui-common": "workspace:^", - "@elastic/eui-theme-base": "workspace:^", + "@elastic/eui-theme-common": "workspace:^", + "@types/jest": "^29.5.12", + "@types/prettier": "2.7.3", + "@typescript-eslint/eslint-plugin": "^5.59.7", + "@typescript-eslint/parser": "^5.59.7", + "eslint": "^8.41.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jest": "^28.5.0", + "eslint-plugin-local": "^1.0.0", + "eslint-plugin-prettier": "^4.2.1", + "jest": "^29.7.0", + "prettier": "^2.8.8", + "stylelint": "^15.7.0", + "stylelint-config-prettier-scss": "^1.0.0", + "stylelint-config-standard": "^33.0.0", + "stylelint-config-standard-scss": "^9.0.0", "typescript": "^5.6.2" }, "peerDependencies": { - "@elastic/eui-common": "0.0.1", - "@elastic/eui-theme-base": "0.0.1" + "@elastic/eui-theme-common": "0.0.1" }, "main": "lib/index.js", "exports": { @@ -34,5 +52,8 @@ "lib/", "src/**/*.scss", "README.md" - ] + ], + "installConfig": { + "hoistingLimits": "workspaces" + } } diff --git a/packages/eui-theme-borealis/src/index.ts b/packages/eui-theme-borealis/src/index.ts index be797a62519..1427ca8b1e9 100644 --- a/packages/eui-theme-borealis/src/index.ts +++ b/packages/eui-theme-borealis/src/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { buildTheme, EuiThemeShape } from '@elastic/eui-theme-base'; +import { buildTheme, EuiThemeShape } from '@elastic/eui-theme-common'; import { colors } from './variables/_colors'; import { animation } from './variables/_animation'; diff --git a/packages/eui-theme-borealis/src/theme_dark.scss b/packages/eui-theme-borealis/src/theme_dark.scss index 52507d8984a..f07a4678b9f 100644 --- a/packages/eui-theme-borealis/src/theme_dark.scss +++ b/packages/eui-theme-borealis/src/theme_dark.scss @@ -3,4 +3,4 @@ // Global styling @import './variables/index'; -@import 'node_modules/@elastic/eui-common/src/global_styling/index'; \ No newline at end of file +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/index'; \ No newline at end of file diff --git a/packages/eui-theme-borealis/src/theme_light.scss b/packages/eui-theme-borealis/src/theme_light.scss index 19216cf89aa..8c6610678e5 100644 --- a/packages/eui-theme-borealis/src/theme_light.scss +++ b/packages/eui-theme-borealis/src/theme_light.scss @@ -3,4 +3,4 @@ // Global styling @import './variables/index'; -@import 'node_modules/@elastic/eui-common/src/global_styling/index'; \ No newline at end of file +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/index'; \ No newline at end of file diff --git a/packages/eui-theme-borealis/src/variables/_animation.ts b/packages/eui-theme-borealis/src/variables/_animation.ts index e6c52bdaef0..84933441db3 100644 --- a/packages/eui-theme-borealis/src/variables/_animation.ts +++ b/packages/eui-theme-borealis/src/variables/_animation.ts @@ -10,7 +10,7 @@ import type { _EuiThemeAnimationSpeeds, _EuiThemeAnimationEasings, _EuiThemeAnimation, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; export const animation_speed: _EuiThemeAnimationSpeeds = { extraFast: '90ms', diff --git a/packages/eui-theme-borealis/src/variables/_borders.ts b/packages/eui-theme-borealis/src/variables/_borders.ts index 19639073715..35926695e77 100644 --- a/packages/eui-theme-borealis/src/variables/_borders.ts +++ b/packages/eui-theme-borealis/src/variables/_borders.ts @@ -6,8 +6,11 @@ * Side Public License, v 1. */ -import { computed, type _EuiThemeBorder } from '@elastic/eui-theme-base'; -import { sizeToPixel } from '@elastic/eui-common'; +import { + computed, + type _EuiThemeBorder, + sizeToPixel, +} from '@elastic/eui-theme-common'; export const border: _EuiThemeBorder = { color: computed(([lightShade]) => lightShade, ['colors.lightShade']), diff --git a/packages/eui-theme-borealis/src/variables/_breakpoint.ts b/packages/eui-theme-borealis/src/variables/_breakpoint.ts index 2b39afe5351..facd8e14ba4 100644 --- a/packages/eui-theme-borealis/src/variables/_breakpoint.ts +++ b/packages/eui-theme-borealis/src/variables/_breakpoint.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { _EuiThemeBreakpoints } from '@elastic/eui-theme-base'; +import type { _EuiThemeBreakpoints } from '@elastic/eui-theme-common'; export const breakpoint: _EuiThemeBreakpoints = { xl: 1200, diff --git a/packages/eui-theme-borealis/src/variables/_colors.ts b/packages/eui-theme-borealis/src/variables/_colors.ts index f42e381dde0..09ff1a3e2f5 100644 --- a/packages/eui-theme-borealis/src/variables/_colors.ts +++ b/packages/eui-theme-borealis/src/variables/_colors.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { _EuiThemeColors } from '@elastic/eui-theme-base'; +import type { _EuiThemeColors } from '@elastic/eui-theme-common'; import { light_colors } from './_colors_light'; import { dark_colors } from './_colors_dark'; diff --git a/packages/eui-theme-borealis/src/variables/_colors_dark.scss b/packages/eui-theme-borealis/src/variables/_colors_dark.scss index af75f9df34f..e648b1b0841 100644 --- a/packages/eui-theme-borealis/src/variables/_colors_dark.scss +++ b/packages/eui-theme-borealis/src/variables/_colors_dark.scss @@ -1,14 +1,14 @@ // stylelint-disable color-no-hex // This extra import allows any variables that are created via functions to work when loaded into JS -@import 'node_modules/@elastic/eui-common/src/global_styling/functions/index'; +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/functions/index'; // These colors stay the same no matter the theme $euiColorGhost: #FFF !default; $euiColorInk: #000 !default; // Core -$euiColorPrimary: #00aa00 !default; // test color for distinction +$euiColorPrimary: #0A0 !default; // test color for distinction $euiColorAccent: #F68FBE !default; // Status diff --git a/packages/eui-theme-borealis/src/variables/_colors_dark.ts b/packages/eui-theme-borealis/src/variables/_colors_dark.ts index b1586e837f8..88a280d27c2 100644 --- a/packages/eui-theme-borealis/src/variables/_colors_dark.ts +++ b/packages/eui-theme-borealis/src/variables/_colors_dark.ts @@ -8,14 +8,13 @@ import { computed, - type _EuiThemeColors, type _EuiThemeBrandColors, type _EuiThemeBrandTextColors, type _EuiThemeShadeColors, type _EuiThemeSpecialColors, type _EuiThemeTextColors, type _EuiThemeColorsMode, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; /* * DARK THEME diff --git a/packages/eui-theme-borealis/src/variables/_colors_light.scss b/packages/eui-theme-borealis/src/variables/_colors_light.scss index 4588ef5e096..610ff5327bf 100644 --- a/packages/eui-theme-borealis/src/variables/_colors_light.scss +++ b/packages/eui-theme-borealis/src/variables/_colors_light.scss @@ -1,14 +1,14 @@ // stylelint-disable color-no-hex // This extra import allows any variables that are created via functions to work when loaded into JS -@import 'node_modules/@elastic/eui-common/src/global_styling/functions/index'; +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/functions/index'; // These colors stay the same no matter the theme $euiColorGhost: #FFF !default; $euiColorInk: #000 !default; // Core -$euiColorPrimary: #00ff00 !default; // test color for distinction +$euiColorPrimary: #0F0 !default; // test color for distinction $euiColorAccent: #F04E98 !default; // Status diff --git a/packages/eui-theme-borealis/src/variables/_colors_light.ts b/packages/eui-theme-borealis/src/variables/_colors_light.ts index 7d6a8124156..95715428e71 100644 --- a/packages/eui-theme-borealis/src/variables/_colors_light.ts +++ b/packages/eui-theme-borealis/src/variables/_colors_light.ts @@ -8,14 +8,13 @@ import { computed, - type _EuiThemeColors, type _EuiThemeBrandColors, type _EuiThemeBrandTextColors, type _EuiThemeShadeColors, type _EuiThemeSpecialColors, type _EuiThemeTextColors, type _EuiThemeColorsMode, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; /* * LIGHT THEME diff --git a/packages/eui-theme-borealis/src/variables/_index.scss b/packages/eui-theme-borealis/src/variables/_index.scss index 77409be2e50..9768a81e8ee 100644 --- a/packages/eui-theme-borealis/src/variables/_index.scss +++ b/packages/eui-theme-borealis/src/variables/_index.scss @@ -1,5 +1,5 @@ // Import base theme first, then override -@import 'node_modules/@elastic/eui-theme-base/src/variables/index'; +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/index'; @import 'states'; @import 'buttons'; diff --git a/packages/eui-theme-borealis/src/variables/_levels.ts b/packages/eui-theme-borealis/src/variables/_levels.ts index 94a26288967..1f4e2db0bb7 100644 --- a/packages/eui-theme-borealis/src/variables/_levels.ts +++ b/packages/eui-theme-borealis/src/variables/_levels.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { _EuiThemeLevels } from '@elastic/eui-theme-base'; +import type { _EuiThemeLevels } from '@elastic/eui-theme-common'; export const levels: _EuiThemeLevels = { toast: 9000, diff --git a/packages/eui-theme-borealis/src/variables/_size.ts b/packages/eui-theme-borealis/src/variables/_size.ts index 6982ef4af39..1b3fe6a8ea2 100644 --- a/packages/eui-theme-borealis/src/variables/_size.ts +++ b/packages/eui-theme-borealis/src/variables/_size.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -import { sizeToPixel } from '@elastic/eui-common'; import { computed, + sizeToPixel, type _EuiThemeBase, type _EuiThemeSizes, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; export const base: _EuiThemeBase = 16; diff --git a/packages/eui-theme-borealis/src/variables/_states.ts b/packages/eui-theme-borealis/src/variables/_states.ts index 2ffe0e84efe..776a00ffeca 100644 --- a/packages/eui-theme-borealis/src/variables/_states.ts +++ b/packages/eui-theme-borealis/src/variables/_states.ts @@ -6,8 +6,11 @@ * Side Public License, v 1. */ -import { sizeToPixel } from '@elastic/eui-common'; -import { computed, type _EuiThemeFocus } from '@elastic/eui-theme-base'; +import { + computed, + sizeToPixel, + type _EuiThemeFocus, +} from '@elastic/eui-theme-common'; export const focus: _EuiThemeFocus = { // Focus ring diff --git a/packages/eui-theme-borealis/src/variables/_typography.ts b/packages/eui-theme-borealis/src/variables/_typography.ts index 7d27fe803f3..6454c7b239c 100644 --- a/packages/eui-theme-borealis/src/variables/_typography.ts +++ b/packages/eui-theme-borealis/src/variables/_typography.ts @@ -12,7 +12,7 @@ import { type _EuiThemeFontBase, type _EuiThemeFontScales, type _EuiThemeFontWeights, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; // Typographic scale -- loosely based on Major Third (1.250) export const fontScale: _EuiThemeFontScales = { diff --git a/packages/eui-theme-common/.babelrc.js b/packages/eui-theme-common/.babelrc.js new file mode 100644 index 00000000000..0fc74dd1fe9 --- /dev/null +++ b/packages/eui-theme-common/.babelrc.js @@ -0,0 +1,27 @@ +module.exports = { + // We need to preserve comments as they are used by webpack for + // naming chunks during code-splitting. The compression step during + // bundling will remove them later. + comments: true, + + presets: [ + [ + '@babel/env', + { + // `targets` property set via `.browserslistrc` + useBuiltIns: process.env.NO_COREJS_POLYFILL ? false : 'usage', + corejs: !process.env.NO_COREJS_POLYFILL ? '3.6' : undefined, + modules: process.env.BABEL_MODULES + ? process.env.BABEL_MODULES === 'false' + ? false + : process.env.BABEL_MODULES + : 'commonjs', // babel's default is commonjs + }, + ], + ['@babel/react', { runtime: 'classic' }], + [ + '@babel/typescript', + { isTSX: true, allExtensions: true, allowDeclareFields: true }, + ], + ], +}; diff --git a/packages/eui-theme-common/.eslintignore b/packages/eui-theme-common/.eslintignore new file mode 100644 index 00000000000..c6be7e9a761 --- /dev/null +++ b/packages/eui-theme-common/.eslintignore @@ -0,0 +1,10 @@ +dist +node_modules +lib +types +**/*.d.ts +package.json +scripts +.eslintrc.js +babel.config.js +jest.config.js diff --git a/packages/eui-theme-common/.eslintplugin.js b/packages/eui-theme-common/.eslintplugin.js new file mode 100644 index 00000000000..25ddbe3db65 --- /dev/null +++ b/packages/eui-theme-common/.eslintplugin.js @@ -0,0 +1,3 @@ +exports.rules = { + 'require-license-header': require('./scripts/eslint-plugin-local/require_license_header.js'), +}; diff --git a/packages/eui-theme-common/.eslintrc.js b/packages/eui-theme-common/.eslintrc.js new file mode 100644 index 00000000000..e33853c0255 --- /dev/null +++ b/packages/eui-theme-common/.eslintrc.js @@ -0,0 +1,114 @@ +const SSPL_ELASTIC_2_0_LICENSE_HEADER = ` +/* + * 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. + */ +`; + +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: ['./tsconfig.json'], + ecmaFeatures: { + jsx: true, + }, + }, + settings: { + 'import/resolver': { + node: { + extensions: ['.ts', '.tsx', '.js', '.json'], + }, + }, + }, + extends: [ + 'plugin:@typescript-eslint/recommended', + // Prettier options need to come last, in order to override other style rules + 'plugin:prettier/recommended', + ], + plugins: ['local', 'import'], + rules: { + 'block-scoped-var': 'error', + camelcase: 'off', + 'dot-notation': ['error', { allowKeywords: true }], + eqeqeq: ['error', 'always', { null: 'ignore' }], + 'guard-for-in': 'error', + 'new-cap': ['error', { capIsNewExceptions: ['Private'] }], + 'no-caller': 'error', + 'no-const-assign': 'error', + 'no-debugger': 'error', + 'no-empty': ['error', { allowEmptyCatch: true }], + 'no-eval': 'error', + 'no-extend-native': 'error', + 'no-global-assign': 'error', + 'no-loop-func': 'error', + 'no-restricted-globals': ['error', 'context'], + 'no-script-url': 'error', + 'no-sequences': 'error', + 'no-var': 'error', + 'no-with': 'error', + 'prefer-const': 'error', + 'prefer-template': 'error', + strict: ['error', 'never'], + 'valid-typeof': 'error', + + 'local/require-license-header': [ + 'warn', + { + license: SSPL_ELASTIC_2_0_LICENSE_HEADER, + }, + ], + + 'import/no-unresolved': ['error', { amd: true, commonjs: true }], + 'import/namespace': 'error', + 'import/default': 'error', + 'import/export': 'error', + 'import/no-named-as-default': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-duplicates': 'error', + + '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-member-accessibility': 'off', + '@typescript-eslint/indent': 'off', + '@typescript-eslint/ban-tslint-comment': 'error', + '@typescript-eslint/no-empty-interface': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-parameter-properties': 'off', + '@typescript-eslint/no-triple-slash-reference': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { argsIgnorePattern: '^_', ignoreRestSiblings: true }, + ], + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-empty-function': 'off', + // It"s all very well saying that some types are trivially inferrable, + // but being explicit is still clearer. + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-ignore': 'allow-with-description', + 'ts-expect-error': 'allow-with-description', + }, + ], + '@typescript-eslint/consistent-type-exports': [ + 'error', + { fixMixedExportsWithInlineTypeSpecifier: false }, + ], + }, + overrides: [ + { + files: ['*.d.ts'], + rules: { + 'react/prefer-es6-class': 'off', + }, + }, + ], +}; diff --git a/packages/eui-theme-common/.gitignore b/packages/eui-theme-common/.gitignore new file mode 100644 index 00000000000..4450fe8d868 --- /dev/null +++ b/packages/eui-theme-common/.gitignore @@ -0,0 +1,11 @@ +# Dependencies +/node_modules + +# Production +/lib + +yarn-debug.log* +yarn-error.log* + +# Build-related files +.eslintcache \ No newline at end of file diff --git a/packages/eui-theme-common/.prettierrc b/packages/eui-theme-common/.prettierrc new file mode 100644 index 00000000000..b2f0fa8f00e --- /dev/null +++ b/packages/eui-theme-common/.prettierrc @@ -0,0 +1,7 @@ +{ + "parser": "typescript", + "printWidth": 80, + "semi": true, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/packages/eui-theme-common/.stylelintrc.js b/packages/eui-theme-common/.stylelintrc.js new file mode 100644 index 00000000000..42adc41f28c --- /dev/null +++ b/packages/eui-theme-common/.stylelintrc.js @@ -0,0 +1,163 @@ +const camelCaseRegex = '^[a-z][\\w-]*$'; // Note: also allows `_` as part of BEM naming +const camelCaseValueRegex = '/^[a-z][\\w.]*$/'; // Note: also allows `.` for JS objects +const cssInJsVarRegex = '/\\${[a-zA-Z]+/'; + +module.exports = { + // @see https://stylelint.io/user-guide/rules + rules: { + // Enforce camelCase naming + 'selector-class-pattern': camelCaseRegex, + 'keyframes-name-pattern': camelCaseRegex, + 'custom-property-pattern': camelCaseRegex, + + // Opinionated rules + 'declaration-no-important': true, + 'max-nesting-depth': [ + 2, + { + ignore: ['blockless-at-rules', 'pseudo-classes'], + }, + ], + 'block-no-empty': true, + 'selector-no-qualifying-type': [ + true, + { + ignore: ['attribute'], // Allows input[type=search] + }, + ], + + // Non-Prettier newline rules + // Put a line-break between sections of CSS, but allow quick one-liners for legibility + 'rule-empty-line-before': [ + 'always-multi-line', + { + ignore: ['first-nested', 'after-comment'], + }, + ], + 'comment-empty-line-before': null, + 'declaration-empty-line-before': null, + + // Value preferences + 'number-max-precision': null, + // Attempt to catch/flag non-variable color values + 'color-named': 'never', + 'color-no-hex': true, + // Prefer lowercase values, except for font names and currentColor + 'value-keyword-case': [ + 'lower', + { + ignoreProperties: ['font-family', '/^\\$eui[\\w]+/'], // Allow fonts and Sass variables + ignoreKeywords: ['currentColor'], + }, + ], + 'declaration-block-no-duplicate-properties': [ + true, + { + ignore: ['consecutive-duplicates'], // We occasionally use duplicate property values for cross-browser fallbacks + }, + ], + + // TODO: It may be worth investigating and updating these rules to their more modern counterparts + 'color-function-notation': 'legacy', + 'alpha-value-notation': 'number', + + // Disable various opinionated extended stylelint rules that EUI has not previously enforced + 'no-descending-specificity': null, + 'keyframe-selector-notation': null, + 'declaration-block-no-redundant-longhand-properties': null, + }, + overrides: [ + { + // TODO: Remove Sass-specific config & rules once we're completely off Sass + files: ['**/*.scss'], + ignoreFiles: [ + 'generator-eui/**/*.scss', + 'src/global_styling/react_date_picker/**/*.scss', + 'src/themes/amsterdam/global_styling/react_date_picker/**/*.scss', + 'src/components/date_picker/react-datepicker/**/*.scss', + ], + extends: [ + 'stylelint-config-standard-scss', + 'stylelint-config-prettier-scss', + ], + // @see https://github.com/stylelint-scss/stylelint-scss#list-of-rules + rules: { + // Casing + 'scss/dollar-variable-pattern': camelCaseRegex, + 'scss/at-mixin-pattern': camelCaseRegex, + 'scss/at-function-pattern': camelCaseRegex, + 'function-name-case': [ + 'lower', + { + ignoreFunctions: [`/${camelCaseRegex}/`, 'MIN'], + }, + ], + + // Whitespace/newlines + 'scss/at-if-closing-brace-space-after': 'always-intermediate', + 'scss/operator-no-unspaced': true, + + // Formatting rules deprecated as of v15 - keep them in Sass styles just in case until end of migration + // @see https://github.com/stylelint/stylelint/blob/main/docs/user-guide/rules.md#deprecated + 'color-hex-case': 'upper', + 'string-quotes': 'single', + // 2 spaces for indentation + indentation: [2, { indentInsideParens: 'once-at-root-twice-in-block' }], + // Mimic 1tbs `} else {` brace style, like our JS + 'block-opening-brace-space-before': 'always', + 'block-closing-brace-newline-before': 'always-multi-line', + // Ensure multiple selectors on one line each + 'selector-list-comma-newline-before': 'never-multi-line', + 'selector-list-comma-newline-after': 'always', + // Trim unnecessary newlines/whitespace + 'block-closing-brace-empty-line-before': 'never', + 'max-empty-lines': 1, + 'no-eol-whitespace': true, + // Enforce spacing around various syntax symbols (colons, operators, etc.) + 'declaration-colon-space-after': 'always-single-line', + 'declaration-colon-space-before': 'never', + 'function-calc-no-unspaced-operator': true, + 'selector-combinator-space-before': 'always', + 'selector-combinator-space-after': 'always', + // Ensure trailing semicolons are always present on non-oneliners + 'declaration-block-semicolon-newline-after': 'always-multi-line', + + // Disable various opinionated extended stylelint rules that EUI has not previously enforced + 'scss/no-global-function-names': null, + 'scss/dollar-variable-empty-line-before': null, + 'scss/at-rule-conditional-no-parentheses': null, + 'scss/double-slash-comment-empty-line-before': null, + 'scss/at-if-no-null': null, + 'selector-not-notation': null, // Enforce comma notation for CSS-in-JS moving forward + }, + }, + { + files: ['**/*.styles.ts', '**/*.ts', '**/*.tsx'], + extends: ['stylelint-config-standard'], + customSyntax: 'postcss-styled-syntax', + rules: { + // Unfortunately, double slash comments must be replaced with standard CSS /* */ comments + // Otherwise we get a parsing error - see https://github.com/hudochenkov/postcss-styled-syntax#known-issues + 'no-invalid-double-slash-comments': true, + // Empty style keys should be allowed, as Emotion still uses them for generating classNames + 'no-empty-source': null, + // Don't lint casing on interpolated JS vars + 'function-name-case': ['lower', { ignoreFunctions: [cssInJsVarRegex] }], + 'function-no-unknown': [true, { ignoreFunctions: [cssInJsVarRegex] }], + 'value-keyword-case': [ + 'lower', + { + ignoreProperties: ['font-family'], + ignoreKeywords: [camelCaseValueRegex], + }, + ], + // This is set to deprecate after stylelint v16, but in the meanwhile, is helpful + // for finding extraneous semicolons after utils that already output semicolons (e.g. logicalCSS()) + 'no-extra-semicolons': true, + + // Emotion uses the `label` property to generate the output className string + 'property-no-unknown': [true, { ignoreProperties: 'label' }], + }, + }, + ], +}; diff --git a/packages/eui-theme-common/LICENSE.txt b/packages/eui-theme-common/LICENSE.txt new file mode 100644 index 00000000000..74327a8f6f3 --- /dev/null +++ b/packages/eui-theme-common/LICENSE.txt @@ -0,0 +1,6 @@ +Source code in this repository is covered by (i) a dual license under the Server +Side Public License, v 1 and the Elastic License 2.0 or (ii) an Apache License +2.0 compatible license or (iii) solely under the Elastic License 2.0, in each +case, as noted in the applicable header. The default throughout the repository +is a dual license under the Server Side Public License, v 1 and the Elastic +License 2.0, unless the header specifies another license. diff --git a/packages/eui-theme-common/README.md b/packages/eui-theme-common/README.md new file mode 100644 index 00000000000..ff61cce2b64 --- /dev/null +++ b/packages/eui-theme-common/README.md @@ -0,0 +1 @@ +# EUI common theming functionality and styling \ No newline at end of file diff --git a/packages/eui-theme-common/babel.config.js b/packages/eui-theme-common/babel.config.js new file mode 100644 index 00000000000..8165fe45577 --- /dev/null +++ b/packages/eui-theme-common/babel.config.js @@ -0,0 +1,6 @@ +module.exports = { + presets: [ + ['@babel/preset-env', { targets: { node: 'current' } }], + '@babel/preset-typescript', + ], +}; diff --git a/packages/eui-theme-common/jest.config.js b/packages/eui-theme-common/jest.config.js new file mode 100644 index 00000000000..1b5b81ebf06 --- /dev/null +++ b/packages/eui-theme-common/jest.config.js @@ -0,0 +1,7 @@ +const config = { + moduleFileExtensions: ['ts', 'tsx', 'js', 'json'], + testEnvironment: 'node', + testMatch: ['**/*.test.js', '**/*.test.ts'], +}; + +module.exports = config; diff --git a/packages/eui-theme-common/package.json b/packages/eui-theme-common/package.json new file mode 100644 index 00000000000..e4590fefa31 --- /dev/null +++ b/packages/eui-theme-common/package.json @@ -0,0 +1,67 @@ +{ + "name": "@elastic/eui-theme-common", + "version": "0.0.1", + "description": "EUI theme common", + "license": "SEE LICENSE IN LICENSE.txt", + "scripts": { + "build:clean": "rimraf lib/", + "build": "yarn build:clean && yarn build:compile && yarn build:compile:cjs && yarn build:types", + "build:compile": "tsc --project ./tsconfig.json", + "build:compile:cjs": "NODE_ENV=production babel src --out-dir=lib/cjs --extensions .js,.ts,.tsx --source-maps", + "build:types": "NODE_ENV=production tsc --project tsconfig.types.json", + "build-pack": "yarn build && npm pack", + "lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-sass", + "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", + "lint-sass": "yarn stylelint \"**/*.scss\" --quiet-deprecation-warnings", + "test": "jest" + }, + "repository": { + "type": "git", + "url": "https://github.com/elastic/eui.git", + "directory": "packages/eui-theme-common" + }, + "private": true, + "devDependencies": { + "@babel/cli": "^7.21.5", + "@babel/core": "^7.21.8", + "@babel/preset-env": "^7.21.5", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.5", + "@types/jest": "^29.5.12", + "@types/prettier": "2.7.3", + "@typescript-eslint/eslint-plugin": "^5.59.7", + "@typescript-eslint/parser": "^5.59.7", + "eslint": "^8.41.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jest": "^28.5.0", + "eslint-plugin-local": "^1.0.0", + "eslint-plugin-prettier": "^4.2.1", + "jest": "^29.7.0", + "prettier": "^2.8.8", + "rimraf": "^6.0.1", + "stylelint": "^15.7.0", + "stylelint-config-prettier-scss": "^1.0.0", + "stylelint-config-standard": "^33.0.0", + "stylelint-config-standard-scss": "^9.0.0", + "typescript": "4.5.3" + }, + "main": "lib/cjs/index.js", + "exports": { + "./lib/*": "./lib/*", + "./scripts/*": "./scripts/*", + ".": { + "require": "./lib/cjs/index.js", + "import": "./lib/esm/index.js", + "default": "./lib/cjs/index.js" + } + }, + "files": [ + "lib/", + "src/**/*.scss", + "README.md" + ], + "installConfig": { + "hoistingLimits": "workspaces" + } +} diff --git a/packages/eui-theme-common/scripts/eslint-plugin-local/require_license_header.js b/packages/eui-theme-common/scripts/eslint-plugin-local/require_license_header.js new file mode 100644 index 00000000000..23b83648dd1 --- /dev/null +++ b/packages/eui-theme-common/scripts/eslint-plugin-local/require_license_header.js @@ -0,0 +1,132 @@ +const eslintParser = require('@typescript-eslint/parser'); + +function assert(truth, message) { + if (truth) { + return; + } + + const error = new Error(message); + error.failedAssertion = true; + throw error; +} + +function normalizeWhitespace(string) { + return string.replace(/\s+/g, ' '); +} + +function init(context, program, initStep) { + try { + return initStep(); + } catch (error) { + if (error.failedAssertion) { + context.report({ + node: program, + message: error.message, + }); + } else { + throw error; + } + } +} + +function isHashbang(text) { + return text.trim().startsWith('#!') && !text.trim().includes('\n'); +} + +module.exports = { + meta: { + fixable: 'code', + schema: [ + { + type: 'object', + properties: { + license: { + type: 'string', + }, + }, + additionalProperties: false, + }, + ], + }, + create: (context) => { + return { + Program(program) { + const license = init(context, program, function () { + const options = context.options[0] || {}; + const license = options.license; + + assert(!!license, '"license" option is required'); + + const parsed = eslintParser.parse(license, { comment: true }); + assert( + !parsed.body.length, + '"license" option must only include a single comment' + ); + assert( + parsed.comments.length === 1, + '"license" option must only include a single comment' + ); + + return { + source: license, + nodeValue: normalizeWhitespace(parsed.comments[0].value), + }; + }); + + if (!license) { + return; + } + + const sourceCode = context.getSourceCode(); + const comment = sourceCode + .getAllComments() + .find( + (node) => normalizeWhitespace(node.value) === license.nodeValue + ); + + // no licence comment + if (!comment) { + context.report({ + message: 'File must start with a license header', + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: sourceCode.lines[0].length - 1 }, + }, + fix(fixer) { + if (isHashbang(sourceCode.lines[0])) { + return undefined; + } + + return fixer.replaceTextRange([0, 0], license.source + '\n\n'); + }, + }); + return; + } + + // ensure there is nothing before the comment + const sourceBeforeNode = sourceCode + .getText() + .slice(0, sourceCode.getIndexFromLoc(comment.loc.start)); + if (sourceBeforeNode.length && !isHashbang(sourceBeforeNode)) { + context.report({ + node: comment, + message: 'License header must be at the very beginning of the file', + fix(fixer) { + // replace leading whitespace if possible + if (sourceBeforeNode.trim() === '') { + return fixer.replaceTextRange([0, sourceBeforeNode.length], ''); + } + + // inject content at top and remove node from current location + // if removing whitespace is not possible + return [ + fixer.remove(comment), + fixer.replaceTextRange([0, 0], license.source + '\n\n'), + ]; + }, + }); + } + }, + }; + }, +}; diff --git a/packages/eui-theme-common/scripts/eslint-plugin-local/require_license_header.test.js b/packages/eui-theme-common/scripts/eslint-plugin-local/require_license_header.test.js new file mode 100644 index 00000000000..904dff17bc0 --- /dev/null +++ b/packages/eui-theme-common/scripts/eslint-plugin-local/require_license_header.test.js @@ -0,0 +1,177 @@ +const { RuleTester } = require('eslint'); +const rule = require('./require_license_header'); +const dedent = require('dedent'); + +const ruleTester = new RuleTester({ + parser: require.resolve('@typescript-eslint/parser'), +}); + +ruleTester.run('@kbn/eslint/require-license-header', rule, { + valid: [ + { + code: dedent` + /* license */ + + console.log('foo') + `, + + options: [{ license: '/* license */' }], + }, + { + code: dedent` + // license + + console.log('foo') + `, + + options: [{ license: '// license' }], + }, + ], + + invalid: [ + // missing license option + { + code: dedent` + console.log('foo') + `, + + options: [], + errors: [ + { + message: '"license" option is required', + }, + ], + }, + + // content cannot contain multiple block comments + { + code: dedent` + console.log('foo') + `, + + options: [{ license: '/* one *//* two */' }], + errors: [ + { + message: '"license" option must only include a single comment', + }, + ], + }, + + // content cannot contain multiple line comments + { + code: dedent` + console.log('foo') + `, + + options: [{ license: `// one\n// two` }], + errors: [ + { + message: '"license" option must only include a single comment', + }, + ], + }, + + // content cannot contain expressions + { + code: dedent` + console.log('foo') + `, + + options: [ + { + license: dedent` + /* license */ + console.log('hello world'); + `, + }, + ], + errors: [ + { + message: '"license" option must only include a single comment', + }, + ], + }, + + // content is not a single comment + { + code: dedent` + console.log('foo') + `, + + options: [{ license: `console.log('hello world');` }], + errors: [ + { + message: '"license" option must only include a single comment', + }, + ], + }, + + // missing license header + { + code: dedent` + console.log('foo') + `, + + options: [{ license: '/* license */' }], + errors: [ + { + message: 'File must start with a license header', + }, + ], + + output: dedent` + /* license */ + + console.log('foo') + `, + }, + + // strips newlines before the license comment + { + code: + '\n\n' + + dedent` + /* license */ + + console.log('foo') + `, + + options: [{ license: '/* license */' }], + errors: [ + { + message: 'License header must be at the very beginning of the file', + }, + ], + + output: dedent` + /* license */ + + console.log('foo') + `, + }, + + // moves license header before other nodes if necessary + { + code: dedent` + /* not license */ + /* license */ + console.log('foo') + `, + + options: [{ license: '/* license */' }], + errors: [ + { + message: 'License header must be at the very beginning of the file', + }, + ], + + output: dedent` + /* license */ + + /* not license */ + + console.log('foo') + `, + }, + ], +}); diff --git a/packages/eui-theme-common/src/global_styling/functions/_colors.scss b/packages/eui-theme-common/src/global_styling/functions/_colors.scss new file mode 100644 index 00000000000..25834e10add --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/functions/_colors.scss @@ -0,0 +1,138 @@ +// Converting a normal hex color to RBG +@function hexToRGB($color) { + @return 'rgb%28#{round(red($color))}, #{round(green($color))}, #{round(blue($color))}%29'; +} + +// Mixes a provided color with white. +@function tint($color, $percent) { + @return mix($euiColorGhost, $color, $percent); +} + +// Mixes a provided color with black. +@function shade($color, $percent) { + @return mix($euiColorInk, $color, $percent); +} + +// For theming. Checks the text color and tells us whether it's light or dark. +// Based on that we either tint (add white) or shade (add black). +@function tintOrShade($color, $tint, $shade) { + @if (lightness($euiTextColor) > 50) { + @return shade($color, $shade); + } @else { + @return tint($color, $tint); + } +} + +// The reverse of the above +@function shadeOrTint($color, $shade, $tint) { + @if (lightness($euiTextColor) < 50) { + @return shade($color, $shade); + } @else { + @return tint($color, $tint); + } +} + +// Similar to above, but uses the light or dark color based +// on whether it's the light or dark theme +@function lightOrDarkTheme($lightColor, $darkColor) { + @if (lightness($euiTextColor) < 50) { + @return $lightColor; + } @else { + @return $darkColor; + } +} + +// Calculates luminance, which is better than brightness for checking colors +// pow, nth functions come from the _math.scss functions +@function luminance($color) { + // Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef + $rgba: red($color), green($color), blue($color); + $rgba2: (); + + @for $i from 1 through 3 { + $rgb: nth($rgba, $i); + $rgb: $rgb / 255; + + $rgb: if($rgb < .03928, $rgb / 12.92, pow(($rgb + .055) / 1.055, 2.4)); + + $rgba2: append($rgba2, $rgb); + } + + @return .2126 * nth($rgba2, 1) + .7152 * nth($rgba2, 2) + .0722 * nth($rgba2, 3); +} + +// Calculate contrast +@function contrastRatio($background, $foreground) { + $backgroundLum: luminance($background) + .05; + $foregroundLum: luminance($foreground) + .05; + + @return max($backgroundLum, $foregroundLum) / min($backgroundLum, $foregroundLum); +} + +// Given $color, decide whether $lightText or $darkText should be used as the text color +// ex: chooseLightOrDarkText(#EEE, #FFF, #000) would return #000 because it has +// a higher contrast than #FFF against a #EEE background. +@function chooseLightOrDarkText($background, $lightText: $euiColorGhost, $darkText: $euiColorInk) { + $lightContrast: contrastRatio($background, $lightText); + $darkContrast: contrastRatio($background, $darkText); + + @if ($lightContrast > $darkContrast) { + @return $lightText; + } @else { + @return $darkText; + } +} + +// Given a $foreground and a $background, make the $foreground AA accessibility by slightly +// adjusting it till the contrast is high enough +// By default it will compare against the page background color + +// ex: makeContrastColor($lightPink, #FFF) would continually shade the pink until +// it had higher than 4.5 contrast on a white background. +$euiContrastRatioText: 4.5; +@function makeHighContrastColor($foreground, $background: $euiPageBackgroundColor, $ratio: $euiContrastRatioText) { + $contrast: contrastRatio($foreground, $background); + + // Determine the lightness factor of the background color first to + // determine whether to shade or tint the foreground. + $brightness: lightness($background); + + $highContrastTextColor: $foreground; + + @while ($contrast < $ratio) { + @if ($brightness > 50) { + $highContrastTextColor: shade($highContrastTextColor, 5%); + } @else { + $highContrastTextColor: tint($highContrastTextColor, 5%); + } + + $contrast: contrastRatio($highContrastTextColor, $background); + + @if (lightness($highContrastTextColor) < 5) { + @warn 'High enough contrast could not be determined. Most likely your background color does not adjust for light mode.'; + @return $highContrastTextColor; + } + + @if (lightness($highContrastTextColor) > 95) { + @warn 'High enough contrast could not be determined. Most likely your background color does not adjust for dark mode.'; + @return $highContrastTextColor; + } + } + + @return $highContrastTextColor; +} + +// Graphics such as stand alone icons and pieces of a graph only need a minimum ratio of 3:1 with its background. +// Therefore, we can reuse the `makeHighContrastColor()` function but only attain a min contrast of 3.0. +// It is still recommended to use `makeHighContrastColor()` to attain a 4.5:1 ratio if the graphic is small or thinly stroked. +// https://www.w3.org/WAI/GL/low-vision-a11y-tf/wiki/Informational_Graphic_Contrast_(Minimum) +$euiContrastRatioGraphic: 3; +@function makeGraphicContrastColor($color, $background: $euiPageBackgroundColor) { + @return makeHighContrastColor($color, $background, $euiContrastRatioGraphic); +} + +// Disabled content only needs a contrast of at least 2 because there is no interaction available +$euiContrastRatioDisabled: 2; +@function makeDisabledContrastColor($color, $background: $euiPageBackgroundColor) { + @return makeHighContrastColor($color, $background, $euiContrastRatioDisabled); +} diff --git a/packages/eui-theme-common/src/global_styling/functions/_index.scss b/packages/eui-theme-common/src/global_styling/functions/_index.scss new file mode 100644 index 00000000000..de8260b2bba --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/functions/_index.scss @@ -0,0 +1,5 @@ +// Math needs to be first in the load order +@import 'math'; + +// Using math, we have functions to manipulate contrast / luminosity for accessibility +@import 'colors'; diff --git a/packages/eui-theme-common/src/global_styling/functions/_math.scss b/packages/eui-theme-common/src/global_styling/functions/_math.scss new file mode 100644 index 00000000000..cdec36f3e60 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/functions/_math.scss @@ -0,0 +1 @@ +@import 'math_pow'; \ No newline at end of file diff --git a/packages/eui-theme-common/src/global_styling/functions/_math_pow.scss b/packages/eui-theme-common/src/global_styling/functions/_math_pow.scss new file mode 100644 index 00000000000..2e2d784a845 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/functions/_math_pow.scss @@ -0,0 +1,82 @@ +/** +The MIT License (MIT) + +Copyright (c) 2015 strarsis https://github.com/strarsis/sass-math-pow + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +@function pow($number, $exp) { + $exp1: round($exp); + $result: powInt($number, $exp1); + + @if ($exp1 != $exp) { + $result: $result * mathExp(($exp - $exp1) * mathLn($number)); + } + + @return $result; +} + +@function powInt($number, $exp) { + @if $exp == 0 { + @return 1; + } @else if $exp < 0 { + @return 1 / powInt($number, -$exp); + } @else { + $e: floor($exp / 2); + $pow: pow($number, $e); + @if $e * 2 == $exp { + @return $pow * $pow; + } @else { + @return $pow * $pow * $number; + } + } +} + +@function mathExp($value) { + $item: 1; + $result: 1; + + @for $index from 1 to 100 { + $item: $item * $value / $index; + $result: $result + $item; + } + + @return $result; +} + +@function mathLn($value) { + $tenExp: 0; + $lnTen: 2.30258509; + + @while ($value > 1) { + $tenExp: $tenExp + 1; + $value: $value / 10; + } + + $item: -1; + $result: 0; + + @for $index from 1 to 100 { + $item: $item * (1 - $value); + $result: $result + $item / $index; + } + + @return $result + $tenExp * $lnTen; +} diff --git a/packages/eui-theme-common/src/global_styling/functions/index.ts b/packages/eui-theme-common/src/global_styling/functions/index.ts new file mode 100644 index 00000000000..5b07f8b8473 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/functions/index.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export * from './size'; diff --git a/packages/eui-theme-common/src/global_styling/functions/size.ts b/packages/eui-theme-common/src/global_styling/functions/size.ts new file mode 100644 index 00000000000..a96b5b85452 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/functions/size.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +/* TODO: move to a shared module package */ + +/** + * Calculates the `px` value based on a scale multiplier + * @param scale - The font scale multiplier + * * + * @param themeOrBase - Theme base value + * * + * @returns string - Rem unit aligned to baseline + */ + +export const sizeToPixel = + (scale: number = 1) => + (themeOrBase: number | { base: number; [key: string]: any }) => { + const base = + typeof themeOrBase === 'object' ? themeOrBase.base : themeOrBase; + return `${base * scale}px`; + }; diff --git a/packages/eui-theme-common/src/global_styling/index.scss b/packages/eui-theme-common/src/global_styling/index.scss new file mode 100644 index 00000000000..5c29e0435a5 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/index.scss @@ -0,0 +1,18 @@ +// Core + +// Functions need to be first, since we use them in our variables and mixin definitions +@import 'functions/index'; + +// Variables come next, and are used in some mixins +@import 'variables/index'; + +// Mixins provide generic code expansion through helpers +@import 'mixins/index'; + +// Utility classes provide one-off selectors for common css problems +@import 'utility/index'; + +// The reset file has moved to global_styles.tsx + +// Customization of the React Date Picker +@import 'react_date_picker/index'; diff --git a/packages/eui-theme-common/src/global_styling/index.ts b/packages/eui-theme-common/src/global_styling/index.ts new file mode 100644 index 00000000000..47fa2bee007 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/index.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +export * from './types'; +export * from './functions'; +export * from './variables'; diff --git a/packages/eui-theme-common/src/global_styling/mixins/_button.scss b/packages/eui-theme-common/src/global_styling/mixins/_button.scss new file mode 100644 index 00000000000..47c87b6e742 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_button.scss @@ -0,0 +1,149 @@ +// Provides a solid reset and base for handling sizing layout +// Does not include any visual styles +@mixin euiButtonBase { + display: inline-block; + appearance: none; + cursor: pointer; + height: $euiButtonHeight; + line-height: $euiButtonHeight; // prevents descenders from getting cut off + text-align: center; + white-space: nowrap; + max-width: 100%; + vertical-align: middle; +} + +// Adds the focus (and hover) animation for translating up 1px +@mixin euiButtonFocus { + @include euiCanAnimate { + transition: transform $euiAnimSpeedNormal ease-in-out, background-color $euiAnimSpeedNormal ease-in-out; + + &:hover:not(:disabled) { + transform: translateY(-1px); + } + + &:focus { + animation: euiButtonActive $euiAnimSpeedNormal $euiAnimSlightBounce; + } + + &:active:not(:disabled) { + transform: translateY(1px); + } + } +} + +// All of the button base styles including the base, focus, font, and initial styles +// Does not include individual alterations like color or sizes +@mixin euiButton { + @include euiButtonBase; + @include euiFont; + @include euiFontSize; + @include euiButtonFocus; + + font-weight: $euiButtonFontWeight; + text-decoration: none; + outline-offset: -1px; + + &:hover:not(:disabled), + &:focus { + text-decoration: underline; + } +} + +// Correctly lays out the contents of a button when using the proper dom elements of: +// +// 1. Apply margin to all but last item in the flex. +// 2. Margin gets flipped because of the row-reverse. +@mixin euiButtonContent($isReverse: false) { + height: 100%; + width: 100%; + vertical-align: middle; + + .euiButtonContent__icon, + .euiButtonContent__spinner { + flex-shrink: 0; // Ensures the icons/spinner don't scale down below their intended size + } + + @if ($isReverse) { + flex-direction: row-reverse; + + > * + * { + margin-inline-start: 0; // 1, 2 + margin-inline-end: $euiSizeS; // 1, 2 + } + } @else { + display: flex; + justify-content: center; + align-items: center; + + > * + * { + margin-inline-start: $euiSizeS; // 1 + } + } +} + +@mixin euiButtonContentDisabled { + pointer-events: auto; + cursor: not-allowed; + + &:hover, + &:focus, + &:focus-within { + text-decoration: none; + } + + .euiButtonContent__spinner { + border-color: euiLoadingSpinnerBorderColors(currentColor); + } +} + +/* + * Creates the Amsterdam style of button with a transparent background + */ +@mixin euiButtonDefaultStyle($color: 'primary', $includeStates: true, $transparency: $euiButtonDefaultTransparency) { + $backgroundColor: $color; + + @if (map-has-key($euiButtonTypes, $color)) { + $backgroundColor: map-get($euiButtonTypes, $color); + } + + $percentConversion: $transparency * 100%; + // This variable simulates the possibly darkest background the button could be on + // Simulates the 20% opaque color on top of the page background color + $backgroundColorSimulated: mix($euiPageBackgroundColor, $backgroundColor, $percentConversion); + // Then we can calculate the darkest text color needed + color: makeHighContrastColor($backgroundColor, $backgroundColorSimulated); + // But still use transparency + background-color: transparentize($backgroundColor, $transparency); + + @if ($includeStates) { + &:not([class*='isDisabled']) { + &:hover, + &:focus { + // Duplicated from inert state simply to override default theme + background-color: transparentize($backgroundColor, $transparency); + } + } + } +} + +/* + * Creates the Amsterdam style of fill button + */ +@mixin euiButtonFillStyle($color: 'primary') { + $backgroundColor: $color; + + @if (map-has-key($euiButtonTypes, $color)) { + $backgroundColor: map-get($euiButtonTypes, $color); + } + + background-color: $backgroundColor; + color: chooseLightOrDarkText($backgroundColor); +} + +// Keyframe animation declarations can be found in +// utility/animations.scss diff --git a/packages/eui-theme-common/src/global_styling/mixins/_form.scss b/packages/eui-theme-common/src/global_styling/mixins/_form.scss new file mode 100644 index 00000000000..326a8491f87 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_form.scss @@ -0,0 +1,273 @@ +@mixin euiFormControlLayoutPadding($numOfIcons, $side: 'right', $compressed: false) { + $iconSize: $euiSize; + $iconPadding: $euiFormControlPadding; + $marginBetweenIcons: $euiFormControlPadding / 2; + + @if ($compressed) { + $iconPadding: $euiFormControlCompressedPadding; + } + + @if variable-exists(numOfIcons) == false { + @error '$numOfIcons:integer (1-3) must be provided to @mixin euiFormControlLayoutPadding().'; + } @else if $numOfIcons == 1 { + padding-#{$side}: $iconPadding + $iconSize + $iconPadding; + } @else if $numOfIcons == 2 { + padding-#{$side}: $iconPadding + $iconSize + $marginBetweenIcons + $iconSize + $iconPadding; + } @else if $numOfIcons == 3 { + padding-#{$side}: $iconPadding + $iconSize + $marginBetweenIcons + $iconSize + $marginBetweenIcons + $iconSize + $iconPadding; + } +} + +@mixin euiPlaceholderPerBrowser { + // stylelint-disable selector-no-vendor-prefix + // Each prefix must be its own content block + &::-webkit-input-placeholder { @content; opacity: 1; } + &::-moz-placeholder { @content; opacity: 1; } + &:-ms-input-placeholder { @content; opacity: 1; } + &:-moz-placeholder { @content; opacity: 1; } + &::placeholder { @content; opacity: 1; } +} + +@function euiFormControlGradient($color: $euiColorPrimary) { + @return linear-gradient(to top, + $color, + $color 2px, + transparent 2px, + transparent 100% + ); +} + +@mixin euiFormControlText { + @include euiFont; + font-size: $euiFontSizeS; + color: $euiTextColor; + + @include euiPlaceholderPerBrowser { + color: $euiFormControlPlaceholderText; + } +} + +@mixin euiFormControlSize( + $height: $euiFormControlHeight, + $includeAlternates: false +) { + // Default + max-width: $euiFormMaxWidth; + width: 100%; + height: $height; + + @if ($includeAlternates) { + &--fullWidth { + max-width: 100%; + } + + &--compressed { + height: $euiFormControlCompressedHeight; + } + + &--inGroup { + height: 100%; + } + } +} + +@mixin euiFormControlWithIcon($isIconOptional: false, $side: 'left', $compressed: false) { + @if ($isIconOptional) { + @at-root { + #{&}--withIcon { + @include euiFormControlLayoutPadding(1, $side, $compressed); + } + } + } @else { + @include euiFormControlLayoutPadding(1, $side, $compressed); + } +} + +@mixin euiFormControlIsLoading($isNextToIcon: false) { + @at-root { + #{&}-isLoading { + @if ($isNextToIcon) { + @include euiFormControlLayoutPadding(2); + } @else { + @include euiFormControlLayoutPadding(1); + } + } + + #{&}-isLoading#{&}--compressed { + @if ($isNextToIcon) { + @include euiFormControlLayoutPadding(2, $compressed: true); + } @else { + @include euiFormControlLayoutPadding(1, $compressed: true); + } + } + } +} + +// 1. Must supply both values to background-size or some browsers apply the single value to both directions + +@mixin euiFormControlDefaultShadow($borderOnly: false) { + background-color: $euiFormBackgroundColor; + background-repeat: no-repeat; + background-size: 0% 100%; // 1 + + @if ($borderOnly) { + box-shadow: inset 0 0 0 1px $euiFormBorderColor; + } @else { + box-shadow: + #{$euiFormControlBoxShadow}, + inset 0 0 0 1px $euiFormBorderColor; + } + + transition: + box-shadow $euiAnimSpeedFast ease-in, + background-image $euiAnimSpeedFast ease-in, + background-size $euiAnimSpeedFast ease-in, + background-color $euiAnimSpeedFast ease-in; + + // Fixes bug in Firefox where adding a transition to the background-color + // caused a flash of differently styled dropdown. + @supports (-moz-appearance: none) { + // List *must* be in the same order as the above. + transition-property: box-shadow, background-image, background-size; + } +} + +@mixin euiFormControlFocusStyle($borderOnly: false) { + background-color: tintOrShade($euiColorEmptyShade, 0%, 40%); + background-image: euiFormControlGradient(); + background-size: 100% 100%; // 1 + outline: none; // Blanket remove all outlines relying on our own bottom border + + @if ($borderOnly) { + box-shadow: inset 0 0 0 1px $euiFormBorderColor; + } @else { + box-shadow: inset 0 0 0 1px $euiFormBorderColor; + } +} + +@mixin euiFormControlInvalidStyle { + background-image: euiFormControlGradient($euiColorDanger); + background-size: 100%; +} + +@mixin euiFormControlDisabledTextStyle { + color: $euiFormControlDisabledColor; + -webkit-text-fill-color: $euiFormControlDisabledColor; // Required for Safari +} + +@mixin euiFormControlDisabledStyle { + @include euiFormControlDisabledTextStyle; + cursor: not-allowed; + background: $euiFormBackgroundDisabledColor; + box-shadow: inset 0 0 0 1px $euiFormBorderDisabledColor; + + @include euiPlaceholderPerBrowser { + color: $euiFormControlDisabledColor; + } +} + +@mixin euiFormControlReadOnlyStyle { + cursor: default; + color: $euiTextColor; + -webkit-text-fill-color: $euiTextColor; // Required for Safari + // Use transparency since there is no border and in case form is on a non-white background + background: $euiFormBackgroundReadOnlyColor; + border-color: transparent; + box-shadow: inset 0 0 0 1px $euiFormBorderDisabledColor; +} + +// 2. Override invalid state with focus state. + +@mixin euiFormControlStyle($borderOnly: false, $includeStates: true, $includeSizes: true) { + @include euiFormControlSize($includeAlternates: $includeSizes); + @include euiFormControlDefaultShadow; + @include euiFormControlText; + + border: none; + border-radius: $euiFormControlBorderRadius; + padding: $euiFormControlPadding; + + @if ($includeStates) { + &:invalid { // 2 + @include euiFormControlInvalidStyle; + } + + &:focus { // 2 + @include euiFormControlFocusStyle; + } + + &:disabled { + @include euiFormControlDisabledStyle; + } + + &[readOnly] { + @include euiFormControlReadOnlyStyle; + } + + // Needs to be set for autofill + &:-webkit-autofill { + -webkit-text-fill-color: lightOrDarkTheme($euiColorDarkestShade, $euiColorLightShade); + + ~ .euiFormControlLayoutIcons { + color: lightOrDarkTheme($euiColorDarkestShade, $euiColorLightShade); + } + } + } + + @if ($includeSizes) { + &--compressed { + @include euiFormControlStyleCompressed($borderOnly, $includeStates); + } + + &--inGroup { + // stylelint-disable-next-line declaration-no-important + box-shadow: none !important; + border-radius: 0; + } + } +} + +@mixin euiFormControlStyleCompressed($borderOnly: false, $includeStates: true) { + @include euiFormControlDefaultShadow($borderOnly: true); + padding: $euiFormControlCompressedPadding; + border-radius: $euiFormControlCompressedBorderRadius; + + @if ($includeStates) { + &:invalid { // 2 + @include euiFormControlInvalidStyle; + } + + &:focus { // 2 + @include euiFormControlFocusStyle($borderOnly: true); + } + + &:disabled { + @include euiFormControlDisabledStyle; + } + + &[readOnly] { + @include euiFormControlReadOnlyStyle; + } + } +} + +@mixin euiHiddenSelectableInput { + position: absolute; + // stylelint-disable-next-line declaration-no-important + opacity: 0 !important; // Make sure it's still hidden when :disabled + width: 100%; + height: 100%; + cursor: pointer; +} + +// Adjusts form controls border radius +@mixin euiFormControlSideBorderRadius($borderRadius, $side, $internal: false) { + @if $internal == true { + $borderRadius: $borderRadius - 1; + } + @if $side == 'left' { + border-radius: $borderRadius 0 0 $borderRadius; + } @else if $side == 'right' { + border-radius: 0 $borderRadius $borderRadius 0; + } +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_helpers.scss b/packages/eui-theme-common/src/global_styling/mixins/_helpers.scss new file mode 100644 index 00000000000..00688ef63ef --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_helpers.scss @@ -0,0 +1,126 @@ +// Helper mixins + +// Set scroll bar appearance on Chrome (and firefox). +@mixin euiScrollBar($thumbColor: $euiColorDarkShade, $trackBackgroundColor: transparent, $size: 'thin') { + // Firefox's scrollbar coloring cascades, but the sizing does not, + // so it's being added to this mixin for allowing support wherever custom scrollbars are + scrollbar-color: transparentize($thumbColor, .5) $trackBackgroundColor; // Firefox support + + @if ($size == 'thin') { + scrollbar-width: thin; + } + + // stylelint-disable selector-no-vendor-prefix + &::-webkit-scrollbar { + width: $euiScrollBar; + height: $euiScrollBar; + } + + &::-webkit-scrollbar-thumb { + background-color: transparentize($thumbColor, .5); + background-clip: content-box; + border-radius: $euiScrollBar; + + @if ($size == 'thin') { + border: $euiScrollBarCornerThin solid $trackBackgroundColor; + } @else { + border: $euiScrollBarCorner solid $trackBackgroundColor; + } + } + + &::-webkit-scrollbar-corner, + &::-webkit-scrollbar-track { + background-color: $trackBackgroundColor; + } +} + +/** + * 1. Focus rings shouldn't be visible on scrollable regions, but a11y requires them to be focusable. + * Browser's supporting `:focus-visible` will still show outline on keyboard focus only. + * Others like Safari, won't show anything at all. + * 2. Force the `:focus-visible` when the `tabindex=0` (is tabbable) + */ + +// Just overflow and scrollbars +@mixin euiYScroll { + @include euiScrollBar; + height: 100%; + overflow-y: auto; + overflow-x: hidden; + + &:focus { + outline: none; /* 1 */ + } + + &[tabindex='0']:focus:focus-visible { + outline-style: auto; /* 2 */ + } +} + +@mixin euiXScroll { + @include euiScrollBar; + overflow-x: auto; + + &:focus { + outline: none; /* 1 */ + } + + &[tabindex='0']:focus:focus-visible { + outline-style: auto; /* 2 */ + } +} + +// The full overflow with shadow +@mixin euiYScrollWithShadows { + @include euiYScroll; + @include euiOverflowShadow('y'); +} + +@mixin euiXScrollWithShadows { + @include euiXScroll; + @include euiOverflowShadow('x'); +} + +/** + * For quickly applying a full-height element whether using flex or not + */ +@mixin euiFullHeight { + height: 100%; + flex: 1 1 auto; + overflow: hidden; +} + +// Hiding elements offscreen to only be read by screen reader +// See https://github.com/elastic/eui/pull/5130 and https://github.com/elastic/eui/pull/5152 for more info +@mixin euiScreenReaderOnly { + // Take the element out of the layout + position: absolute; + // Keep it vertically inline + top: auto; + // Chrome requires a left value, and Selenium (used by Kibana's FTR) requires an off-screen position for its .getVisibleText() to not register SR-only text + left: -10000px; + // The element must have a size (for some screen readers) + width: 1px; + height: 1px; + // But reduce the visible size to nothing + clip: rect(0 0 0 0); + clip-path: inset(50%); + // And ensure no overflows occur + overflow: hidden; + // Chrome requires the negative margin to not cause overflows of parent containers + margin: -1px; +} + +// Doesn't have reduced motion turned on +@mixin euiCanAnimate { + @media screen and (prefers-reduced-motion: no-preference) { + @content; + } +} + +// Does have reduced motion turned on +@mixin euiCantAnimate { + @media screen and (prefers-reduced-motion: reduce) { + @content; + } +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_index.scss b/packages/eui-theme-common/src/global_styling/mixins/_index.scss new file mode 100644 index 00000000000..7d0cba8a92e --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_index.scss @@ -0,0 +1,14 @@ +@import 'responsive'; +@import 'shadow'; +@import 'size'; +@import 'typography'; +@import 'helpers'; +@import 'states'; + +@import 'button'; +@import 'form'; +@import 'loading'; +@import 'link'; +@import 'panel'; +@import 'range'; +@import 'tool_tip'; diff --git a/packages/eui-theme-common/src/global_styling/mixins/_link.scss b/packages/eui-theme-common/src/global_styling/mixins/_link.scss new file mode 100644 index 00000000000..98dac59b9cc --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_link.scss @@ -0,0 +1,11 @@ +@mixin euiLink { + text-align: left; + + &:hover { + text-decoration: underline; + } + + &:focus { + text-decoration: underline; + } +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_loading.scss b/packages/eui-theme-common/src/global_styling/mixins/_loading.scss new file mode 100644 index 00000000000..0f72a8433f7 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_loading.scss @@ -0,0 +1,6 @@ +@function euiLoadingSpinnerBorderColors( + $main: $euiColorLightShade, + $highlight: $euiColorPrimary +) { + @return $highlight $main $main $main; +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_panel.scss b/packages/eui-theme-common/src/global_styling/mixins/_panel.scss new file mode 100644 index 00000000000..4eb0a5fb55a --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_panel.scss @@ -0,0 +1,55 @@ +@mixin euiPanel($selector) { + @if variable-exists(selector) == false { + @error 'A $selector must be provided to @mixin euiPanel().'; + } @else { + #{$selector} { + flex-grow: 1; + + &#{$selector}--flexGrowZero { + flex-grow: 0; + } + + &#{$selector}--hasShadow { + @include euiBottomShadowMedium; + } + + &#{$selector}--hasBorder { + border: $euiBorderThin; + box-shadow: none; + } + + &#{$selector}--isClickable { + // transition the shadow + transition: all $euiAnimSpeedFast $euiAnimSlightResistance; + + &:enabled { // This is a good selector for buttons since it doesn't exist on divs + // in case of button wrapper which inherently is inline-block and no width + display: block; + width: 100%; + text-align: left; + } + + &:hover, + &:focus { + @include euiBottomShadow; + transform: translateY(-2px); + cursor: pointer; + } + } + + // Border Radii + @each $modifier, $amount in $euiPanelBorderRadiusModifiers { + &#{$selector}--#{$modifier} { + border-radius: $amount; + } + } + + // Background colors + @each $modifier, $amount in $euiPanelBackgroundColorModifiers { + &#{$selector}--#{$modifier} { + background-color: $amount; + } + } + } + } +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_range.scss b/packages/eui-theme-common/src/global_styling/mixins/_range.scss new file mode 100644 index 00000000000..ec47e39e2d6 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_range.scss @@ -0,0 +1,62 @@ +/* +The CSS in JS version of this file lives in: + - src/components/form/range/range.styles.ts + +The following files still use the Sass version: + - src/themes/amsterdam/overrides/_color_stops.scss + - src/themes/amsterdam/overrides/_hue.scss +*/ + +@mixin euiRangeTrackSize($compressed: false) { + height: $euiRangeTrackHeight; + width: $euiRangeTrackWidth; + + @if ($compressed) { + height: $euiRangeTrackCompressedHeight; + } +} + +@mixin euiRangeTrackPerBrowser { + &::-webkit-slider-runnable-track { @content; } + &::-moz-range-track { @content; } + &::-ms-fill-lower { @content; } + &::-ms-fill-upper { @content; } +} + +@mixin euiRangeThumbBorder { + border: 2px solid $euiRangeThumbBorderColor; +} + +@mixin euiRangeThumbBoxShadow { + box-shadow: + 0 0 0 1px $euiRangeThumbBorderColor, + 0 2px 2px -1px rgba($euiShadowColor, .2), + 0 1px 5px -2px rgba($euiShadowColor, .2); +} + +@mixin euiRangeThumbFocusBoxShadow { + box-shadow: 0 0 0 2px $euiFocusRingColor; +} + +@mixin euiRangeThumbStyle { + @include euiRangeThumbBoxShadow; + @include euiRangeThumbBorder; + cursor: pointer; + background-color: $euiRangeThumbBackgroundColor; + padding: 0; + height: $euiRangeThumbHeight; + width: $euiRangeThumbWidth; + box-sizing: border-box; // required for firefox or the border makes the width and height to increase +} + +@mixin euiRangeThumbPerBrowser { + &::-webkit-slider-thumb { @content; } + &::-moz-range-thumb { @content; } + &::-ms-thumb { @content; } +} + +@mixin euiRangeThumbFocus { + @include euiRangeThumbBorder; + @include euiRangeThumbFocusBoxShadow; + background-color: $euiColorPrimary; +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_responsive.scss b/packages/eui-theme-common/src/global_styling/mixins/_responsive.scss new file mode 100644 index 00000000000..0fa3a9b08a8 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_responsive.scss @@ -0,0 +1,44 @@ +// A sem-complicated mixin for breakpoints, that takes any number of +// named breakpoints that exists in $euiBreakpoints. + +@mixin euiBreakpoint($sizes...) { + // Loop through each size parameter + @each $size in $sizes { + // Store the location of the size in the list to check against + $index: index($euiBreakpointKeys, $size); + + // Check to make sure it exists in the allowed breakpoint names + @if ( $index ) { + + // Set the min size to the value of the size + $minSize: map-get($euiBreakpoints, $size); + + // If it is the last item, don't give it a max-width + @if ( $index == length($euiBreakpointKeys) ) { + @media only screen and (min-width: $minSize) { + @content; + } + // If it's not the last item, add a max-width + } @else { + + // Set the max size to the value of the next size (-1px as to not overlap) + $maxSize: map-get($euiBreakpoints, nth($euiBreakpointKeys, $index + 1)) - 1px; + + // If it's the the first item, don't set a min-width + @if ( $index == 1 ) { + @media only screen and (max-width: $maxSize) { + @content; + } + // Otherwise it should have a min and max width + } @else { + @media only screen and (min-width: $minSize) and (max-width: $maxSize) { + @content; + } + } + } + // If it's not a known breakpoint, throw a warning + } @else { + @warn "euiBreakpoint(): '#{$size}' is not a valid size in $euiBreakpoints. Accepted values are '#{$euiBreakpointKeys}'"; + } + } +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_shadow.scss b/packages/eui-theme-common/src/global_styling/mixins/_shadow.scss new file mode 100644 index 00000000000..1bc64eb085b --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_shadow.scss @@ -0,0 +1,108 @@ +@function shadowOpacity($opacity) { + @if (lightness($euiTextColor) < 50) { + @return $opacity * 1; + } @else { + @return $opacity * 2.5; + } +} + +@mixin euiSlightShadow($color: $euiShadowColor) { + box-shadow: + 0 .8px .8px rgba($color, shadowOpacity(.04)), + 0 2.3px 2px rgba($color, shadowOpacity(.03)); +} + +@mixin euiBottomShadowSmall($color: $euiShadowColor) { + box-shadow: + 0 .7px 1.4px rgba($color, shadowOpacity(.07)), + 0 1.9px 4px rgba($color, shadowOpacity(.05)), + 0 4.5px 10px rgba($color, shadowOpacity(.05)); +} + +@mixin euiBottomShadowMedium($color: $euiShadowColor) { + box-shadow: + 0 .9px 4px -1px rgba($color, shadowOpacity(.08)), + 0 2.6px 8px -1px rgba($color, shadowOpacity(.06)), + 0 5.7px 12px -1px rgba($color, shadowOpacity(.05)), + 0 15px 15px -1px rgba($color, shadowOpacity(.04)); +} + +// Similar to shadow medium but without the bottom depth. Useful for popovers +// that drop UP rather than DOWN. +@mixin euiBottomShadowFlat($color: $euiShadowColor) { + box-shadow: + 0 0 .8px rgba($color, shadowOpacity(.06)), + 0 0 2px rgba($color, shadowOpacity(.04)), + 0 0 5px rgba($color, shadowOpacity(.04)), + 0 0 17px rgba($color, shadowOpacity(.03)); +} + +@mixin euiBottomShadow($color: $euiShadowColor) { + box-shadow: + 0 1px 5px rgba($color, shadowOpacity(.1)), + 0 3.6px 13px rgba($color, shadowOpacity(.07)), + 0 8.4px 23px rgba($color, shadowOpacity(.06)), + 0 23px 35px rgba($color, shadowOpacity(.05)); +} + +@mixin euiBottomShadowLarge( + $color: $euiShadowColor, + $opacity: 0, + $reverse: false +) { + @if ($reverse) { + box-shadow: + 0 -2.7px 9px rgba($color, shadowOpacity(.13)), + 0 -9.4px 24px rgba($color, shadowOpacity(.09)), + 0 -21.8px 43px rgba($color, shadowOpacity(.08)); + } @else { + box-shadow: + 0 2.7px 9px rgba($color, shadowOpacity(.13)), + 0 9.4px 24px rgba($color, shadowOpacity(.09)), + 0 21.8px 43px rgba($color, shadowOpacity(.08)); + } +} + +@mixin euiSlightShadowHover($color: $euiShadowColor) { + box-shadow: + 0 1px 5px rgba($color, shadowOpacity(.1)), + 0 3.6px 13px rgba($color, shadowOpacity(.07)), + 0 8.4px 23px rgba($color, shadowOpacity(.06)), + 0 23px 35px rgba($color, shadowOpacity(.05)); +} + +// stylelint-disable color-named +@mixin euiOverflowShadow($direction: 'y', $side: 'both') { + $hideHeight: $euiScrollBarCornerThin * 1.25; + $gradient: null; + $gradientStart: + transparentize(red, .9) 0%, + transparentize(red, 0) $hideHeight; + $gradientEnd: + transparentize(red, 0) calc(100% - #{$hideHeight}), + transparentize(red, .9) 100%; + @if ($side == 'both' or $side == 'start' or $side == 'end') { + @if ($side == 'both') { + $gradient: $gradientStart, $gradientEnd; + } @else if ($side == 'start') { + $gradient: $gradientStart; + } @else { + $gradient: $gradientEnd; + } + } @else { + @warn "euiOverflowShadow() expects side to be 'both', 'start' or 'end' but got '#{$side}'"; + } + + @if ($direction == 'y') { + mask-image: linear-gradient(to bottom, #{$gradient}); + } @else if ($direction == 'x') { + mask-image: linear-gradient(to right, #{$gradient}); + } @else { + @warn "euiOverflowShadow() expects direction to be 'y' or 'x' but got '#{$direction}'"; + } + + // Chrome+Edge has a very bizarre edge case bug where `mask-image` stops working + // This workaround forces a stacking context on the scrolling container, which + // hopefully addresses the bug. @see https://github.com/elastic/eui/pull/7855 + transform: translateZ(0); +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_size.scss b/packages/eui-theme-common/src/global_styling/mixins/_size.scss new file mode 100644 index 00000000000..809dc870bf8 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_size.scss @@ -0,0 +1,4 @@ +@mixin size($size) { + width: $size; + height: $size; +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_states.scss b/packages/eui-theme-common/src/global_styling/mixins/_states.scss new file mode 100644 index 00000000000..a2d1bc83aef --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_states.scss @@ -0,0 +1,50 @@ +@mixin euiFocusRing($size: 'small', $amsterdamOnlyProp: null) { + @if $size == 'large' { + // It's always OK to use the focus animation. This will take precedence over times we turn it off individually like EuiButtonEmpty + // stylelint-disable-next-line declaration-no-important + animation: $euiAnimSpeedSlow $euiAnimSlightResistance 1 normal forwards focusRingAnimateLarge !important; + } @else { + // stylelint-disable-next-line declaration-no-important + animation: $euiAnimSpeedSlow $euiAnimSlightResistance 1 normal forwards focusRingAnimate !important; + } +} + +// Keyframe animation declarations can be found in +// utility/animations.scss + +@mixin euiFocusBackground($color: $euiColorPrimary) { + background-color: tintOrShade($euiColorPrimary, ((1 - $euiFocusTransparency) * 100%), ((1 - $euiFocusTransparency) * 100%)); +} + +@mixin euiHoverState { + cursor: pointer; + text-decoration: underline; +} + +@mixin euiFocusState($color: $euiColorPrimary) { + @include euiHoverState; + @include euiFocusBackground($color); +} + +@mixin euiDisabledState($color: $euiButtonColorDisabledText) { + cursor: not-allowed; + text-decoration: none; + + @if ($color) { + color: $color; + } +} + +@mixin euiInteractiveStates($focusColor: $euiColorPrimary, $disabledColor: $euiButtonColorDisabledText) { + &:hover { + @include euiHoverState; + } + + &:focus { + @include euiFocusState($focusColor); + } + + &:disabled { + @include euiDisabledState($disabledColor); + } +} diff --git a/packages/eui-theme-common/src/global_styling/mixins/_tool_tip.scss b/packages/eui-theme-common/src/global_styling/mixins/_tool_tip.scss new file mode 100644 index 00000000000..d8feb0d4258 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_tool_tip.scss @@ -0,0 +1,25 @@ +@mixin euiToolTipStyle($size: null) { + @include euiBottomShadow($color: $euiColorInk); + + $euiTooltipBackgroundColor: tintOrShade($euiColorFullShade, 25%, 100%) !default; + $euiTooltipBorderColor: tintOrShade($euiColorFullShade, 35%, 80%) !default; + + border-radius: $euiBorderRadius; + background-color: $euiTooltipBackgroundColor; + color: $euiColorGhost; + z-index: $euiZLevel9; + max-width: 256px; + overflow-wrap: break-word; + padding: $euiSizeS; + + .euiHorizontalRule { + background-color: $euiTooltipBorderColor; + } +} + +@mixin euiToolTipTitle { + font-weight: $euiFontWeightBold; + border-bottom: solid $euiBorderWidthThin $euiTooltipBorderColor; + padding-bottom: $euiSizeXS; + margin-bottom: $euiSizeXS; +} \ No newline at end of file diff --git a/packages/eui-theme-common/src/global_styling/mixins/_typography.scss b/packages/eui-theme-common/src/global_styling/mixins/_typography.scss new file mode 100644 index 00000000000..7090f0e2371 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/mixins/_typography.scss @@ -0,0 +1,167 @@ +// stylelint-disable property-no-vendor-prefix +// stylelint-disable declaration-no-important + +@function fontSizeToRemOrEm($size, $sizingMethod: 'rem') { + @if ($sizingMethod == 'rem') { + @return #{$size / $euiFontSize}rem; + } @else if ($sizingMethod == 'em') { + @return #{$size / $euiFontSize}em; + } +} + +// It can also be applied to calculate paddings +@function marginToRemOrEm($elementSize, $elementFontSize, $sizingMethod: 'rem') { + @if ($sizingMethod == 'rem') { + @return #{$elementSize / $euiFontSize}rem; + } @else if ($sizingMethod == 'em') { + @return #{$elementSize / $elementFontSize}em; + } +} + +// Spit out rem and px +@mixin fontSize($size: $euiFontSize, $sizingMethod: 'rem') { + @if ($sizingMethod == 'rem') { + font-size: $size; + font-size: fontSizeToRemOrEm($size, 'rem'); + } @else if ($sizingMethod == 'em') { + font-size: fontSizeToRemOrEm($size, 'em'); + } +} + +@mixin lineHeightFromBaseline($multiplier: 3) { + line-height: lineHeightFromBaseline($multiplier); +} + +// Some mixins that help us deal with browser scaling of text more consistently. +// Essentially, fonts across eui should scale against the root html element, not +// against parent inheritance. + +// Our base fonts + +@mixin euiFont { + font-family: $euiFontFamily; + font-weight: $euiFontWeightRegular; + letter-spacing: -.005em; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + font-kerning: normal; +} + +@mixin euiCodeFont { + font-family: $euiCodeFontFamily; + letter-spacing: normal; +} + +@mixin euiText { + color: $euiTextColor; + font-weight: $euiFontWeightRegular; +} + +@mixin euiTitle($size: 'm') { + @include euiTextBreakWord; + color: $euiTitleColor; + + @if (map-has-key($euiTitles, $size)) { + @each $property, $value in map-get($euiTitles, $size) { + @if ($property == 'font-size') { + @include fontSize($value); + } @else { + #{$property}: $value; + } + } + } @else { + @include fontSize($size); + @include lineHeightFromBaseline(3); + } +} + +// Font sizing extends, using rem mixin + +@mixin euiFontSizeXS { + @include fontSize($euiFontSizeXS); + line-height: $euiLineHeight; +} + +@mixin euiFontSizeS { + @include fontSize($euiFontSizeS); + line-height: $euiLineHeight; +} + +@mixin euiFontSize { + @include fontSize($euiFontSize); + line-height: $euiLineHeight; +} + +@mixin euiFontSizeM { + @include fontSize($euiFontSizeM); + line-height: $euiLineHeight; +} + +@mixin euiFontSizeL { + @include fontSize($euiFontSizeL); + line-height: $euiLineHeight; +} + +@mixin euiFontSizeXL { + @each $property, $value in map-get($euiTitles, 'm') { + @if ($property == 'font-size') { + @include fontSize($value); + } @else { + #{$property}: $value; + } + } + line-height: 1.25; +} + +@mixin euiFontSizeXXL { + @each $property, $value in map-get($euiTitles, 'l') { + @if ($property == 'font-size') { + @include fontSize($value); + } @else { + #{$property}: $value; + } + } + line-height: 1.25; +} + +@mixin euiTextBreakWord { + // https://css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/ + overflow-wrap: break-word !important; // makes sure the long string will wrap and not bust out of the container + word-break: break-word; +} + +/** + * Text truncation + * + * Prevent text from wrapping onto multiple lines, and truncate with an ellipsis. + * + * 1. Ensure that the node has a maximum width after which truncation can occur. + */ +@mixin euiTextTruncate { + max-width: 100%; // 1 + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +@mixin euiNumberFormat { + font-feature-settings: $euiFontFeatureSettings, 'tnum' 1; // Fixed-width numbers for tabular data +} + +/** + * Text weight shifting + * + * When changing the font-weight based the state of the component + * this mixin will ensure that the sizing is dependent on the boldest + * weight so it doesn't shifter sibling content. + */ +@mixin euiTextShift($fontWeight: $euiFontWeightBold, $attr: 'data-text') { + &::after { + display: block; + content: attr(#{$attr}); + font-weight: $fontWeight; + height: 0; + overflow: hidden; + visibility: hidden; + } +} diff --git a/packages/eui-theme-common/src/global_styling/react_date_picker/_date_picker.scss b/packages/eui-theme-common/src/global_styling/react_date_picker/_date_picker.scss new file mode 100644 index 00000000000..84208a3a648 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/react_date_picker/_date_picker.scss @@ -0,0 +1,772 @@ +/* This file is a heavy retheme of react-datepicker's Sass as of v1.4.0 +** https://github.com/Hacker0x01/react-datepicker +** +** In places where features were disabled, I've commented out the original Sass +** selectors rather than removing it so we can better understand what's changed. +** Commented out selectors that don't have properties indicate that we are not +** using those dom elements for styling of any kind. For example, react-datepicker +** has lots of pointer arrows attached to its popovers, but we choose not to render +** then in any way. +** +** Similarly, you will also find several times where we use display: none to +** completely remove extraneous UI (they had some overly obvious legends for example). +*/ + + +// Because we don't have control over react-datepicker's dom we use SVG URIs for the navigation arrows. +// There is one for light and dark. +@mixin datePickerArrow { + background-position: center; + @if (lightness($euiColorEmptyShade) > 50) { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiI+ICA8ZGVmcz4gICAgPHBhdGggaWQ9ImFycm93X2Rvd24tYSIgZD0iTTEzLjA2ODg1MDgsNS4xNTcyNTAzOCBMOC4zODQyMzk3NSw5Ljc2ODI3NDI4IEM4LjE3MDU0NDE1LDkuOTc4NjEzMDggNy44Mjk5OTIxNCw5Ljk3OTE0MDk1IDcuNjE1NzYwMjUsOS43NjgyNzQyOCBMMi45MzExNDkxNSw1LjE1NzI1MDM4IEMyLjcxODEzNTksNC45NDc1ODMyMSAyLjM3Mjc3MzE5LDQuOTQ3NTgzMjEgMi4xNTk3NTk5NCw1LjE1NzI1MDM4IEMxLjk0Njc0NjY5LDUuMzY2OTE3NTYgMS45NDY3NDY2OSw1LjcwNjg1NTIyIDIuMTU5NzU5OTQsNS45MTY1MjI0IEw2Ljg0NDM3MTA0LDEwLjUyNzU0NjMgQzcuNDg1MTc0MjQsMTEuMTU4MjgzNiA4LjUxNjQ0OTc5LDExLjE1NjY4NTEgOS4xNTU2Mjg5NiwxMC41Mjc1NDYzIEwxMy44NDAyNDAxLDUuOTE2NTIyNCBDMTQuMDUzMjUzMyw1LjcwNjg1NTIyIDE0LjA1MzI1MzMsNS4zNjY5MTc1NiAxMy44NDAyNDAxLDUuMTU3MjUwMzggQzEzLjYyNzIyNjgsNC45NDc1ODMyMSAxMy4yODE4NjQxLDQuOTQ3NTgzMjEgMTMuMDY4ODUwOCw1LjE1NzI1MDM4IFoiLz4gIDwvZGVmcz4gIDxnIGZpbGwtcnVsZT0iZXZlbm9kZCI+ICAgIDx1c2UgZmlsbC1ydWxlPSJub256ZXJvIiB4bGluazpocmVmPSIjYXJyb3dfZG93bi1hIi8+ICA8L2c+PC9zdmc+); + } @else { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiI+ICA8ZGVmcz4gICAgPHBhdGggaWQ9ImRvd25hcnJvd3doaXRlLWEiIGQ9Ik0xMy4wNjg4NTA4LDUuMTU3MjUwMzggTDguMzg0MjM5NzUsOS43NjgyNzQyOCBDOC4xNzA1NDQxNSw5Ljk3ODYxMzA4IDcuODI5OTkyMTQsOS45NzkxNDA5NSA3LjYxNTc2MDI1LDkuNzY4Mjc0MjggTDIuOTMxMTQ5MTUsNS4xNTcyNTAzOCBDMi43MTgxMzU5LDQuOTQ3NTgzMjEgMi4zNzI3NzMxOSw0Ljk0NzU4MzIxIDIuMTU5NzU5OTQsNS4xNTcyNTAzOCBDMS45NDY3NDY2OSw1LjM2NjkxNzU2IDEuOTQ2NzQ2NjksNS43MDY4NTUyMiAyLjE1OTc1OTk0LDUuOTE2NTIyNCBMNi44NDQzNzEwNCwxMC41Mjc1NDYzIEM3LjQ4NTE3NDI0LDExLjE1ODI4MzYgOC41MTY0NDk3OSwxMS4xNTY2ODUxIDkuMTU1NjI4OTYsMTAuNTI3NTQ2MyBMMTMuODQwMjQwMSw1LjkxNjUyMjQgQzE0LjA1MzI1MzMsNS43MDY4NTUyMiAxNC4wNTMyNTMzLDUuMzY2OTE3NTYgMTMuODQwMjQwMSw1LjE1NzI1MDM4IEMxMy42MjcyMjY4LDQuOTQ3NTgzMjEgMTMuMjgxODY0MSw0Ljk0NzU4MzIxIDEzLjA2ODg1MDgsNS4xNTcyNTAzOCBaIi8+ICA8L2RlZnM+ICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICA8dXNlIGZpbGw9IiNGRkYiIGZpbGwtcnVsZT0ibm9uemVybyIgeGxpbms6aHJlZj0iI2Rvd25hcnJvd3doaXRlLWEiLz4gIDwvZz48L3N2Zz4=); + } +} + +// The only "new" css in this component is a wrapper class for dealing with shadows. +// This is mostly here so that we can provide an inline version that doesn't have the +// shadows and depth. +.euiDatePicker { + .euiFormControlLayout { + height: auto; + } + + &.euiDatePicker--shadow { + .react-datepicker-popper { + @include euiBottomShadowMedium; + + border: $euiBorderThin; + background-color: $euiColorEmptyShade; + border-radius: 0 0 $euiBorderRadius $euiBorderRadius; + } + + // If the shadow is on, and it is inline, we need to put the shadow on the datepicker + // itself rather than the popper. + &.euiDatePicker--inline { + .react-datepicker { + @include euiBottomShadowMedium; + + border: $euiBorderThin; + background-color: $euiColorEmptyShade; + border-radius: $euiBorderRadius; + } + } + } +} + +// .react-datepicker-wrapper { +// } + +.react-datepicker { + @include euiFont; + font-size: $euiFontSizeXS; + color: $euiColorFullShade; + display: flex; + position: relative; + border-radius: $euiBorderRadius; +} + +// When in time only mode we make the dropdown look more like the combo box styling. +.react-datepicker--time-only { + + .react-datepicker__time-container { + + .react-datepicker__time { + + .react-datepicker__time-box { + width: 100%; + + .react-datepicker__time-list li.react-datepicker__time-list-item { + font-size: $euiFontSizeS; + text-align: left; + padding-left: $euiSizeXL + $euiSizeXS; + padding-right: $euiSizeXL + $euiSizeXS; + color: $euiTextColor; + + &.react-datepicker__time-list-item--selected { + color: $euiColorGhost; + } + + &.react-datepicker__time-list-item--disabled{ + color: $euiColorDisabledText + } + } + } + } + } + + + .react-datepicker__time-container { + border-left: 0; + } + + // .react-datepicker__triangle { + // } + // .react-datepicker__time { + // } + // .react-datepicker__time-box { + // } +} + +// .react-datepicker__triangle { +// } + +.euiDatePicker.euiDatePicker--shadow .react-datepicker-popper { + z-index: $euiZContentMenu; + animation: euiAnimFadeIn $euiAnimSpeedFast ease-in; + + &[data-placement^="bottom"] { + + // .react-datepicker__triangle { + // } + } + + &[data-placement^="top"] { + @include euiBottomShadowFlat; + + border-radius: $euiBorderRadius $euiBorderRadius 0 0; + + // .react-datepicker__triangle { + // } + } + + &[data-placement^="right"] { + margin-left: 0; + + // .react-datepicker__triangle { + // } + } + + &[data-placement^="left"] { + margin-right: 0; + + // .react-datepicker__triangle { + // } + } +} + +.react-datepicker__header { + text-align: center; + border-top-left-radius: $euiBorderRadius; + border-top-right-radius: $euiBorderRadius; + + &--time { + display: none; + } +} + +.react-datepicker__header__dropdown { + padding: $euiSize 0 $euiSizeS 0; +} + +.react-datepicker__year-dropdown-container--select, +.react-datepicker__month-dropdown-container--select, +.react-datepicker__month-year-dropdown-container--select, +.react-datepicker__year-dropdown-container--scroll, +.react-datepicker__month-dropdown-container--scroll, +.react-datepicker__month-year-dropdown-container--scroll { + display: inline-block; + margin: 0 $euiSizeXS; +} + +.react-datepicker__current-month, +.react-datepicker-time__header { + display: none; +} + +.react-datepicker-time__header { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.react-datepicker__navigation { + cursor: pointer; + position: absolute; + // Pixel pushing because these are icons against text + top: $euiSize + ($euiSizeXS / 2); + width: 0; + padding: 0; + z-index: 1; + text-indent: -999em; + overflow: hidden; + + &--previous { + @include datePickerArrow; + left: $euiSize + $euiSizeXS; + height: $euiSize; + width: $euiSize; + transform: rotate(90deg); + transition: transform $euiAnimSpeedExtraFast ease-in-out; + + &:hover, &:focus { + border-radius: $euiBorderRadius; + transform: scale(1.2) rotate(90deg); + } + + &:hover { + background-color: $euiColorLightestShade; + box-shadow: 0 0 0 ($euiSizeXS / 2) $euiColorLightestShade; + } + + &:focus { + background-color: $euiFocusBackgroundColor; + box-shadow: 0 0 0 ($euiSizeXS / 2) $euiFocusBackgroundColor; + } + + &--disabled, + &--disabled:hover { + cursor: not-allowed ; + opacity: .2; + } + } + + &--next { + @include datePickerArrow; + // Pixel value because of some padding on the icon + right: 20px; + height: $euiSize; + width: $euiSize; + transform: rotate(-90deg); + + &--with-time:not(&--with-today-button) { + // This a pixel value against the width of the cal. It needs + // to be left because the timepicker adds more width + left: 248px; + } + + &:hover, &:focus { + border-radius: $euiBorderRadius; + transform: scale(1.2) rotate(-90deg); + } + + &:hover { + background-color: $euiColorLightestShade; + box-shadow: 0 0 0 ($euiSizeXS / 2) $euiColorLightestShade; + } + + &:focus { + background-color: $euiFocusBackgroundColor; + box-shadow: 0 0 0 ($euiSizeXS / 2) $euiFocusBackgroundColor; + } + + &--disabled, + &--disabled:hover { + cursor: not-allowed ; + opacity: .2; + } + } + + &--years { + position: relative; + top: 0; + display: block; + margin-left: auto; + margin-right: auto; + + &-previous { + top: $euiSizeXS; + border-top-color: $euiColorLightestShade; + + &:hover { + border-top-color: darken($euiColorLightestShade, 10%); + } + } + + &-upcoming { + top: -$euiSizeXS; + border-bottom-color: $euiColorLightestShade; + + &:hover { + border-bottom-color: darken($euiColorLightestShade, 10%); + } + } + } +} + +// .react-datepicker__month-container { +// } + +.react-datepicker__month { + margin: 0 $euiSize $euiSize $euiSize; + text-align: center; + border-radius: $euiBorderRadius; +} + +.react-datepicker__time-container { + border-left: $euiBorderColor; + width: auto; + display: flex; + padding: $euiSize 0; + border-radius: 0 $euiBorderRadius $euiBorderRadius 0; + flex-grow: 1; + + // &--with-today-button { + // } + + .react-datepicker__time { + position: relative; + flex-grow: 1; + display: flex; + padding-left: $euiSizeXS; + flex-direction: column; + + .react-datepicker__time-box { + width: auto; + display: flex; + flex-direction: column; + flex-grow: 1; + + ul.react-datepicker__time-list { + @include euiScrollBar; + height: 204px !important; + display: flex; + flex-direction: column; + flex-grow: 1; + overflow-y: auto; + align-items: center; + + li.react-datepicker__time-list-item { + padding: $euiSizeXS $euiSizeS; + margin-bottom: $euiSizeXS; + text-align: right; + color: $euiColorDarkShade; + white-space: nowrap; + // IE needs this to fix collapsing flex + line-height: $euiSizeM; + + &:hover, + &:focus { + cursor: pointer; + text-decoration: underline; + } + &--selected { + background-color: $euiColorPrimary; + color: white; + border-radius: $euiBorderRadius / 2; + &:hover { + background-color: $euiColorPrimary; + } + } + &--disabled { + color: $euiColorLightShade; + + &:hover { + cursor: not-allowed; + text-decoration: none; + background-color: transparent; + } + } + } + } + } + } +} + +.react-datepicker__week-number { + color: $euiColorLightestShade; + display: inline-block; + width: $euiSizeXL; + line-height: $euiSizeXL - $euiSizeXS; + text-align: center; + margin: 0 $euiSizeXS; + &.react-datepicker__week-number--clickable { + cursor: pointer; + &:hover { + border-radius: $euiBorderRadius; + background-color: $euiColorEmptyShade; + } + } +} + +.react-datepicker__day-names, +.react-datepicker__week { + white-space: nowrap; +} + +.react-datepicker__day-name, +.react-datepicker__day, +.react-datepicker__time-name { + color: $euiColorFullShade; + display: inline-block; + width: $euiSizeXL; + line-height: $euiSizeXL - $euiSizeXS; + text-align: center; + margin: 0 $euiSizeXS / 2; +} + +.react-datepicker__day-name { + color: $euiColorDarkShade; + text-transform: uppercase; +} + +.react-datepicker__day { + cursor: pointer; + border: solid 2px transparent; + transition: transform $euiAnimSpeedExtraFast ease-in-out; + + &:hover:not(&--disabled) { + text-decoration: underline; + font-weight: $euiFontWeightBold; + transform: scale(1.2); + } + + &--today { + font-weight: bold; + color: $euiColorPrimary; + } + &--outside-month { + color: $euiColorDarkShade; + } + + &--highlighted { + border-radius: $euiBorderRadius; + background-color: $euiColorSuccess; + color: $euiColorGhost; + + &:hover { + background-color: darken($euiColorSuccess, 5%); + } + } + + &--in-range { + background-color: transparentize($euiColorPrimary, .9); + color: $euiColorFullShade; + border-radius: 0; + border-top: solid 6px $euiColorEmptyShade; + border-bottom: solid 6px $euiColorEmptyShade; + border-right: none; + border-left: none; + line-height: $euiSizeL - $euiSizeXS; + } + + &--selected, + &--in-selecting-range { + height: $euiSizeXL; + margin: 0 $euiSizeXS / 2; + border-radius: $euiBorderRadius; + background-color: $euiColorPrimary; + line-height: $euiSizeL + $euiSizeXS; + border: solid $euiSizeXS / 2 $euiColorPrimary; + color: $euiColorGhost; + + &:hover { + background-color: darken($euiColorPrimary, 5%); + } + } + + &--keyboard-selected { + border-radius: $euiBorderRadius; + border: solid $euiSizeXS / 2 $euiColorPrimary; + font-weight: $euiFontWeightBold; + + &:hover { + background-color: darken($euiColorPrimary, 5%); + color: $euiColorGhost; + } + } + + &--in-selecting-range:not(&--in-range) { + background-color: rgba($euiColorPrimary, 0.5); + } + + &--in-range:not(&--in-selecting-range) { + .react-datepicker__month--selecting-range & { + background-color: $euiColorEmptyShade; + color: $euiColorFullShade; + } + } + + &--disabled { + cursor: not-allowed; + color: $euiColorLightShade; + + &:hover { + background-color: transparent; + } + } +} + +.react-datepicker__input-container { + position: relative; +} + +.react-datepicker__year-read-view { + font-weight: $euiFontWeightLight; + color: $euiColorDarkShade; +} + +.react-datepicker__month-read-view { + font-weight: $euiFontWeightMedium; +} + +.react-datepicker__year-read-view, +.react-datepicker__month-read-view, +.react-datepicker__month-year-read-view { + font-size: $euiFontSizeL; + + &:hover { + cursor: pointer; + color: $euiColorPrimary; + + .react-datepicker__year-read-view--down-arrow, + .react-datepicker__month-read-view--down-arrow { + border-top-color: darken($euiColorLightestShade, 10%); + } + } + + &--down-arrow { + display: none; + } +} + +.react-datepicker__year-dropdown, +.react-datepicker__month-dropdown, +.react-datepicker__month-year-dropdown { + background-color: $euiColorEmptyShade; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + bottom: 0; + right: 0; + z-index: 1; + text-align: center; + border-radius: $euiBorderRadius; + display: flex; + flex-wrap: wrap; + animation: euiAnimFadeIn $euiAnimSpeedFast ease-in; + align-content: space-around; + align-items: center; + padding: $euiSizeS; + + + &:hover { + cursor: pointer; + } + + // &--scrollable { + // height: 150px; + // overflow-y: scroll; + // } +} + +// Strike that, reverse it Willy Wonka style +.react-datepicker__year-dropdown { + flex-wrap: wrap-reverse; + flex-direction: row-reverse; + justify-content: flex-end; +} + +.react-datepicker__year-option, +.react-datepicker__month-option, +.react-datepicker__month-year-option { + font-size: $euiFontSizeXS; + padding: $euiSizeS; + color: $euiColorDarkestShade; + flex-basis: 33.3%; + + &:first-of-type { + border-top-left-radius: $euiBorderRadius; + border-top-right-radius: $euiBorderRadius; + } + + &:last-of-type { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-bottom-left-radius: $euiBorderRadius; + border-bottom-right-radius: $euiBorderRadius; + } + + &:hover { + background-color: $euiColorLightestShade; + + .react-datepicker__navigation--years-upcoming { + border-bottom-color: darken($euiColorLightestShade, 10%); + } + + .react-datepicker__navigation--years-previous { + border-top-color: darken($euiColorLightestShade, 10%); + } + } + + &--selected { + display: none; + } +} + +.react-datepicker__screenReaderOnly { + position: absolute; + left: -10000px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; +} + +.react-datepicker__year-option--preselected, +.react-datepicker__month-option--preselected { + background: $euiFocusBackgroundColor; +} + +.react-datepicker__year-option--selected_year.react-datepicker__year-option--preselected, +.react-datepicker__month-option--selected_month.react-datepicker__month-option--preselected{ + background: $euiColorPrimary; +} + +.react-datepicker__time-list-item--preselected, +.react-datepicker__year-option--preselected, +.react-datepicker__month-option--preselected { + background: darken($euiFocusBackgroundColor, 5%); +} + +.react-datepicker__time-container--focus { + background: $euiFocusBackgroundColor; +} + +.react-datepicker__month-read-view:focus, +.react-datepicker__year-read-view:focus { + text-decoration: underline; +} + +.react-datepicker__month--accessible:focus { + background: $euiFocusBackgroundColor; + + .react-datepicker__day--in-range:not(.react-datepicker__day--selected) { + border-top-color: $euiFocusBackgroundColor; + border-bottom-color: $euiFocusBackgroundColor; + } +} +.react-datepicker__navigation:focus { + background-color: $euiFocusBackgroundColor; +} + +// These selectors are not a typo. react-datepicker has a bug where these selectors +// output as "--selected_year". Sass has trouble compiling .--selected_year, so instead +// we use this generic selector get around it. +.react-datepicker__year-option--selected_year, +.react-datepicker__month-option--selected_month { + background: $euiColorPrimary; + color: $euiColorEmptyShade; + font-weight: $euiFontWeightBold; + border-radius: $euiBorderRadius; +} + +.react-datepicker__focusTrap { + display: flex; +} + +// The below is for the portal version of react-datepicker which we do not use. +// It is shown here just to know what their baseline includes. + +// .react-datepicker__close-icon { +// background-color: transparent; +// border: 0; +// cursor: pointer; +// display: inline-block; +// height: 0; +// outline: 0; +// padding: 0; +// vertical-align: middle; +// +// &::after { +// background-color: $euiColorPrimary; +// border-radius: 50%; +// bottom: 0; +// box-sizing: border-box; +// color: #fff; +// content: "\00d7"; +// cursor: pointer; +// font-size: 12px; +// height: 16px; +// width: 16px; +// line-height: 1; +// margin: -8px auto 0; +// padding: 2px; +// position: absolute; +// right: 7px; +// text-align: center; +// top: 50%; +// } +// } +// +// .react-datepicker__today-button { +// background: $euiColorEmptyShade; +// border-top: 1px solid $euiBorderColor; +// cursor: pointer; +// text-align: center; +// font-weight: bold; +// padding: 5px 0; +// clear: left; +// } +// +// .react-datepicker__portal { +// position: fixed; +// width: 100vw; +// height: 100vh; +// background-color: rgba(0, 0, 0, 0.8); +// left: 0; +// top: 0; +// justify-content: center; +// align-items: center; +// display: flex; +// z-index: 2147483647; +// +// .react-datepicker__day-name, +// .react-datepicker__day, +// .react-datepicker__time-name { +// width: 3rem; +// line-height: 3rem; +// } +// +// // Resize for small screens +// @media (max-width: 400px), (max-height: 550px) { +// .react-datepicker__day-name, +// .react-datepicker__day, +// .react-datepicker__time-name { +// width: 2rem; +// line-height: 2rem; +// } +// } +// +// .react-datepicker__current-month, +// .react-datepicker-time__header { +// font-size: $euiFontSizeXS * 1.8; +// } +// +// .react-datepicker__navigation { +// border: 1.8 * $euiSize solid transparent; +// } +// +// .react-datepicker__navigation--previous { +// border-right-color: $euiColorLightestShade; +// +// &:hover { +// border-right-color: darken($euiColorLightestShade, 10%); +// } +// +// &--disabled, +// &--disabled:hover { +// border-right-color: $datepicker__navigation-disabled-color; +// cursor: default; +// } +// } +// +// .react-datepicker__navigation--next { +// border-left-color: $euiColorLightestShade; +// +// &:hover { +// border-left-color: darken($euiColorLightestShade, 10%); +// } +// +// &--disabled, +// &--disabled:hover { +// border-left-color: $datepicker__navigation-disabled-color; +// cursor: default; +// } +// } +// } diff --git a/packages/eui-theme-common/src/global_styling/react_date_picker/_index.scss b/packages/eui-theme-common/src/global_styling/react_date_picker/_index.scss new file mode 100644 index 00000000000..48ea2f99771 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/react_date_picker/_index.scss @@ -0,0 +1,2 @@ +@import 'variables'; +@import 'date_picker'; diff --git a/packages/eui-theme-common/src/global_styling/react_date_picker/_variables.scss b/packages/eui-theme-common/src/global_styling/react_date_picker/_variables.scss new file mode 100644 index 00000000000..6a5abd4e528 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/react_date_picker/_variables.scss @@ -0,0 +1 @@ +$euiDatePickerCalendarWidth: 284px; \ No newline at end of file diff --git a/packages/eui-theme-common/src/global_styling/types.ts b/packages/eui-theme-common/src/global_styling/types.ts new file mode 100644 index 00000000000..e2b7a96a9ff --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/types.ts @@ -0,0 +1,106 @@ +/* + * 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 type { CSSObject } from '@emotion/react'; + +import type { RecursivePartial, ValueOf } from '../types'; + +import { _EuiThemeAnimation } from './variables/animations'; +import { _EuiThemeBreakpoints } from './variables/breakpoint'; +import { _EuiThemeBorder } from './variables/borders'; +import { _EuiThemeColors } from './variables/colors'; +import { _EuiThemeBase, _EuiThemeSizes } from './variables/size'; +import { _EuiThemeFont } from './variables/typography'; +import { _EuiThemeFocus } from './variables/states'; +import { _EuiThemeLevels } from './variables/levels'; + +export const COLOR_MODES_STANDARD = { + light: 'LIGHT', + dark: 'DARK', +} as const; +export const COLOR_MODES_INVERSE = 'INVERSE' as const; + +export type EuiThemeColorModeInverse = typeof COLOR_MODES_INVERSE; +export type EuiThemeColorModeStandard = ValueOf; +export type EuiThemeColorMode = + | 'light' + | 'dark' + | EuiThemeColorModeStandard + | 'inverse' + | EuiThemeColorModeInverse; + +export type ColorModeSwitch = + | { + [key in EuiThemeColorModeStandard]: T; + } + | T; + +export type StrictColorModeSwitch = { + [key in EuiThemeColorModeStandard]: T; +}; + +export type EuiThemeShape = { + colors: _EuiThemeColors; + /** - Default value: 16 */ + base: _EuiThemeBase; + /** + * @see {@link https://eui.elastic.co/#/theming/sizing | Reference} for more information + */ + size: _EuiThemeSizes; + font: _EuiThemeFont; + border: _EuiThemeBorder; + focus: _EuiThemeFocus; + animation: _EuiThemeAnimation; + breakpoint: _EuiThemeBreakpoints; + levels: _EuiThemeLevels; +}; + +export type EuiThemeSystem = { + root: EuiThemeShape & T; + model: EuiThemeShape & T; + key: string; +}; + +export type EuiThemeModifications = RecursivePartial; + +export type ComputedThemeShape< + T, + P = string | number | bigint | boolean | null | undefined +> = T extends P | ColorModeSwitch + ? T extends ColorModeSwitch + ? X extends P + ? X + : { + [K in keyof (X & + Exclude< + T, + keyof X | keyof StrictColorModeSwitch + >)]: ComputedThemeShape< + (X & Exclude)[K], + P + >; + } + : T + : { + [K in keyof T]: ComputedThemeShape; + }; + +export type EuiThemeComputed = ComputedThemeShape & { + themeName: string; +}; + +export type EuiThemeNested = { + isGlobalTheme: boolean; + hasDifferentColorFromGlobalTheme: boolean; + bodyColor: string; + colorClassName: string; + setGlobalCSSVariables: Function; + globalCSSVariables?: CSSObject; + setNearestThemeCSSVariables: Function; + themeCSSVariables?: CSSObject; +}; diff --git a/packages/eui-theme-common/src/global_styling/utility/_animations.scss b/packages/eui-theme-common/src/global_styling/utility/_animations.scss new file mode 100644 index 00000000000..c0cb6e7365a --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/utility/_animations.scss @@ -0,0 +1,55 @@ +// Animations as utility so they don't get duplicated in compiled CSS + +@keyframes euiAnimFadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes euiGrow { + 0% { + opacity: 0; + } + + 1% { + opacity: 0; + transform: scale(0); + } + + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes focusRingAnimate { + 0% { + box-shadow: 0 0 0 $euiFocusRingAnimStartSize $euiFocusRingAnimStartColor; + } + + 100% { + box-shadow: 0 0 0 $euiFocusRingSize $euiFocusRingColor; + } +} + +@keyframes focusRingAnimateLarge { + 0% { + box-shadow: 0 0 0 $euiFocusRingAnimStartSizeLarge $euiFocusRingAnimStartColor; + } + + 100% { + box-shadow: 0 0 0 $euiFocusRingSizeLarge $euiFocusRingColor; + } +} + +// Component specific + +@keyframes euiButtonActive { + 50% { + transform: translateY(1px); + } +} diff --git a/packages/eui-theme-common/src/global_styling/utility/_index.scss b/packages/eui-theme-common/src/global_styling/utility/_index.scss new file mode 100644 index 00000000000..5c978807848 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/utility/_index.scss @@ -0,0 +1 @@ +@import 'animations'; diff --git a/packages/eui-theme-common/src/global_styling/variables/_animations.scss b/packages/eui-theme-common/src/global_styling/variables/_animations.scss new file mode 100644 index 00000000000..93b9daf1641 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_animations.scss @@ -0,0 +1,13 @@ +// Animations + +$euiAnimSlightBounce: cubic-bezier(.34, 1.61, .7, 1) !default; +$euiAnimSlightResistance: cubic-bezier(.694, .0482, .335, 1) !default; + +$euiAnimSpeedExtraFast: 90ms !default; +$euiAnimSpeedFast: 150ms !default; +$euiAnimSpeedNormal: 250ms !default; +$euiAnimSpeedSlow: 350ms !default; +$euiAnimSpeedExtraSlow: 500ms !default; + +// Keyframe animation declarations can be found in +// eui/utility/animations.scss diff --git a/packages/eui-theme-common/src/global_styling/variables/_borders.scss b/packages/eui-theme-common/src/global_styling/variables/_borders.scss new file mode 100644 index 00000000000..6fa0216ff3b --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_borders.scss @@ -0,0 +1,11 @@ +// Borders + +$euiBorderWidthThin: 1px !default; +$euiBorderWidthThick: 2px !default; + +$euiBorderColor: $euiColorLightShade !default; +$euiBorderRadius: $euiSizeS * .75 !default; +$euiBorderRadiusSmall: $euiSizeS * .5 !default; +$euiBorderThick: $euiBorderWidthThick solid $euiBorderColor !default; +$euiBorderThin: $euiBorderWidthThin solid $euiBorderColor !default; +$euiBorderEditable: $euiBorderWidthThick dotted $euiBorderColor !default; diff --git a/packages/eui-theme-common/src/global_styling/variables/_buttons.scss b/packages/eui-theme-common/src/global_styling/variables/_buttons.scss new file mode 100644 index 00000000000..4d4e8a5f0b1 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_buttons.scss @@ -0,0 +1,18 @@ +$euiButtonHeight: $euiSizeXXL !default; +$euiButtonHeightSmall: $euiSizeXL !default; +$euiButtonHeightXSmall: $euiSizeL !default; + +// Modifier naming and colors. +$euiButtonTypes: ( + primary: $euiColorPrimary, + accent: $euiColorAccent, + success: $euiColorSuccess, + warning: $euiColorWarning, + danger: $euiColorDanger, + ghost: $euiColorGhost, // Ghost is special, and does not care about theming. + text: $euiColorDarkShade, // Reserved for special use cases +) !default; + +// TODO: Remove this once elastic-charts no longer uses this variable +// @see https://github.com/elastic/elastic-charts/pull/2528 +$euiButtonColorDisabledText: $euiColorDisabledText; diff --git a/packages/eui-theme-common/src/global_styling/variables/_colors_vis.scss b/packages/eui-theme-common/src/global_styling/variables/_colors_vis.scss new file mode 100644 index 00000000000..cfffdf5e55d --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_colors_vis.scss @@ -0,0 +1,72 @@ +// Visualization colors +// stylelint-disable color-no-hex + +// Maps allow for easier JSON usage +// Use map_merge($euiColorVisColors, $yourMap) to change individual colors after importing ths file +// The `behindText` variant is a direct copy of the hex output by the JS euiPaletteColorBlindBehindText() function +$euiPaletteColorBlind: ( + euiColorVis0: ( + graphic: #54B399, + behindText: #6DCCB1, + ), + euiColorVis1: ( + graphic: #6092C0, + behindText: #79AAD9, + ), + euiColorVis2: ( + graphic: #D36086, + behindText: #EE789D, + ), + euiColorVis3: ( + graphic: #9170B8, + behindText: #A987D1, + ), + euiColorVis4: ( + graphic: #CA8EAE, + behindText: #E4A6C7, + ), + euiColorVis5: ( + graphic: #D6BF57, + behindText: #F1D86F, + ), + euiColorVis6: ( + graphic: #B9A888, + behindText: #D2C0A0, + ), + euiColorVis7: ( + graphic: #DA8B45, + behindText: #F5A35C, + ), + euiColorVis8: ( + graphic: #AA6556, + behindText: #C47C6C, + ), + euiColorVis9: ( + graphic: #E7664C, + behindText: #FF7E62, + ) +) !default; + +$euiPaletteColorBlindKeys: map-keys($euiPaletteColorBlind); + +$euiColorVis0: map-get(map-get($euiPaletteColorBlind, 'euiColorVis0'), 'graphic') !default; +$euiColorVis1: map-get(map-get($euiPaletteColorBlind, 'euiColorVis1'), 'graphic') !default; +$euiColorVis2: map-get(map-get($euiPaletteColorBlind, 'euiColorVis2'), 'graphic') !default; +$euiColorVis3: map-get(map-get($euiPaletteColorBlind, 'euiColorVis3'), 'graphic') !default; +$euiColorVis4: map-get(map-get($euiPaletteColorBlind, 'euiColorVis4'), 'graphic') !default; +$euiColorVis5: map-get(map-get($euiPaletteColorBlind, 'euiColorVis5'), 'graphic') !default; +$euiColorVis6: map-get(map-get($euiPaletteColorBlind, 'euiColorVis6'), 'graphic') !default; +$euiColorVis7: map-get(map-get($euiPaletteColorBlind, 'euiColorVis7'), 'graphic') !default; +$euiColorVis8: map-get(map-get($euiPaletteColorBlind, 'euiColorVis8'), 'graphic') !default; +$euiColorVis9: map-get(map-get($euiPaletteColorBlind, 'euiColorVis9'), 'graphic') !default; + +$euiColorVis0_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis0'), 'behindText') !default; +$euiColorVis1_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis1'), 'behindText') !default; +$euiColorVis2_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis2'), 'behindText') !default; +$euiColorVis3_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis3'), 'behindText') !default; +$euiColorVis4_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis4'), 'behindText') !default; +$euiColorVis5_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis5'), 'behindText') !default; +$euiColorVis6_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis6'), 'behindText') !default; +$euiColorVis7_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis7'), 'behindText') !default; +$euiColorVis8_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis8'), 'behindText') !default; +$euiColorVis9_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis9'), 'behindText') !default; diff --git a/packages/eui-theme-common/src/global_styling/variables/_colors_vis.ts b/packages/eui-theme-common/src/global_styling/variables/_colors_vis.ts new file mode 100644 index 00000000000..4459b04ff8c --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_colors_vis.ts @@ -0,0 +1,62 @@ +/* + * 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. + */ + +/** + * NOTE: These were quick conversions of their Sass counterparts. + * They have yet to be used/tested. + * TODO: Make the graphic version available from `euiPaletteColorBlind()` + */ + +// Maps allow for easier JSON usage +// Use map_merge(euiColorVisColors, $yourMap) to change individual colors after importing ths file +// The `behindText` variant is a direct copy of the hex output by the JS euiPaletteColorBlindBehindText() function +const euiPaletteColorBlind = { + euiColorVis0: { + graphic: '#54B399', + }, + euiColorVis1: { + graphic: '#6092C0', + }, + euiColorVis2: { + graphic: '#D36086', + }, + euiColorVis3: { + graphic: '#9170B8', + }, + euiColorVis4: { + graphic: '#CA8EAE', + }, + euiColorVis5: { + graphic: '#D6BF57', + }, + euiColorVis6: { + graphic: '#B9A888', + }, + euiColorVis7: { + graphic: '#DA8B45', + }, + euiColorVis8: { + graphic: '#AA6556', + }, + euiColorVis9: { + graphic: '#E7664C', + }, +}; + +export const colorVis = { + euiColorVis0: euiPaletteColorBlind.euiColorVis0.graphic, + euiColorVis1: euiPaletteColorBlind.euiColorVis1.graphic, + euiColorVis2: euiPaletteColorBlind.euiColorVis2.graphic, + euiColorVis3: euiPaletteColorBlind.euiColorVis3.graphic, + euiColorVis4: euiPaletteColorBlind.euiColorVis4.graphic, + euiColorVis5: euiPaletteColorBlind.euiColorVis5.graphic, + euiColorVis6: euiPaletteColorBlind.euiColorVis6.graphic, + euiColorVis7: euiPaletteColorBlind.euiColorVis7.graphic, + euiColorVis8: euiPaletteColorBlind.euiColorVis8.graphic, + euiColorVis9: euiPaletteColorBlind.euiColorVis9.graphic, +}; diff --git a/packages/eui-theme-common/src/global_styling/variables/_font_weight.scss b/packages/eui-theme-common/src/global_styling/variables/_font_weight.scss new file mode 100644 index 00000000000..f5dfd287835 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_font_weight.scss @@ -0,0 +1,10 @@ +// Separated out to its own file for easy import into docs + +// Font weights +$euiFontWeightLight: 300 !default; +$euiFontWeightRegular: 400 !default; +$euiFontWeightMedium: 500 !default; +$euiFontWeightSemiBold: 600 !default; +$euiFontWeightBold: 700 !default; +$euiCodeFontWeightRegular: 400 !default; +$euiCodeFontWeightBold: 700 !default; diff --git a/packages/eui-theme-common/src/global_styling/variables/_form.scss b/packages/eui-theme-common/src/global_styling/variables/_form.scss new file mode 100644 index 00000000000..41c5dfad04e --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_form.scss @@ -0,0 +1,21 @@ +// Sizing +$euiFormMaxWidth: $euiSizeXXL * 10 !default; +$euiFormControlHeight: $euiSizeXXL !default; +$euiFormControlCompressedHeight: $euiSizeXL !default; +$euiFormControlPadding: $euiSizeM !default; +$euiFormControlCompressedPadding: $euiSizeS !default; +$euiFormControlBorderRadius: $euiBorderRadius !default; +$euiFormControlCompressedBorderRadius: $euiBorderRadiusSmall !default; + +// Coloring +$euiFormBackgroundColor: tintOrShade($euiColorLightestShade, 60%, 40%) !default; +$euiFormBackgroundDisabledColor: darken($euiColorLightestShade, 2%) !default; +$euiFormBackgroundReadOnlyColor: $euiColorEmptyShade !default; +$euiFormBorderOpaqueColor: shadeOrTint(desaturate(adjust-hue($euiColorPrimary, 22), 22.95), 26%, 100%) !default; +$euiFormBorderColor: transparentize($euiFormBorderOpaqueColor, .9) !default; +$euiFormBorderDisabledColor: transparentize($euiFormBorderOpaqueColor, .9) !default; +$euiFormControlDisabledColor: $euiColorMediumShade !default; +$euiFormControlBoxShadow: 0 0 transparent !default; +$euiFormControlPlaceholderText: makeHighContrastColor($euiTextSubduedColor, $euiFormBackgroundColor) !default; +$euiFormInputGroupLabelBackground: tintOrShade($euiColorLightShade, 50%, 15%) !default; +$euiFormInputGroupBorder: none !default; \ No newline at end of file diff --git a/packages/eui-theme-common/src/global_styling/variables/_index.scss b/packages/eui-theme-common/src/global_styling/variables/_index.scss new file mode 100644 index 00000000000..993979a78a5 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_index.scss @@ -0,0 +1,23 @@ +// -------------------------------------------------------------------------------------- +// EUI global variables +// -------------------------------------------------------------------------------------- +// This module contains all global variables available within EUI. Every variable in this +// document should be prefixed with $eui. This lets us know where the variable is +// coming from when looking inside the individual component files. Any component local +// variables should be declared at the top of those documents prefixed with $componentName. + +// Global colors are established and importer per theme, before this manifest +// Import order is important. Size, vis colors, ...etc are used in other variables. +@import 'size'; +@import 'colors_vis'; +@import 'animations'; +@import 'font_weight'; +@import 'typography'; +@import 'borders'; +@import 'responsive'; +@import 'shadows'; +@import 'states'; +@import 'z_index'; + +@import 'buttons'; +@import 'form'; diff --git a/packages/eui-theme-common/src/global_styling/variables/_responsive.scss b/packages/eui-theme-common/src/global_styling/variables/_responsive.scss new file mode 100644 index 00000000000..de6e8ca5b83 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_responsive.scss @@ -0,0 +1,9 @@ +$euiBreakpoints: ( + 'xs': 0, + 's': 575px, + 'm': 768px, + 'l': 992px, + 'xl': 1200px +) !default; + +$euiBreakpointKeys: map-keys($euiBreakpoints); diff --git a/packages/eui-theme-common/src/global_styling/variables/_shadows.scss b/packages/eui-theme-common/src/global_styling/variables/_shadows.scss new file mode 100644 index 00000000000..05e445f27a1 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_shadows.scss @@ -0,0 +1,2 @@ +// Shadows +$euiShadowColor: $euiColorInk !default; diff --git a/packages/eui-theme-common/src/global_styling/variables/_size.scss b/packages/eui-theme-common/src/global_styling/variables/_size.scss new file mode 100644 index 00000000000..f07645832d1 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_size.scss @@ -0,0 +1,15 @@ +$euiSize: 16px !default; + +$euiSizeXS: $euiSize * .25 !default; +$euiSizeS: $euiSize * .5 !default; +$euiSizeM: $euiSize * .75 !default; +$euiSizeL: $euiSize * 1.5 !default; +$euiSizeXL: $euiSize * 2 !default; +$euiSizeXXL: $euiSize * 2.5 !default; + +$euiButtonMinWidth: $euiSize * 7 !default; + +$euiScrollBar: $euiSize !default; +// Corner sizes are used as an inset border and therefore a smaller corner size means a larger thumb +$euiScrollBarCorner: $euiSizeXS !default; +$euiScrollBarCornerThin: $euiSizeS * .75 !default; diff --git a/packages/eui-theme-common/src/global_styling/variables/_states.scss b/packages/eui-theme-common/src/global_styling/variables/_states.scss new file mode 100644 index 00000000000..fba4cc59caa --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_states.scss @@ -0,0 +1,14 @@ +// Colors +$euiFocusRingColor: rgba($euiColorPrimary, .3) !default; +$euiFocusRingAnimStartColor: rgba($euiColorPrimary, 0) !default; +$euiFocusRingAnimStartSize: 6px !default; +$euiFocusRingAnimStartSizeLarge: 10px !default; + +// Sizing +$euiFocusRingSizeLarge: $euiSizeXS !default; +$euiFocusRingSize: $euiFocusRingSizeLarge * .75 !default; + +// Transparency +$euiFocusTransparency: lightOrDarkTheme(.1, .2) !default; +$euiFocusTransparencyPercent: lightOrDarkTheme(90%, 80%) !default; +$euiFocusBackgroundColor: tintOrShade($euiColorPrimary, $euiFocusTransparencyPercent, $euiFocusTransparencyPercent) !default; diff --git a/packages/eui-theme-common/src/global_styling/variables/_typography.scss b/packages/eui-theme-common/src/global_styling/variables/_typography.scss new file mode 100644 index 00000000000..1ca62f3248c --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_typography.scss @@ -0,0 +1,75 @@ +// Families +$euiFontFamily: 'Inter', BlinkMacSystemFont, Helvetica, Arial, sans-serif !default; +$euiCodeFontFamily: 'Roboto Mono', Menlo, Courier, monospace !default; + +// Careful using ligatures. Code editors like ACE will often error because of width calculations +$euiFontFeatureSettings: 'calt' 1, 'kern' 1, 'liga' 1 !default; + +// Font sizes -- scale is loosely based on Major Third (1.250) +$euiTextScale: 2.25, 1.75, 1.25, 1.125, 1, .875, .75 !default; + +$euiFontSize: $euiSize !default; // 5th position in scale +$euiFontSizeXS: $euiFontSize * nth($euiTextScale, 7) !default; // 12px +$euiFontSizeS: $euiFontSize * nth($euiTextScale, 6) !default; // 14px +$euiFontSizeM: $euiFontSize * nth($euiTextScale, 4) !default; // 18px +$euiFontSizeL: $euiFontSize * nth($euiTextScale, 3) !default; // 20px +$euiFontSizeXL: $euiFontSize * nth($euiTextScale, 2) !default; // 28px +$euiFontSizeXXL: $euiFontSize * nth($euiTextScale, 1) !default; // 36px + +// Line height +$euiLineHeight: 1.5 !default; +$euiBodyLineHeight: 1 !default; + +// Normally functions are imported before variables in `_index.scss` files +// But because they need to consume some typography variables they need to live here +@function convertToRem($size) { + @return #{$size / $euiFontSize}rem; +} + +// Our base gridline is at 1/2 the font-size, ensure line-heights stay on that gridline. +// EX: A proper line-height for text is 1.5 times the font-size. +// If our base font size (euiFontSize) is 16, our baseline is 8 (16*1.5 / 3). To ensure the +// text stays on the baseline, we pass a multiplier to calculate a line-height in rems. +@function lineHeightFromBaseline($multiplier: 3) { + @return convertToRem(($euiFontSize / 2) * $multiplier); +} + +// Titles map +// Lists all the properties per EuiTitle size that then gets looped through to create the selectors. +// The map allows for tokenization and easier customization per theme, otherwise you'd have to override the selectors themselves +$euiTitles: ( + 'xxxs': ( + 'font-size': $euiFontSizeXS, + 'line-height': lineHeightFromBaseline(3), + 'font-weight': $euiFontWeightBold, + ), + 'xxs': ( + 'font-size': $euiFontSizeS, + 'line-height': lineHeightFromBaseline(3), + 'font-weight': $euiFontWeightBold, + ), + 'xs': ( + 'font-size': $euiFontSize, + 'line-height': lineHeightFromBaseline(3), + 'font-weight': $euiFontWeightSemiBold, + 'letter-spacing': -.02em, + ), + 's': ( + 'font-size': $euiFontSizeL, + 'line-height': lineHeightFromBaseline(4), + 'font-weight': $euiFontWeightMedium, + 'letter-spacing': -.025em, + ), + 'm': ( + 'font-size': $euiFontSizeXL, + 'line-height': lineHeightFromBaseline(5), + 'font-weight': $euiFontWeightLight, + 'letter-spacing': -.04em, + ), + 'l': ( + 'font-size': $euiFontSizeXXL, + 'line-height': lineHeightFromBaseline(6), + 'font-weight': $euiFontWeightLight, + 'letter-spacing': -.03em, + ), +) !default; diff --git a/packages/eui-theme-common/src/global_styling/variables/_z_index.scss b/packages/eui-theme-common/src/global_styling/variables/_z_index.scss new file mode 100644 index 00000000000..2448a34c61a --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/_z_index.scss @@ -0,0 +1,34 @@ +// Z-Index + +// Remember that z-index is relative to parent and based on the stacking context. +// z-indexes only compete against other z-indexes when they exist as children of +// that shared parent. + +// That means a popover with a settings of 2, will still show above a modal +// with a setting of 100, if it is within that modal and not besides it. + +// Generally that means it's a good idea to consider things added to this file +// as competitive only as siblings. + +// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context + +$euiZLevel0: 0; +$euiZLevel1: 1000; +$euiZLevel2: 2000; +$euiZLevel3: 3000; +$euiZLevel4: 4000; +$euiZLevel5: 5000; +$euiZLevel6: 6000; +$euiZLevel7: 7000; +$euiZLevel8: 8000; +$euiZLevel9: 9000; + +$euiZToastList: $euiZLevel9; +$euiZModal: $euiZLevel8; +$euiZMask: $euiZLevel6; +$euiZNavigation: $euiZLevel6; +$euiZContentMenu: $euiZLevel2; +$euiZHeader: $euiZLevel1; +$euiZFlyout: $euiZHeader; +$euiZMaskBelowHeader: $euiZHeader; +$euiZContent: $euiZLevel0; diff --git a/packages/eui-theme-common/src/global_styling/variables/animations.ts b/packages/eui-theme-common/src/global_styling/variables/animations.ts new file mode 100644 index 00000000000..46bce009c92 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/animations.ts @@ -0,0 +1,66 @@ +/* + * 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 { CSSProperties } from 'react'; + +/** + * A constant storing the `prefers-reduced-motion` media query + * so that when it is turned off, animations are not run. + */ +export const euiCanAnimate = + '@media screen and (prefers-reduced-motion: no-preference)'; + +/** + * A constant storing the `prefers-reduced-motion` media query that will + * only apply the content if the setting is off (reduce). + */ +export const euiCantAnimate = + '@media screen and (prefers-reduced-motion: reduce)'; + +/** + * Speeds / Durations / Delays + */ + +export const EuiThemeAnimationSpeeds = [ + 'extraFast', + 'fast', + 'normal', + 'slow', + 'extraSlow', +] as const; + +export type _EuiThemeAnimationSpeed = (typeof EuiThemeAnimationSpeeds)[number]; + +export type _EuiThemeAnimationSpeeds = { + /** - Default value: 90ms */ + extraFast: CSSProperties['animationDuration']; + /** - Default value: 150ms */ + fast: CSSProperties['animationDuration']; + /** - Default value: 250ms */ + normal: CSSProperties['animationDuration']; + /** - Default value: 350ms */ + slow: CSSProperties['animationDuration']; + /** - Default value: 500ms */ + extraSlow: CSSProperties['animationDuration']; +}; + +/** + * Easings / Timing functions + */ + +export const EuiThemeAnimationEasings = ['bounce', 'resistance'] as const; + +export type _EuiThemeAnimationEasing = + (typeof EuiThemeAnimationEasings)[number]; + +export type _EuiThemeAnimationEasings = Record< + _EuiThemeAnimationEasing, + CSSProperties['animationTimingFunction'] +>; + +export type _EuiThemeAnimation = _EuiThemeAnimationEasings & + _EuiThemeAnimationSpeeds; diff --git a/packages/eui-theme-common/src/global_styling/variables/borders.ts b/packages/eui-theme-common/src/global_styling/variables/borders.ts new file mode 100644 index 00000000000..3673010aba2 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/borders.ts @@ -0,0 +1,74 @@ +/* + * 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 { CSSProperties } from 'react'; +import { ColorModeSwitch } from '../types'; + +export interface _EuiThemeBorderWidthValues { + /** + * Thinnest width for border + * - Default value: 1px + */ + thin: CSSProperties['borderWidth']; + /** + * Thickest width for border + * - Default value: 2px + */ + thick: CSSProperties['borderWidth']; +} + +export interface _EuiThemeBorderRadiusValues { + /** + * Primary corner radius size + * - Default value: 6px + */ + medium: CSSProperties['borderRadius']; + /** + * Small corner radius size + * - Default value: 4px + */ + small: CSSProperties['borderRadius']; +} + +export interface _EuiThemeBorderColorValues { + /** + * Color for all borders; Default is `colors.lightShade` + */ + color: ColorModeSwitch; +} + +export interface _EuiThemeBorderValues extends _EuiThemeBorderColorValues { + /** + * Varied thicknesses for borders + */ + width: _EuiThemeBorderWidthValues; + /** + * Varied border radii + */ + radius: _EuiThemeBorderRadiusValues; +} + +export interface _EuiThemeBorderTypes { + /** + * Full `border` property string computed using `border.width.thin` and `border.color` + * - Default value: 1px solid [colors.lightShade] + */ + thin: CSSProperties['border']; + /** + * Full `border` property string computed using `border.width.thick` and `border.color` + * - Default value: 2px solid [colors.lightShade] + */ + thick: CSSProperties['border']; + /** + * Full editable style `border` property string computed using `border.width.thick` and `border.color` + * - Default value: 2px dotted [colors.lightShade] + */ + editable: CSSProperties['border']; +} + +export type _EuiThemeBorder = _EuiThemeBorderValues & _EuiThemeBorderTypes; diff --git a/packages/eui-theme-common/src/global_styling/variables/breakpoint.ts b/packages/eui-theme-common/src/global_styling/variables/breakpoint.ts new file mode 100644 index 00000000000..68aef1fba38 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/breakpoint.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export const EuiThemeBreakpoints = ['xs', 's', 'm', 'l', 'xl'] as const; + +// This type cannot be a string enum / must be a generic string +// in case consumers add custom breakpoint sizes, such as xxl or xxs +export type _EuiThemeBreakpoint = string; + +// Explicitly list out each key so we can document default values +// via JSDoc (which is available to devs in IDE via intellisense) +export type _EuiThemeBreakpoints = Record<_EuiThemeBreakpoint, number> & { + /** - Default value: 0 */ + xs: number; + /** - Default value: 575 */ + s: number; + /** - Default value: 768 */ + m: number; + /** - Default value: 992 */ + l: number; + /** - Default value: 1200 */ + xl: number; +}; diff --git a/packages/eui-theme-common/src/global_styling/variables/colors.ts b/packages/eui-theme-common/src/global_styling/variables/colors.ts new file mode 100644 index 00000000000..8604ecafba4 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/colors.ts @@ -0,0 +1,156 @@ +/* + * 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 { ColorModeSwitch, StrictColorModeSwitch } from '../types'; + +/** + * Top 5 colors + */ +export type _EuiThemeBrandColors = { + /** + * Main brand color and used for most **call to actions** like buttons and links. + */ + primary: ColorModeSwitch; + /** + * Pulls attention to key indicators like **notifications** or number of selections. + */ + accent: ColorModeSwitch; + /** + * Used for **positive** messages/graphics and additive actions. + */ + success: ColorModeSwitch; + /** + * Used for **warnings** and actions that have a potential to be destructive. + */ + warning: ColorModeSwitch; + /** + * Used for **negative** messages/graphics like errors and destructive actions. + */ + danger: ColorModeSwitch; +}; + +/** + * Every brand color must have a contrast computed text equivelant + */ +export type _EuiThemeBrandTextColors = { + /** + * Typically computed against `colors.primary` + */ + primaryText: ColorModeSwitch; + /** + * Typically computed against `colors.accent` + */ + accentText: ColorModeSwitch; + /** + * Typically computed against `colors.success` + */ + successText: ColorModeSwitch; + /** + * Typically computed against `colors.warning` + */ + warningText: ColorModeSwitch; + /** + * Typically computed against `colors.danger` + */ + dangerText: ColorModeSwitch; +}; + +export type _EuiThemeShadeColors = { + /** + * Used as the background color of primary **page content and panels** including modals and flyouts. + */ + emptyShade: ColorModeSwitch; + /** + * Used to lightly shade areas that contain **secondary content** or contain panel-like components. + */ + lightestShade: ColorModeSwitch; + /** + * Used for most **borders** and dividers (horizontal rules). + */ + lightShade: ColorModeSwitch; + /** + * The middle gray for all themes; this is the base for `colors.subdued`. + */ + mediumShade: ColorModeSwitch; + /** + * Slightly subtle graphic color + */ + darkShade: ColorModeSwitch; + /** + * Used as the **text** color and the background color for **inverted components** like tooltips and the control bar. + */ + darkestShade: ColorModeSwitch; + /** + * The opposite of `emptyShade` + */ + fullShade: ColorModeSwitch; +}; + +export type _EuiThemeTextColors = { + /** + * Computed against `colors.darkestShade` + */ + text: ColorModeSwitch; + /** + * Computed against `colors.text` + */ + title: ColorModeSwitch; + /** + * Computed against `colors.mediumShade` + */ + subduedText: ColorModeSwitch; + /** + * Computed against `colors.primaryText` + */ + link: ColorModeSwitch; +}; + +export type _EuiThemeSpecialColors = { + /** + * The background color for the **whole window (body)** and is a computed value of `colors.lightestShade`. + * Provides denominator (background) value for **contrast calculations**. + */ + body: ColorModeSwitch; + /** + * Used to **highlight text** when matching against search strings + */ + highlight: ColorModeSwitch; + /** + * Computed against `colors.darkestShade` + */ + disabled: ColorModeSwitch; + /** + * Computed against `colors.disabled` + */ + disabledText: ColorModeSwitch; + /** + * The base color for shadows that gets `transparentized` + * at a value based on the `colorMode` and then layered. + */ + shadow: ColorModeSwitch; +}; + +export type _EuiThemeConstantColors = { + /** + * Purest **white** + */ + ghost: string; + /** + * Purest **black** + */ + ink: string; +}; + +export type _EuiThemeColorsMode = _EuiThemeBrandColors & + _EuiThemeBrandTextColors & + _EuiThemeShadeColors & + _EuiThemeSpecialColors & + _EuiThemeTextColors; + +export type _EuiThemeColors = StrictColorModeSwitch<_EuiThemeColorsMode> & + _EuiThemeConstantColors; diff --git a/packages/eui-theme-common/src/global_styling/variables/index.ts b/packages/eui-theme-common/src/global_styling/variables/index.ts new file mode 100644 index 00000000000..48eacef5cbb --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +export * from './animations'; +export * from './borders'; +export * from './breakpoint'; +export * from './colors'; +export * from './_colors_vis'; +export * from './levels'; +export * from './size'; +export * from './shadow'; +export * from './states'; +export * from './typography'; diff --git a/packages/eui-theme-common/src/global_styling/variables/levels.ts b/packages/eui-theme-common/src/global_styling/variables/levels.ts new file mode 100644 index 00000000000..7d38c71791b --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/levels.ts @@ -0,0 +1,60 @@ +/* + * 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 { CSSProperties } from 'react'; + +/** + * Z-Index + * + * Remember that z-index is relative to parent and based on the stacking context. + * z-indexes only compete against other z-indexes when they exist as children of + * that shared parent. + * + * That means a popover with a settings of 2, will still show above a modal + * with a setting of 100, if it is within that modal and not besides it. + * + * Generally that means it's a good idea to consider things added to this file + * as competitive only as siblings. + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context + */ + +export const EuiThemeLevels = [ + 'toast', + 'modal', + 'mask', + 'navigation', + 'menu', + 'header', + 'flyout', + 'maskBelowHeader', + 'content', +] as const; + +export type _EuiThemeLevel = (typeof EuiThemeLevels)[number]; + +export type _EuiThemeLevels = { + /** - Default value: 9000 */ + toast: NonNullable; + /** - Default value: 8000 */ + modal: NonNullable; + /** - Default value: 6000 */ + mask: NonNullable; + /** - Default value: 6000 */ + navigation: NonNullable; + /** - Default value: 2000 */ + menu: NonNullable; + /** - Default value: 1000 */ + header: NonNullable; + /** - Default value: 1000 */ + flyout: NonNullable; + /** - Default value: 1000 */ + maskBelowHeader: NonNullable; + /** - Default value: 0 */ + content: NonNullable; +}; diff --git a/packages/eui-theme-common/src/global_styling/variables/shadow.ts b/packages/eui-theme-common/src/global_styling/variables/shadow.ts new file mode 100644 index 00000000000..7761fbdb9a0 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/shadow.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export const EuiThemeShadowSizes = ['xs', 's', 'm', 'l', 'xl'] as const; + +export type _EuiThemeShadowSize = (typeof EuiThemeShadowSizes)[number]; + +/** + * Shadow t-shirt sizes descriptions + */ +export const _EuiShadowSizesDescriptions: Record<_EuiThemeShadowSize, string> = + { + xs: 'Very subtle shadow used on small components.', + s: 'Adds subtle depth, usually used in conjunction with a border.', + m: 'Used on small sized portalled content like popovers.', + l: 'Primary shadow used in most cases to add visible depth.', + xl: 'Very large shadows used for large portalled style containers like modals and flyouts.', + }; + +export interface _EuiThemeShadowCustomColor { + color?: string; + property?: 'box-shadow' | 'filter'; +} diff --git a/packages/eui-theme-common/src/global_styling/variables/size.ts b/packages/eui-theme-common/src/global_styling/variables/size.ts new file mode 100644 index 00000000000..98428346b61 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/size.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +export type _EuiThemeBase = number; + +export const EuiThemeSizes = [ + 'xxs', + 'xs', + 's', + 'm', + 'base', + 'l', + 'xl', + 'xxl', + 'xxxl', + 'xxxxl', +] as const; + +export type _EuiThemeSize = (typeof EuiThemeSizes)[number]; + +export type _EuiThemeSizes = { + /** - Default value: 2px */ + xxs: string; + /** - Default value: 4px */ + xs: string; + /** - Default value: 8px */ + s: string; + /** - Default value: 12px */ + m: string; + /** - Default value: 16px */ + base: string; + /** - Default value: 24px */ + l: string; + /** - Default value: 32px */ + xl: string; + /** - Default value: 40px */ + xxl: string; + /** - Default value: 48px */ + xxxl: string; + /** - Default value: 64px */ + xxxxl: string; +}; diff --git a/packages/eui-theme-common/src/global_styling/variables/states.ts b/packages/eui-theme-common/src/global_styling/variables/states.ts new file mode 100644 index 00000000000..2d0283ac949 --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/states.ts @@ -0,0 +1,33 @@ +/* + * 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 { CSSProperties } from 'react'; +import { ColorModeSwitch } from '../types'; + +export interface _EuiThemeFocus { + /** + * Default color of the focus ring, some components may override this property + * - Default value: currentColor + */ + color: ColorModeSwitch; + /** + * Thickness of the outline + * - Default value: 2px + */ + width: CSSProperties['borderWidth']; + /** + * Used to transparentize the focus background color + * - Default value: { LIGHT: 0.1, DARK: 0.2 } + */ + transparency: ColorModeSwitch; + /** + * Default focus background color. Not all components set a background color on focus + * - Default value: `colors.primary` computed with `focus.transparency` + */ + backgroundColor: ColorModeSwitch; +} diff --git a/packages/eui-theme-common/src/global_styling/variables/typography.ts b/packages/eui-theme-common/src/global_styling/variables/typography.ts new file mode 100644 index 00000000000..80ebbc8b1cb --- /dev/null +++ b/packages/eui-theme-common/src/global_styling/variables/typography.ts @@ -0,0 +1,146 @@ +/* + * 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 { CSSProperties } from 'react'; + +/** + * Font units of measure + */ + +export const EuiThemeFontUnits = ['rem', 'px', 'em'] as const; + +export type _EuiThemeFontUnit = (typeof EuiThemeFontUnits)[number]; + +/* + * Font scale + */ + +export const EuiThemeFontScales = [ + 'xxxs', + 'xxs', + 'xs', + 's', + 'm', + 'l', + 'xl', + 'xxl', +] as const; + +export type _EuiThemeFontScale = (typeof EuiThemeFontScales)[number]; + +export type _EuiThemeFontScales = Record<_EuiThemeFontScale, number>; + +/* + * Font base settings + */ + +export type _EuiThemeFontBase = { + /** + * The whole font family stack for all parts of the UI. + * We encourage only customizing the first font in the stack. + */ + family: string; + /** + * The font family used for monospace UI elements like EuiCode + */ + familyCode?: string; + /** + * The font family used for serif UI elements like blockquotes within EuiText + */ + familySerif?: string; + /** + * Controls advanced features OpenType fonts. + * 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` + */ + baseline: number; + /** + * Establishes the ideal line-height percentage, but it is the `baseline` integer that establishes the final pixel/rem value + */ + lineHeightMultiplier: number; +}; + +/* + * Font weights + */ + +export const EuiThemeFontWeights = [ + 'light', + 'regular', + 'medium', + 'semiBold', + 'bold', +] as const; + +export type _EuiThemeFontWeight = (typeof EuiThemeFontWeights)[number]; + +export type _EuiThemeFontWeights = { + /** - Default value: 300 */ + light: CSSProperties['fontWeight']; + /** - Default value: 400 */ + regular: CSSProperties['fontWeight']; + /** - Default value: 500 */ + medium: CSSProperties['fontWeight']; + /** - Default value: 600 */ + semiBold: CSSProperties['fontWeight']; + /** - Default value: 700 */ + bold: CSSProperties['fontWeight']; +}; + +/** + * Body / Base styles + */ + +export interface _EuiThemeBody { + /** + * A sizing key from one of the font scales to set as the base body font-size + */ + scale: _EuiThemeFontScale; + /** + * A font weight key for setting the base body weight + */ + weight: keyof _EuiThemeFontWeights; +} + +/** + * Title styles + */ + +export interface _EuiThemeTitle { + /** + * A font weight key for setting the base weight for titles and headings + */ + weight: keyof _EuiThemeFontWeights; +} + +/* + * Font + */ + +export type _EuiThemeFont = _EuiThemeFontBase & { + scale: _EuiThemeFontScales; + /** + * @see {@link https://eui.elastic.co/#/theming/typography/values%23font-weight | Reference} for more information + */ + weight: _EuiThemeFontWeights; + body: _EuiThemeBody; + title: _EuiThemeTitle; +}; diff --git a/packages/eui-theme-common/src/index.ts b/packages/eui-theme-common/src/index.ts new file mode 100644 index 00000000000..05e235c669b --- /dev/null +++ b/packages/eui-theme-common/src/index.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +export * from './global_styling'; + +export * from './types'; +export * from './utils'; diff --git a/packages/eui-theme-common/src/types.ts b/packages/eui-theme-common/src/types.ts new file mode 100644 index 00000000000..68c72d586df --- /dev/null +++ b/packages/eui-theme-common/src/types.ts @@ -0,0 +1,56 @@ +/* + * 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. + */ + +/* TODO: duplicated types from /eui/src/components/common - extract to shared location */ + +/** + * Like `keyof typeof`, but for getting values instead of keys + * ValueOf + * Results in `'value1' | 'value2'` + */ +export type ValueOf = T[keyof T]; + +/** + * Replaces all properties on any type as optional, includes nested types + * + * @example + * ```ts + * interface Person { + * name: string; + * age?: number; + * spouse: Person; + * children: Person[]; + * } + * type PartialPerson = RecursivePartial; + * // results in + * interface PartialPerson { + * name?: string; + * age?: number; + * spouse?: RecursivePartial; + * children?: RecursivePartial[] + * } + * ``` + */ +export type RecursivePartial = { + [P in keyof T]?: T[P] extends NonAny[] // checks for nested any[] + ? T[P] + : T[P] extends readonly NonAny[] // checks for nested ReadonlyArray + ? T[P] + : T[P] extends Array + ? Array> + : T[P] extends ReadonlyArray + ? ReadonlyArray> + : T[P] extends Set // checks for Sets + ? Set> + : T[P] extends Map // checks for Maps + ? Map> + : T[P] extends NonAny // checks for primitive values + ? T[P] + : RecursivePartial; // recurse for all non-array and non-primitive values +}; +type NonAny = number | boolean | string | symbol | null; diff --git a/packages/eui-theme-common/src/utils.test.ts b/packages/eui-theme-common/src/utils.test.ts new file mode 100644 index 00000000000..c654e4d3c22 --- /dev/null +++ b/packages/eui-theme-common/src/utils.test.ts @@ -0,0 +1,279 @@ +/* + * 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 { + isInverseColorMode, + getColorMode, + getOn, + setOn, + computed, + Computed, + getComputed, + buildTheme, + mergeDeep, +} from './utils'; + +describe('isInverseColorMode', () => { + it("true only if 'inverse'", () => { + expect(isInverseColorMode('LIGHT')).toBe(false); + expect(isInverseColorMode('DARK')).toBe(false); + expect(isInverseColorMode('custom')).toBe(false); + expect(isInverseColorMode()).toBe(false); + expect(isInverseColorMode('INVERSE')).toBe(true); + }); +}); + +describe('getColorMode', () => { + it("defaults to 'LIGHT'", () => { + expect(getColorMode()).toEqual('LIGHT'); + }); + it('uses `parentMode` as fallback', () => { + expect(getColorMode(undefined, 'DARK')).toEqual('DARK'); + }); + it("understands 'INVERSE'", () => { + expect(getColorMode('INVERSE', 'DARK')).toEqual('LIGHT'); + expect(getColorMode('INVERSE', 'LIGHT')).toEqual('DARK'); + expect(getColorMode('INVERSE')).toEqual('LIGHT'); + }); +}); + +describe('getOn', () => { + const obj = { + parent: { + child: 'childVal', + }, + other: { + thing: { + string: 'stringVal', + nested: ['array'], + number: 0, + func: () => {}, + }, + }, + colors: { + LIGHT: { primary: '#000' }, + DARK: { primary: '#FFF' }, + }, + }; + it('gets values at the given path', () => { + expect(getOn(obj, 'parent')).toEqual({ + child: 'childVal', + }); + expect(getOn(obj, 'parent.child')).toEqual('childVal'); + expect(getOn(obj, 'other.thing.string')).toEqual('stringVal'); + }); + it('gets values of various kinds', () => { + expect(getOn(obj, 'other.thing.nested')).toEqual(['array']); + expect(getOn(obj, 'other.thing.number')).toEqual(0); + expect(getOn(obj, 'other.thing.func')).toBeInstanceOf(Function); + }); + it('can shortcut color modes', () => { + expect(getOn(obj, 'colors.primary', 'LIGHT')).toEqual('#000'); + expect(getOn(obj, 'colors.primary', 'DARK')).toEqual('#FFF'); + }); + it('will not error', () => { + expect(getOn(obj, 'nope')).toBe(undefined); + expect(getOn(obj, 'other.nope')).toBe(undefined); + expect(getOn(obj, 'other.thing.nope')).toBe(undefined); + }); +}); + +describe('setOn', () => { + let obj: {}; + beforeEach(() => { + obj = { + existing: { + nested: { + val: 'value', + }, + }, + }; + }); + it('sets values at the given path', () => { + setOn(obj, 'existing.new', 'value'); + expect(obj).toEqual({ + existing: { nested: { val: 'value' }, new: 'value' }, + }); + setOn(obj, 'existing.nested.new', 'value'); + expect(obj).toEqual({ + existing: { nested: { val: 'value', new: 'value' }, new: 'value' }, + }); + }); + it('deep arbitrary creation', () => { + setOn(obj, 'trail.blazing.happening.now', 'wow'); + expect(obj).toEqual({ + existing: { nested: { val: 'value' } }, + trail: { blazing: { happening: { now: 'wow' } } }, + }); + }); + it('overrides existing path value', () => { + setOn(obj, 'existing.nested', 'diff'); + expect(obj).toEqual({ + existing: { + nested: 'diff', + }, + }); + }); +}); + +describe('computed', () => { + it('should transform to Computed with dependencies array', () => { + const output = computed(([path]) => path, ['path.to']); + expect(output).toBeInstanceOf(Computed); + expect(output.computer).toBeInstanceOf(Function); + expect(output.dependencies).toEqual(['path.to']); + }); + it('should transform to Computed with single dependency', () => { + const output = computed((path) => path, 'path.to'); + expect(output).toBeInstanceOf(Computed); + expect(output.computer).toBeInstanceOf(Function); + expect(output.dependencies).toEqual('path.to'); + }); + it('should transform to Computed without dependencies array', () => { + const output = computed((path) => path); + expect(output).toBeInstanceOf(Computed); + }); +}); + +const theme = buildTheme( + { + colors: { + LIGHT: { + primary: '#000', + secondary: computed(([primary]) => `${primary}000`, ['colors.primary']), + }, + DARK: { + primary: '#FFF', + secondary: computed((theme) => `${theme.colors.primary}FFF`), + }, + }, + sizes: { + small: 8, + }, + }, + 'minimal' +); +describe('getComputed', () => { + it('computes all values and returns only the current color mode', () => { + // @ts-expect-error intentionally not using a full EUI theme definition + expect(getComputed(theme, {}, 'LIGHT')).toEqual({ + colors: { primary: '#000', secondary: '#000000' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + // @ts-expect-error intentionally not using a full EUI theme definition + expect(getComputed(theme, {}, 'DARK')).toEqual({ + colors: { primary: '#FFF', secondary: '#FFFFFF' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + }); + it('respects simple overrides', () => { + expect( + // @ts-expect-error intentionally not using a full EUI theme definition + getComputed(theme, buildTheme({ sizes: { small: 4 } }, ''), 'LIGHT') + ).toEqual({ + colors: { primary: '#000', secondary: '#000000' }, + sizes: { small: 4 }, + themeName: 'minimal', + }); + }); + it('respects overrides in computation', () => { + expect( + getComputed( + // @ts-expect-error intentionally not using a full EUI theme definition + theme, + buildTheme({ colors: { LIGHT: { primary: '#CCC' } } }, ''), + 'LIGHT' + ) + ).toEqual({ + colors: { primary: '#CCC', secondary: '#CCC000' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + }); + it('respects property extensions', () => { + expect( + getComputed( + // @ts-expect-error intentionally not using a full EUI theme definition + theme, + buildTheme({ colors: { LIGHT: { tertiary: '#333' } } }, ''), + 'LIGHT' + ) + ).toEqual({ + colors: { primary: '#000', secondary: '#000000', tertiary: '#333' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + }); + it('respects section extensions', () => { + expect( + getComputed( + // @ts-expect-error intentionally not using a full EUI theme definition + theme, + buildTheme({ custom: { myProp: '#333' } }, ''), + 'LIGHT' + ) + ).toEqual({ + colors: { primary: '#000', secondary: '#000000' }, + sizes: { small: 8 }, + custom: { myProp: '#333' }, + themeName: 'minimal', + }); + }); + it('respects extensions in computation', () => { + expect( + getComputed( + // @ts-expect-error intentionally not using a full EUI theme definition + theme, + buildTheme( + { + colors: { + LIGHT: { + tertiary: computed( + ([primary]) => `${primary}333`, + ['colors.primary'] + ), + }, + }, + }, + '' + ), + 'LIGHT' + ) + ).toEqual({ + colors: { primary: '#000', secondary: '#000000', tertiary: '#000333' }, + sizes: { small: 8 }, + themeName: 'minimal', + }); + }); +}); + +describe('buildTheme', () => { + it('builds an EUI theme system', () => { + // TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property 'length' which is either non-existant or configurable in the proxy target + // expect(theme).toEqual(Proxy); // get() trap returns theme.model + // expect(theme.root).toEqual(Proxy); + expect(theme.key).toEqual('minimal'); + }); +}); + +describe('mergeDeep', () => { + it('merge simple objects, second into first', () => { + expect(mergeDeep({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 }); + expect(mergeDeep({ a: 1 }, { a: 2 })).toEqual({ a: 2 }); + }); + it('merge complex objects, second into first', () => { + expect( + mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { d: 4 } } }) + ).toEqual({ a: 1, b: { c: { d: 4 } } }); + expect( + mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { e: 5 } } }) + ).toEqual({ a: 1, b: { c: { d: 3, e: 5 } } }); + }); +}); diff --git a/packages/eui-theme-common/src/utils.ts b/packages/eui-theme-common/src/utils.ts new file mode 100644 index 00000000000..caa529ebd48 --- /dev/null +++ b/packages/eui-theme-common/src/utils.ts @@ -0,0 +1,392 @@ +/* + * 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 { + EuiThemeColorMode, + EuiThemeColorModeInverse, + EuiThemeColorModeStandard, + EuiThemeModifications, + EuiThemeSystem, + EuiThemeShape, + EuiThemeComputed, + COLOR_MODES_STANDARD, + COLOR_MODES_INVERSE, +} from './global_styling'; + +export const DEFAULT_COLOR_MODE = COLOR_MODES_STANDARD.light; + +/** + * Returns whether the parameter is an object + * @param {any} obj - Anything + */ +const isObject = (obj: any) => obj && typeof obj === 'object'; + +/** + * Returns whether the provided color mode is `inverse` + * @param {string} colorMode - `light`, `dark`, or `inverse` + */ +export const isInverseColorMode = ( + colorMode?: string +): colorMode is EuiThemeColorModeInverse => { + return colorMode === COLOR_MODES_INVERSE; +}; + +/** + * Returns the color mode configured in the current EuiThemeProvider. + * Returns the parent color mode if none is explicity set. + * @param {string} colorMode - `light`, `dark`, or `inverse` + * @param {string} parentColorMode - `LIGHT` or `DARK`; used as the fallback + */ +export const getColorMode = ( + colorMode?: EuiThemeColorMode, + parentColorMode?: EuiThemeColorModeStandard +): EuiThemeColorModeStandard => { + if (colorMode == null) { + return parentColorMode || DEFAULT_COLOR_MODE; + } + const mode = colorMode.toUpperCase() as + | EuiThemeColorModeInverse + | EuiThemeColorModeStandard; + if (isInverseColorMode(mode)) { + return parentColorMode === COLOR_MODES_STANDARD.dark || + parentColorMode === undefined + ? COLOR_MODES_STANDARD.light + : COLOR_MODES_STANDARD.dark; + } else { + return mode; + } +}; + +/** + * Returns a value at a given path on an object. + * If `colorMode` is provided, will scope the value to the appropriate color mode key (LIGHT\DARK) + * @param {object} model - Object + * @param {string} _path - Dot-notated string to a path on the object + * @param {string} colorMode - `light` or `dark` + */ +export const getOn = ( + model: { [key: string]: any }, + _path: string, + colorMode?: EuiThemeColorModeStandard +) => { + const path = _path.split('.'); + let node = model; + while (path.length) { + const segment = path.shift()!; + + if (node.hasOwnProperty(segment) === false) { + if ( + colorMode && + node.hasOwnProperty(colorMode) === true && + node[colorMode].hasOwnProperty(segment) === true + ) { + if (node[colorMode][segment] instanceof Computed) { + node = node[colorMode][segment].getValue(null, {}, node, colorMode); + } else { + node = node[colorMode][segment]; + } + } else { + return undefined; + } + } else { + if (node[segment] instanceof Computed) { + node = node[segment].getValue(null, {}, node, colorMode); + } else { + node = node[segment]; + } + } + } + + return node; +}; + +/** + * Sets a value at a given path on an object. + * @param {object} model - Object + * @param {string} _path - Dot-notated string to a path on the object + * @param {any} string - The value to set + */ +export const setOn = ( + model: { [key: string]: any }, + _path: string, + value: any +) => { + const path = _path.split('.'); + const propertyName = path.pop()!; + let node = model; + + while (path.length) { + const segment = path.shift()!; + if (node.hasOwnProperty(segment) === false) { + node[segment] = {}; + } + node = node[segment]; + } + + node[propertyName] = value; + return true; +}; + +/** + * Creates a class to store the `computer` method and its eventual parameters. + * Allows for on-demand computation with up-to-date parameters via `getValue` method. + * @constructor + * @param {function} computer - Function to be computed + * @param {string | array} dependencies - Dependencies passed to the `computer` as parameters + */ +export class Computed { + constructor( + public computer: (...values: any[]) => T, + public dependencies: string | string[] = [] + ) {} + + /** + * Executes the `computer` method with the current state of the theme + * by taking into account previously computed values and modifications. + * @param {Proxy | object} base - Computed or uncomputed theme + * @param {Proxy | object} modifications - Theme value overrides + * @param {object} working - Partially computed theme + * @param {string} colorMode - `light` or `dark` + */ + getValue( + base: EuiThemeSystem | EuiThemeShape | null, + modifications: EuiThemeModifications = {}, + working: Partial, + colorMode?: EuiThemeColorModeStandard + ) { + if (!this.dependencies.length) { + return this.computer(working); + } + if (!Array.isArray(this.dependencies)) { + return this.computer( + getOn(working, this.dependencies) ?? + getOn(modifications, this.dependencies, colorMode) ?? + (base ? getOn(base, this.dependencies, colorMode) : working) + ); + } + return this.computer( + this.dependencies.map((dependency) => { + return ( + getOn(working, dependency) ?? + getOn(modifications, dependency, colorMode) ?? + (base ? getOn(base, dependency, colorMode) : working) + ); + }) + ); + } +} + +/** + * Returns a Class (`Computed`) that stores the arbitrary computer method + * and references to its optional dependecies. + * @param {function} computer - Arbitrary method to be called at compute time. + * @param {string | array} dependencies - Values that will be provided to `computer` at compute time. + */ +export function computed(computer: (value: EuiThemeComputed) => T): T; +export function computed( + computer: (value: any[]) => T, + dependencies: string[] +): T; +export function computed( + computer: (value: any) => T, + dependencies: string +): T; +export function computed( + comp: ((value: T) => T) | ((value: any) => T) | ((value: any[]) => T), + dep?: string | string[] +) { + return new Computed(comp, dep); +} + +/** + * Type guard to check for a Computed object based on object shape + * without relying on the Computed class directly + */ +const isComputedLike = (key: object): key is Computed => { + if (typeof key !== 'object' || Array.isArray(key)) return false; + + return key.hasOwnProperty('dependencies') && key.hasOwnProperty('computer'); +}; + +/** + * Takes an uncomputed theme, and computes and returns all values taking + * into consideration value overrides and configured color mode. + * Overrides take precedence, and only values in the current color mode + * are computed and returned. + * @param {Proxy} base - Object to transform into Proxy + * @param {Proxy | object} over - Unique identifier or name + * @param {string} colorMode - `light` or `dark` + */ +export const getComputed = ( + base: EuiThemeSystem, + over: Partial>, + colorMode: EuiThemeColorModeStandard +): EuiThemeComputed => { + const output: Partial = { themeName: base.key }; + + function loop( + base: { [key: string]: any }, + over: { [key: string]: any }, + checkExisting: boolean = false, + path?: string + ) { + Object.keys(base).forEach((key) => { + let newPath = path ? `${path}.${key}` : `${key}`; + // @ts-expect-error `key` is not necessarily a colorMode key + if ([...Object.values(COLOR_MODES_STANDARD), colorMode].includes(key)) { + if (key !== colorMode) { + return; + } else { + const colorModeSegment = new RegExp( + `(\\.${colorMode}\\b)|(\\b${colorMode}\\.)` + ); + newPath = newPath.replace(colorModeSegment, ''); + } + } + const existing = checkExisting && getOn(output, newPath); + if (!existing || isObject(existing)) { + // NOTE: the class type check for Computed is not true for themes created externally; + // we additionally check on the object shape to confirm a Computed value + const baseValue = + base[key] instanceof Computed || isComputedLike(base[key]) + ? base[key].getValue(base.root, over.root, output, colorMode) + : base[key]; + const overValue = + over[key] instanceof Computed || isComputedLike(over[key]) + ? over[key].getValue(base.root, over.root, output, colorMode) + : over[key]; + if (isObject(baseValue) && !Array.isArray(baseValue)) { + loop(baseValue, overValue ?? {}, checkExisting, newPath); + } else { + setOn(output, newPath, overValue ?? baseValue); + } + } + }); + } + // Compute standard theme values and apply overrides + loop(base, over); + // Compute and apply extension values only + loop(over, {}, true); + return output as EuiThemeComputed; +}; + +/** + * Builds a Proxy with a custom `handler` designed to self-reference values + * and prevent arbitrary value overrides. + * @param {object} model - Object to transform into Proxy + * @param {string} key - Unique identifier or name + */ +export const buildTheme = (model: T, key: string) => { + const handler: ProxyHandler> = { + getPrototypeOf(target) { + return Reflect.getPrototypeOf(target.model); + }, + + setPrototypeOf(target, prototype) { + return Reflect.setPrototypeOf(target.model, prototype); + }, + + isExtensible(target) { + return Reflect.isExtensible(target); + }, + + preventExtensions(target) { + return Reflect.preventExtensions(target.model); + }, + + getOwnPropertyDescriptor(target, key) { + return Reflect.getOwnPropertyDescriptor(target.model, key); + }, + + defineProperty(target, property, attributes) { + return Reflect.defineProperty(target.model, property, attributes); + }, + + has(target, property) { + return Reflect.has(target.model, property); + }, + + get(_target, property) { + if (property === 'key') { + return _target[property]; + } + + // prevent Safari from locking up when the proxy is used in dev tools + // as it doesn't support getPrototypeOf + if (property === '__proto__') return {}; + + const target = property === 'root' ? _target : _target.model || _target; + // @ts-ignore `string` index signature + const value = target[property]; + if (isObject(value) && !Array.isArray(value)) { + return new Proxy( + { + model: value, + root: _target.root, + key: `_${_target.key}`, + }, + handler + ); + } else { + return value; + } + }, + + set(target: any) { + return target; + }, + + deleteProperty(target: any) { + return target; + }, + + ownKeys(target) { + return Reflect.ownKeys(target.model); + }, + + apply(target: any) { + return target; + }, + + construct(target: any) { + return target; + }, + }; + const themeProxy = new Proxy({ model, root: model, key }, handler); + + return themeProxy; +}; + +/** + * Deeply merges two objects, using `source` values whenever possible. + * @param {object} _target - Object with fallback values + * @param {object} source - Object with desired values + */ +export const mergeDeep = ( + _target: { [key: string]: any }, + source: { [key: string]: any } = {} +) => { + const target = { ..._target }; + + if (!isObject(target) || !isObject(source)) { + return source; + } + + Object.keys(source).forEach((key) => { + const targetValue = target[key]; + const sourceValue = source[key]; + + if (isObject(targetValue) && isObject(sourceValue)) { + target[key] = mergeDeep({ ...targetValue }, { ...sourceValue }); + } else { + target[key] = sourceValue; + } + }); + + return target; +}; diff --git a/packages/eui-theme-common/tsconfig.cjs.json b/packages/eui-theme-common/tsconfig.cjs.json new file mode 100644 index 00000000000..6becea42efa --- /dev/null +++ b/packages/eui-theme-common/tsconfig.cjs.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib/cjs", + "target": "es6", + "module": "CommonJS", + "lib": [ + "es6", + "DOM" + ], + "moduleResolution": "Node", + "declaration": true, + "sourceMap": true, + "noEmitHelpers": true, + "incremental": true, + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "tsBuildInfoFile": "lib/cjs/.tsbuildinfo", + "importHelpers": false, + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules" + ], +} \ No newline at end of file diff --git a/packages/eui-theme-common/tsconfig.json b/packages/eui-theme-common/tsconfig.json new file mode 100644 index 00000000000..31450bf12d6 --- /dev/null +++ b/packages/eui-theme-common/tsconfig.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib/esm", + "target": "ES2020", + "module": "ESNext", + "lib": [ + "ESNext", + "DOM" + ], + "moduleResolution": "Node", + "declaration": true, + "sourceMap": true, + "noEmitHelpers": true, + "incremental": true, + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "tsBuildInfoFile": "lib/esm/.tsbuildinfo" + }, + "include": [ + "src", + ], + "exclude": [ + "node_modules" + ], +} \ No newline at end of file diff --git a/packages/eui-theme-common/tsconfig.types.json b/packages/eui-theme-common/tsconfig.types.json new file mode 100644 index 00000000000..54e2031daae --- /dev/null +++ b/packages/eui-theme-common/tsconfig.types.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.cjs.json", + "compilerOptions": { + "outDir": "lib/cjs", + "declaration": true, + "declarationMap": true, + "isolatedModules": false, + "noEmit": false, + "allowJs": false, + "emitDeclarationOnly": true + }, + "exclude": ["node_modules", "**/*.test.ts"] +} \ No newline at end of file diff --git a/packages/eui/package.json b/packages/eui/package.json index d680d995bb6..d627c73c0ee 100644 --- a/packages/eui/package.json +++ b/packages/eui/package.json @@ -104,9 +104,8 @@ "@cypress/webpack-dev-server": "^1.7.0", "@elastic/charts": "^64.1.0", "@elastic/datemath": "^5.0.3", - "@elastic/eui-common": "workspace:^", - "@elastic/eui-theme-base": "workspace:^", "@elastic/eui-theme-borealis": "workspace:^", + "@elastic/eui-theme-common": "workspace:^", "@emotion/babel-preset-css-prop": "^11.11.0", "@emotion/cache": "^11.11.0", "@emotion/css": "^11.11.0", @@ -257,9 +256,8 @@ }, "peerDependencies": { "@elastic/datemath": "^5.0.2", - "@elastic/eui-common": "0.0.1", - "@elastic/eui-theme-base": "0.0.1", "@elastic/eui-theme-borealis": "0.0.1", + "@elastic/eui-theme-common": "0.0.1", "@emotion/css": "11.x", "@emotion/react": "11.x", "@types/react": "^16.9 || ^17.0 || ^18.0", diff --git a/packages/eui/src/components/common.ts b/packages/eui/src/components/common.ts index 8742d72c44f..4f88e2324c5 100644 --- a/packages/eui/src/components/common.ts +++ b/packages/eui/src/components/common.ts @@ -17,7 +17,7 @@ import { } from 'react'; import { Interpolation, Theme } from '@emotion/react'; -export type { RecursivePartial, ValueOf } from '@elastic/eui-common'; +export type { RecursivePartial, ValueOf } from '@elastic/eui-theme-common'; export interface CommonProps { className?: string; diff --git a/packages/eui/src/global_styling/functions/_index.scss b/packages/eui/src/global_styling/functions/_index.scss index dde124f0e17..7e1a8b1710d 100644 --- a/packages/eui/src/global_styling/functions/_index.scss +++ b/packages/eui/src/global_styling/functions/_index.scss @@ -1 +1 @@ -@import 'node_modules/@elastic/eui-common/src/global_styling/functions/index'; +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/functions/index'; diff --git a/packages/eui/src/global_styling/functions/size.ts b/packages/eui/src/global_styling/functions/size.ts index d3263020fc7..24652cc3ec1 100644 --- a/packages/eui/src/global_styling/functions/size.ts +++ b/packages/eui/src/global_styling/functions/size.ts @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export { sizeToPixel } from '@elastic/eui-common'; +export { sizeToPixel } from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/index.scss b/packages/eui/src/global_styling/index.scss index dc799ce26b6..ba88bef57dd 100644 --- a/packages/eui/src/global_styling/index.scss +++ b/packages/eui/src/global_styling/index.scss @@ -1,4 +1,3 @@ // Core -@import 'node_modules/@elastic/eui-theme-base/src/variables/index'; -@import 'node_modules/@elastic/eui-common/src/global_styling/index'; \ No newline at end of file +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/index'; \ No newline at end of file diff --git a/packages/eui/src/global_styling/variables/_animations.scss b/packages/eui/src/global_styling/variables/_animations.scss index c564fe586aa..b6e40a79f6d 100644 --- a/packages/eui/src/global_styling/variables/_animations.scss +++ b/packages/eui/src/global_styling/variables/_animations.scss @@ -1,6 +1,6 @@ // Animations -@import 'node_modules/@elastic/eui-theme-base/src/variables/animations' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/animations' // Keyframe animation declarations can be found in // utility/animations.scss diff --git a/packages/eui/src/global_styling/variables/_borders.scss b/packages/eui/src/global_styling/variables/_borders.scss index 779622116d0..818f5807e6f 100644 --- a/packages/eui/src/global_styling/variables/_borders.scss +++ b/packages/eui/src/global_styling/variables/_borders.scss @@ -1,3 +1,3 @@ // Borders -@import 'node_modules/@elastic/eui-theme-base/src/variables/borders' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/borders' diff --git a/packages/eui/src/global_styling/variables/_buttons.scss b/packages/eui/src/global_styling/variables/_buttons.scss index f840381b2f4..288dca14d61 100644 --- a/packages/eui/src/global_styling/variables/_buttons.scss +++ b/packages/eui/src/global_styling/variables/_buttons.scss @@ -1 +1 @@ -@import 'node_modules/@elastic/eui-theme-base/src/variables/buttons' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/buttons' diff --git a/packages/eui/src/global_styling/variables/_colors_vis.scss b/packages/eui/src/global_styling/variables/_colors_vis.scss index ac62244423a..d935ffa7ebe 100644 --- a/packages/eui/src/global_styling/variables/_colors_vis.scss +++ b/packages/eui/src/global_styling/variables/_colors_vis.scss @@ -1,3 +1,3 @@ // Visualization colors -@import 'node_modules/@elastic/eui-theme-base/src/variables/colors_vis' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/colors_vis' diff --git a/packages/eui/src/global_styling/variables/_colors_vis.ts b/packages/eui/src/global_styling/variables/_colors_vis.ts index 9ff03accec4..64dcfd86633 100644 --- a/packages/eui/src/global_styling/variables/_colors_vis.ts +++ b/packages/eui/src/global_styling/variables/_colors_vis.ts @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export { colorVis } from '@elastic/eui-theme-base'; +export { colorVis } from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/variables/_font_weight.scss b/packages/eui/src/global_styling/variables/_font_weight.scss index 7c21eb49d55..152c64d8358 100644 --- a/packages/eui/src/global_styling/variables/_font_weight.scss +++ b/packages/eui/src/global_styling/variables/_font_weight.scss @@ -1,4 +1,4 @@ // Separated out to its own file for easy import into docs // Font weights -@import 'node_modules/@elastic/eui-theme-base/src/variables/font_weight' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/font_weight' diff --git a/packages/eui/src/global_styling/variables/_form.scss b/packages/eui/src/global_styling/variables/_form.scss index abc5c608816..cdf08ad78bf 100644 --- a/packages/eui/src/global_styling/variables/_form.scss +++ b/packages/eui/src/global_styling/variables/_form.scss @@ -1,2 +1,2 @@ // Form -@import 'node_modules/@elastic/eui-theme-base/src/variables/form' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/form' diff --git a/packages/eui/src/global_styling/variables/_responsive.scss b/packages/eui/src/global_styling/variables/_responsive.scss index 3f187ca2d16..45e7a7c4531 100644 --- a/packages/eui/src/global_styling/variables/_responsive.scss +++ b/packages/eui/src/global_styling/variables/_responsive.scss @@ -1 +1 @@ -@import 'node_modules/@elastic/eui-theme-base/src/variables/responsive' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/responsive' diff --git a/packages/eui/src/global_styling/variables/_shadows.scss b/packages/eui/src/global_styling/variables/_shadows.scss index 7b50faeb167..14237af776b 100644 --- a/packages/eui/src/global_styling/variables/_shadows.scss +++ b/packages/eui/src/global_styling/variables/_shadows.scss @@ -1,2 +1,2 @@ // Shadows -@import 'node_modules/@elastic/eui-theme-base/src/variables/shadows' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/shadows' diff --git a/packages/eui/src/global_styling/variables/_size.scss b/packages/eui/src/global_styling/variables/_size.scss index aa1b710e880..987c03b80f6 100644 --- a/packages/eui/src/global_styling/variables/_size.scss +++ b/packages/eui/src/global_styling/variables/_size.scss @@ -1 +1 @@ -@import 'node_modules/@elastic/eui-theme-base/src/variables/size' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/size' diff --git a/packages/eui/src/global_styling/variables/_states.scss b/packages/eui/src/global_styling/variables/_states.scss index 332b22a7dad..581a81bb59b 100644 --- a/packages/eui/src/global_styling/variables/_states.scss +++ b/packages/eui/src/global_styling/variables/_states.scss @@ -1 +1 @@ -@import 'node_modules/@elastic/eui-theme-base/src/variables/states' \ No newline at end of file +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/states' \ No newline at end of file diff --git a/packages/eui/src/global_styling/variables/_typography.scss b/packages/eui/src/global_styling/variables/_typography.scss index 3750b61e117..70a15446af9 100644 --- a/packages/eui/src/global_styling/variables/_typography.scss +++ b/packages/eui/src/global_styling/variables/_typography.scss @@ -1 +1 @@ -@import 'node_modules/@elastic/eui-theme-base/src/variables/typography' \ No newline at end of file +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/typography' \ No newline at end of file diff --git a/packages/eui/src/global_styling/variables/_z_index.scss b/packages/eui/src/global_styling/variables/_z_index.scss index 119788c6b81..2c2769dbd85 100644 --- a/packages/eui/src/global_styling/variables/_z_index.scss +++ b/packages/eui/src/global_styling/variables/_z_index.scss @@ -1,2 +1,2 @@ // Z-Index -@import 'node_modules/@elastic/eui-theme-base/src/variables/z_index' +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/variables/z_index' diff --git a/packages/eui/src/global_styling/variables/animations.ts b/packages/eui/src/global_styling/variables/animations.ts index fa5600993f6..94a1f17c3d5 100644 --- a/packages/eui/src/global_styling/variables/animations.ts +++ b/packages/eui/src/global_styling/variables/animations.ts @@ -16,4 +16,4 @@ export { type _EuiThemeAnimationEasing, type _EuiThemeAnimationEasings, type _EuiThemeAnimation, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/variables/borders.ts b/packages/eui/src/global_styling/variables/borders.ts index 03b9d04bbb4..642575add78 100644 --- a/packages/eui/src/global_styling/variables/borders.ts +++ b/packages/eui/src/global_styling/variables/borders.ts @@ -13,4 +13,4 @@ export type { _EuiThemeBorderValues, _EuiThemeBorderTypes, _EuiThemeBorder, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/variables/breakpoint.ts b/packages/eui/src/global_styling/variables/breakpoint.ts index 456c0f7649e..85032f57d98 100644 --- a/packages/eui/src/global_styling/variables/breakpoint.ts +++ b/packages/eui/src/global_styling/variables/breakpoint.ts @@ -10,4 +10,4 @@ export { EuiThemeBreakpoints, type _EuiThemeBreakpoint, type _EuiThemeBreakpoints, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/variables/colors.ts b/packages/eui/src/global_styling/variables/colors.ts index 679f5f9b27c..48e23b66f82 100644 --- a/packages/eui/src/global_styling/variables/colors.ts +++ b/packages/eui/src/global_styling/variables/colors.ts @@ -15,4 +15,4 @@ export type { _EuiThemeConstantColors, _EuiThemeColorsMode, _EuiThemeColors, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/variables/levels.ts b/packages/eui/src/global_styling/variables/levels.ts index e6fdaed63c4..bf808d9abc7 100644 --- a/packages/eui/src/global_styling/variables/levels.ts +++ b/packages/eui/src/global_styling/variables/levels.ts @@ -10,4 +10,4 @@ export { EuiThemeLevels, type _EuiThemeLevel, type _EuiThemeLevels, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/variables/shadow.ts b/packages/eui/src/global_styling/variables/shadow.ts index a466ecb3fc0..69aeb0d5846 100644 --- a/packages/eui/src/global_styling/variables/shadow.ts +++ b/packages/eui/src/global_styling/variables/shadow.ts @@ -11,4 +11,4 @@ export { _EuiShadowSizesDescriptions, type _EuiThemeShadowSize, type _EuiThemeShadowCustomColor, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/variables/size.ts b/packages/eui/src/global_styling/variables/size.ts index bd9531337c9..da3c3c1eecb 100644 --- a/packages/eui/src/global_styling/variables/size.ts +++ b/packages/eui/src/global_styling/variables/size.ts @@ -11,4 +11,4 @@ export { type _EuiThemeBase, type _EuiThemeSize, type _EuiThemeSizes, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/variables/states.ts b/packages/eui/src/global_styling/variables/states.ts index b61f3efb3c4..205c6e7e7b9 100644 --- a/packages/eui/src/global_styling/variables/states.ts +++ b/packages/eui/src/global_styling/variables/states.ts @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export type { _EuiThemeFocus } from '@elastic/eui-theme-base'; +export type { _EuiThemeFocus } from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/global_styling/variables/typography.ts b/packages/eui/src/global_styling/variables/typography.ts index 3792c40fe12..dfd57186191 100644 --- a/packages/eui/src/global_styling/variables/typography.ts +++ b/packages/eui/src/global_styling/variables/typography.ts @@ -19,4 +19,4 @@ export { type _EuiThemeBody, type _EuiThemeTitle, type _EuiThemeFont, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/services/theme/types.ts b/packages/eui/src/services/theme/types.ts index c4562b1ff92..a8912db19ed 100644 --- a/packages/eui/src/services/theme/types.ts +++ b/packages/eui/src/services/theme/types.ts @@ -19,4 +19,4 @@ export { type ComputedThemeShape, type EuiThemeComputed, type EuiThemeNested, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/eui/src/services/theme/utils.ts b/packages/eui/src/services/theme/utils.ts index 96ed31cdda5..e86ad5c659d 100644 --- a/packages/eui/src/services/theme/utils.ts +++ b/packages/eui/src/services/theme/utils.ts @@ -17,4 +17,4 @@ export { getComputed, buildTheme, mergeDeep, -} from '@elastic/eui-theme-base'; +} from '@elastic/eui-theme-common'; diff --git a/packages/website/package.json b/packages/website/package.json index 566442cf74f..f2c30552a03 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "docusaurus": "docusaurus", - "build:workspaces": "yarn workspace @elastic/eui-common run build && yarn workspace @elastic/eui-theme-base run build && yarn workspace @elastic/eui-theme-borealis run build && yarn workspaces foreach -Rti --from @elastic/eui-website run build", + "build:workspaces": "yarn workspaces foreach -Rti --from @elastic/eui-website run build", "start": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus start", "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus build", "swizzle": "docusaurus swizzle", diff --git a/yarn.lock b/yarn.lock index 6a22de6c8e8..70a6558708d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5696,32 +5696,6 @@ __metadata: languageName: unknown linkType: soft -"@elastic/eui-common@workspace:^, @elastic/eui-common@workspace:packages/eui-common": - version: 0.0.0-use.local - resolution: "@elastic/eui-common@workspace:packages/eui-common" - dependencies: - "@babel/cli": "npm:^7.21.5" - "@babel/core": "npm:^7.21.8" - "@babel/preset-env": "npm:^7.21.5" - "@babel/preset-react": "npm:^7.18.6" - "@babel/preset-typescript": "npm:^7.21.5" - "@types/jest": "npm:^29.5.12" - "@types/prettier": "npm:2.7.3" - "@typescript-eslint/eslint-plugin": "npm:^5.59.7" - "@typescript-eslint/parser": "npm:^5.59.7" - eslint: "npm:^8.41.0" - eslint-config-prettier: "npm:^8.8.0" - eslint-plugin-import: "npm:^2.27.5" - eslint-plugin-jest: "npm:^28.5.0" - eslint-plugin-local: "npm:^1.0.0" - eslint-plugin-prettier: "npm:^4.2.1" - jest: "npm:^29.7.0" - prettier: "npm:^2.8.8" - rimraf: "npm:^6.0.1" - typescript: "npm:^5.6.2" - languageName: unknown - linkType: soft - "@elastic/eui-docgen@workspace:^, @elastic/eui-docgen@workspace:packages/eui-docgen": version: 0.0.0-use.local resolution: "@elastic/eui-docgen@workspace:packages/eui-docgen" @@ -5775,16 +5749,40 @@ __metadata: languageName: unknown linkType: soft -"@elastic/eui-theme-base@workspace:^, @elastic/eui-theme-base@workspace:packages/eui-theme-base": +"@elastic/eui-theme-borealis@workspace:^, @elastic/eui-theme-borealis@workspace:packages/eui-theme-borealis": + version: 0.0.0-use.local + resolution: "@elastic/eui-theme-borealis@workspace:packages/eui-theme-borealis" + dependencies: + "@elastic/eui-theme-common": "workspace:^" + "@types/jest": "npm:^29.5.12" + "@types/prettier": "npm:2.7.3" + "@typescript-eslint/eslint-plugin": "npm:^5.59.7" + "@typescript-eslint/parser": "npm:^5.59.7" + eslint: "npm:^8.41.0" + eslint-config-prettier: "npm:^8.8.0" + eslint-plugin-import: "npm:^2.27.5" + eslint-plugin-jest: "npm:^28.5.0" + eslint-plugin-local: "npm:^1.0.0" + eslint-plugin-prettier: "npm:^4.2.1" + jest: "npm:^29.7.0" + prettier: "npm:^2.8.8" + stylelint: "npm:^15.7.0" + stylelint-config-prettier-scss: "npm:^1.0.0" + stylelint-config-standard: "npm:^33.0.0" + stylelint-config-standard-scss: "npm:^9.0.0" + typescript: "npm:^5.6.2" + languageName: unknown + linkType: soft + +"@elastic/eui-theme-common@workspace:^, @elastic/eui-theme-common@workspace:packages/eui-theme-common": version: 0.0.0-use.local - resolution: "@elastic/eui-theme-base@workspace:packages/eui-theme-base" + resolution: "@elastic/eui-theme-common@workspace:packages/eui-theme-common" dependencies: "@babel/cli": "npm:^7.21.5" "@babel/core": "npm:^7.21.8" "@babel/preset-env": "npm:^7.21.5" "@babel/preset-react": "npm:^7.18.6" "@babel/preset-typescript": "npm:^7.21.5" - "@elastic/eui-common": "workspace:^" "@types/jest": "npm:^29.5.12" "@types/prettier": "npm:2.7.3" "@typescript-eslint/eslint-plugin": "npm:^5.59.7" @@ -5803,21 +5801,6 @@ __metadata: stylelint-config-standard: "npm:^33.0.0" stylelint-config-standard-scss: "npm:^9.0.0" typescript: "npm:4.5.3" - peerDependencies: - "@elastic/eui-common": 0.0.1 - languageName: unknown - linkType: soft - -"@elastic/eui-theme-borealis@workspace:^, @elastic/eui-theme-borealis@workspace:packages/eui-theme-borealis": - version: 0.0.0-use.local - resolution: "@elastic/eui-theme-borealis@workspace:packages/eui-theme-borealis" - dependencies: - "@elastic/eui-common": "workspace:^" - "@elastic/eui-theme-base": "workspace:^" - typescript: "npm:^5.6.2" - peerDependencies: - "@elastic/eui-common": 0.0.1 - "@elastic/eui-theme-base": 0.0.1 languageName: unknown linkType: soft @@ -5873,9 +5856,8 @@ __metadata: "@cypress/webpack-dev-server": "npm:^1.7.0" "@elastic/charts": "npm:^64.1.0" "@elastic/datemath": "npm:^5.0.3" - "@elastic/eui-common": "workspace:^" - "@elastic/eui-theme-base": "workspace:^" "@elastic/eui-theme-borealis": "workspace:^" + "@elastic/eui-theme-common": "workspace:^" "@emotion/babel-preset-css-prop": "npm:^11.11.0" "@emotion/cache": "npm:^11.11.0" "@emotion/css": "npm:^11.11.0" @@ -6058,8 +6040,6 @@ __metadata: yo: "npm:^4.3.1" peerDependencies: "@elastic/datemath": ^5.0.2 - "@elastic/eui-common": 0.0.1 - "@elastic/eui-theme-base": 0.0.1 "@elastic/eui-theme-borealis": 0.0.1 "@emotion/css": 11.x "@emotion/react": 11.x From 854540d18c7fa126c350487494075d2a6e2e26f9 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Tue, 8 Oct 2024 17:20:27 +0200 Subject: [PATCH 26/32] -remove eui-common package --- packages/eui-common/.babelrc.js | 27 - packages/eui-common/.eslintignore | 9 - packages/eui-common/.eslintplugin.js | 3 - packages/eui-common/.eslintrc.js | 115 --- packages/eui-common/.gitignore | 11 - packages/eui-common/.prettierrc | 7 - packages/eui-common/LICENSE.txt | 6 - packages/eui-common/README.md | 1 - packages/eui-common/babel.config.js | 6 - packages/eui-common/package.json | 62 -- .../require_license_header.js | 132 --- .../require_license_header.test.js | 177 ---- .../src/global_styling/functions/_colors.scss | 138 ---- .../src/global_styling/functions/_index.scss | 5 - .../src/global_styling/functions/_math.scss | 1 - .../global_styling/functions/_math_pow.scss | 82 -- .../src/global_styling/functions/index.ts | 9 - .../src/global_styling/functions/size.ts | 26 - .../eui-common/src/global_styling/index.scss | 15 - .../src/global_styling/mixins/_button.scss | 149 ---- .../src/global_styling/mixins/_form.scss | 273 ------- .../src/global_styling/mixins/_helpers.scss | 126 --- .../src/global_styling/mixins/_index.scss | 14 - .../src/global_styling/mixins/_link.scss | 11 - .../src/global_styling/mixins/_loading.scss | 6 - .../src/global_styling/mixins/_panel.scss | 55 -- .../src/global_styling/mixins/_range.scss | 62 -- .../global_styling/mixins/_responsive.scss | 44 - .../src/global_styling/mixins/_shadow.scss | 108 --- .../src/global_styling/mixins/_size.scss | 4 - .../src/global_styling/mixins/_states.scss | 50 -- .../src/global_styling/mixins/_tool_tip.scss | 25 - .../global_styling/mixins/_typography.scss | 167 ---- .../react_date_picker/_date_picker.scss | 772 ------------------ .../react_date_picker/_index.scss | 2 - .../react_date_picker/_variables.scss | 1 - .../global_styling/utility/_animations.scss | 55 -- .../src/global_styling/utility/_index.scss | 1 - packages/eui-common/src/index.ts | 10 - packages/eui-common/src/types.ts | 56 -- packages/eui-common/tsconfig.cjs.json | 29 - packages/eui-common/tsconfig.json | 28 - packages/eui-common/tsconfig.types.json | 13 - packages/eui-theme-base/.babelrc.js | 27 - packages/eui-theme-base/.eslintignore | 9 - packages/eui-theme-base/.eslintplugin.js | 3 - packages/eui-theme-base/.eslintrc.js | 114 --- packages/eui-theme-base/.gitignore | 11 - packages/eui-theme-base/.prettierrc | 7 - packages/eui-theme-base/.stylelintrc.js | 163 ---- packages/eui-theme-base/LICENSE.txt | 6 - packages/eui-theme-base/README.md | 1 - packages/eui-theme-base/babel.config.js | 6 - packages/eui-theme-base/package.json | 70 -- packages/eui-theme-base/src/index.ts | 11 - packages/eui-theme-base/src/types.ts | 105 --- packages/eui-theme-base/src/utils.test.ts | 279 ------- packages/eui-theme-base/src/utils.ts | 392 --------- .../src/variables/_animations.scss | 13 - .../src/variables/_borders.scss | 11 - .../src/variables/_buttons.scss | 18 - .../src/variables/_colors_vis.scss | 72 -- .../src/variables/_colors_vis.ts | 62 -- .../src/variables/_font_weight.scss | 10 - .../eui-theme-base/src/variables/_form.scss | 21 - .../eui-theme-base/src/variables/_index.scss | 23 - .../src/variables/_responsive.scss | 9 - .../src/variables/_shadows.scss | 2 - .../eui-theme-base/src/variables/_size.scss | 15 - .../eui-theme-base/src/variables/_states.scss | 14 - .../src/variables/_typography.scss | 75 -- .../src/variables/_z_index.scss | 34 - .../src/variables/animations.ts | 66 -- .../eui-theme-base/src/variables/borders.ts | 74 -- .../src/variables/breakpoint.ts | 28 - .../eui-theme-base/src/variables/colors.ts | 156 ---- .../eui-theme-base/src/variables/index.ts | 18 - .../eui-theme-base/src/variables/levels.ts | 60 -- .../eui-theme-base/src/variables/shadow.ts | 28 - packages/eui-theme-base/src/variables/size.ts | 47 -- .../eui-theme-base/src/variables/states.ts | 33 - .../src/variables/typography.ts | 146 ---- packages/eui-theme-base/tsconfig.cjs.json | 29 - packages/eui-theme-base/tsconfig.json | 28 - packages/eui-theme-base/tsconfig.types.json | 13 - 85 files changed, 5202 deletions(-) delete mode 100644 packages/eui-common/.babelrc.js delete mode 100644 packages/eui-common/.eslintignore delete mode 100644 packages/eui-common/.eslintplugin.js delete mode 100644 packages/eui-common/.eslintrc.js delete mode 100644 packages/eui-common/.gitignore delete mode 100644 packages/eui-common/.prettierrc delete mode 100644 packages/eui-common/LICENSE.txt delete mode 100644 packages/eui-common/README.md delete mode 100644 packages/eui-common/babel.config.js delete mode 100644 packages/eui-common/package.json delete mode 100644 packages/eui-common/scripts/eslint-plugin-local/require_license_header.js delete mode 100644 packages/eui-common/scripts/eslint-plugin-local/require_license_header.test.js delete mode 100644 packages/eui-common/src/global_styling/functions/_colors.scss delete mode 100644 packages/eui-common/src/global_styling/functions/_index.scss delete mode 100644 packages/eui-common/src/global_styling/functions/_math.scss delete mode 100644 packages/eui-common/src/global_styling/functions/_math_pow.scss delete mode 100644 packages/eui-common/src/global_styling/functions/index.ts delete mode 100644 packages/eui-common/src/global_styling/functions/size.ts delete mode 100644 packages/eui-common/src/global_styling/index.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_button.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_form.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_helpers.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_index.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_link.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_loading.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_panel.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_range.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_responsive.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_shadow.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_size.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_states.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_tool_tip.scss delete mode 100644 packages/eui-common/src/global_styling/mixins/_typography.scss delete mode 100644 packages/eui-common/src/global_styling/react_date_picker/_date_picker.scss delete mode 100644 packages/eui-common/src/global_styling/react_date_picker/_index.scss delete mode 100644 packages/eui-common/src/global_styling/react_date_picker/_variables.scss delete mode 100644 packages/eui-common/src/global_styling/utility/_animations.scss delete mode 100644 packages/eui-common/src/global_styling/utility/_index.scss delete mode 100644 packages/eui-common/src/index.ts delete mode 100644 packages/eui-common/src/types.ts delete mode 100644 packages/eui-common/tsconfig.cjs.json delete mode 100644 packages/eui-common/tsconfig.json delete mode 100644 packages/eui-common/tsconfig.types.json delete mode 100644 packages/eui-theme-base/.babelrc.js delete mode 100644 packages/eui-theme-base/.eslintignore delete mode 100644 packages/eui-theme-base/.eslintplugin.js delete mode 100644 packages/eui-theme-base/.eslintrc.js delete mode 100644 packages/eui-theme-base/.gitignore delete mode 100644 packages/eui-theme-base/.prettierrc delete mode 100644 packages/eui-theme-base/.stylelintrc.js delete mode 100644 packages/eui-theme-base/LICENSE.txt delete mode 100644 packages/eui-theme-base/README.md delete mode 100644 packages/eui-theme-base/babel.config.js delete mode 100644 packages/eui-theme-base/package.json delete mode 100644 packages/eui-theme-base/src/index.ts delete mode 100644 packages/eui-theme-base/src/types.ts delete mode 100644 packages/eui-theme-base/src/utils.test.ts delete mode 100644 packages/eui-theme-base/src/utils.ts delete mode 100644 packages/eui-theme-base/src/variables/_animations.scss delete mode 100644 packages/eui-theme-base/src/variables/_borders.scss delete mode 100644 packages/eui-theme-base/src/variables/_buttons.scss delete mode 100644 packages/eui-theme-base/src/variables/_colors_vis.scss delete mode 100644 packages/eui-theme-base/src/variables/_colors_vis.ts delete mode 100644 packages/eui-theme-base/src/variables/_font_weight.scss delete mode 100644 packages/eui-theme-base/src/variables/_form.scss delete mode 100644 packages/eui-theme-base/src/variables/_index.scss delete mode 100644 packages/eui-theme-base/src/variables/_responsive.scss delete mode 100644 packages/eui-theme-base/src/variables/_shadows.scss delete mode 100644 packages/eui-theme-base/src/variables/_size.scss delete mode 100644 packages/eui-theme-base/src/variables/_states.scss delete mode 100644 packages/eui-theme-base/src/variables/_typography.scss delete mode 100644 packages/eui-theme-base/src/variables/_z_index.scss delete mode 100644 packages/eui-theme-base/src/variables/animations.ts delete mode 100644 packages/eui-theme-base/src/variables/borders.ts delete mode 100644 packages/eui-theme-base/src/variables/breakpoint.ts delete mode 100644 packages/eui-theme-base/src/variables/colors.ts delete mode 100644 packages/eui-theme-base/src/variables/index.ts delete mode 100644 packages/eui-theme-base/src/variables/levels.ts delete mode 100644 packages/eui-theme-base/src/variables/shadow.ts delete mode 100644 packages/eui-theme-base/src/variables/size.ts delete mode 100644 packages/eui-theme-base/src/variables/states.ts delete mode 100644 packages/eui-theme-base/src/variables/typography.ts delete mode 100644 packages/eui-theme-base/tsconfig.cjs.json delete mode 100644 packages/eui-theme-base/tsconfig.json delete mode 100644 packages/eui-theme-base/tsconfig.types.json diff --git a/packages/eui-common/.babelrc.js b/packages/eui-common/.babelrc.js deleted file mode 100644 index 0fc74dd1fe9..00000000000 --- a/packages/eui-common/.babelrc.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = { - // We need to preserve comments as they are used by webpack for - // naming chunks during code-splitting. The compression step during - // bundling will remove them later. - comments: true, - - presets: [ - [ - '@babel/env', - { - // `targets` property set via `.browserslistrc` - useBuiltIns: process.env.NO_COREJS_POLYFILL ? false : 'usage', - corejs: !process.env.NO_COREJS_POLYFILL ? '3.6' : undefined, - modules: process.env.BABEL_MODULES - ? process.env.BABEL_MODULES === 'false' - ? false - : process.env.BABEL_MODULES - : 'commonjs', // babel's default is commonjs - }, - ], - ['@babel/react', { runtime: 'classic' }], - [ - '@babel/typescript', - { isTSX: true, allExtensions: true, allowDeclareFields: true }, - ], - ], -}; diff --git a/packages/eui-common/.eslintignore b/packages/eui-common/.eslintignore deleted file mode 100644 index 4874b17b0b8..00000000000 --- a/packages/eui-common/.eslintignore +++ /dev/null @@ -1,9 +0,0 @@ -dist -node_modules -lib -types -**/*.d.ts -package.json -scripts -.eslintrc.js -babel.config.js diff --git a/packages/eui-common/.eslintplugin.js b/packages/eui-common/.eslintplugin.js deleted file mode 100644 index 25ddbe3db65..00000000000 --- a/packages/eui-common/.eslintplugin.js +++ /dev/null @@ -1,3 +0,0 @@ -exports.rules = { - 'require-license-header': require('./scripts/eslint-plugin-local/require_license_header.js'), -}; diff --git a/packages/eui-common/.eslintrc.js b/packages/eui-common/.eslintrc.js deleted file mode 100644 index 2d464dca972..00000000000 --- a/packages/eui-common/.eslintrc.js +++ /dev/null @@ -1,115 +0,0 @@ -const SSPL_ELASTIC_2_0_LICENSE_HEADER = ` -/* - * 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. - */ -`; - -module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: ['./tsconfig.json'], - ecmaFeatures: { - jsx: true, - }, - }, - settings: { - 'import/resolver': { - node: { - extensions: ['.ts', '.tsx', '.js', '.json'], - paths: ['.'], - }, - }, - }, - extends: [ - 'plugin:@typescript-eslint/recommended', - // Prettier options need to come last, in order to override other style rules - 'plugin:prettier/recommended', - ], - plugins: ['local', 'import'], - rules: { - 'block-scoped-var': 'error', - camelcase: 'off', - 'dot-notation': ['error', { allowKeywords: true }], - eqeqeq: ['error', 'always', { null: 'ignore' }], - 'guard-for-in': 'error', - 'new-cap': ['error', { capIsNewExceptions: ['Private'] }], - 'no-caller': 'error', - 'no-const-assign': 'error', - 'no-debugger': 'error', - 'no-empty': ['error', { allowEmptyCatch: true }], - 'no-eval': 'error', - 'no-extend-native': 'error', - 'no-global-assign': 'error', - 'no-loop-func': 'error', - 'no-restricted-globals': ['error', 'context'], - 'no-script-url': 'error', - 'no-sequences': 'error', - 'no-var': 'error', - 'no-with': 'error', - 'prefer-const': 'error', - 'prefer-template': 'error', - strict: ['error', 'never'], - 'valid-typeof': 'error', - - 'local/require-license-header': [ - 'warn', - { - license: SSPL_ELASTIC_2_0_LICENSE_HEADER, - }, - ], - - 'import/no-unresolved': ['error', { amd: true, commonjs: true }], - 'import/namespace': 'error', - 'import/default': 'error', - 'import/export': 'error', - 'import/no-named-as-default': 'error', - 'import/no-named-as-default-member': 'error', - 'import/no-duplicates': 'error', - - '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], - '@typescript-eslint/ban-types': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-member-accessibility': 'off', - '@typescript-eslint/indent': 'off', - '@typescript-eslint/ban-tslint-comment': 'error', - '@typescript-eslint/no-empty-interface': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-parameter-properties': 'off', - '@typescript-eslint/no-triple-slash-reference': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { argsIgnorePattern: '^_', ignoreRestSiblings: true }, - ], - '@typescript-eslint/no-use-before-define': 'off', - '@typescript-eslint/no-empty-function': 'off', - // It"s all very well saying that some types are trivially inferrable, - // but being explicit is still clearer. - '@typescript-eslint/no-inferrable-types': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/naming-convention': 'off', - '@typescript-eslint/ban-ts-comment': [ - 'error', - { - 'ts-ignore': 'allow-with-description', - 'ts-expect-error': 'allow-with-description', - }, - ], - '@typescript-eslint/consistent-type-exports': [ - 'error', - { fixMixedExportsWithInlineTypeSpecifier: false }, - ], - }, - overrides: [ - { - files: ['*.d.ts'], - rules: { - 'react/prefer-es6-class': 'off', - }, - }, - ], -}; diff --git a/packages/eui-common/.gitignore b/packages/eui-common/.gitignore deleted file mode 100644 index 4450fe8d868..00000000000 --- a/packages/eui-common/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -# Dependencies -/node_modules - -# Production -/lib - -yarn-debug.log* -yarn-error.log* - -# Build-related files -.eslintcache \ No newline at end of file diff --git a/packages/eui-common/.prettierrc b/packages/eui-common/.prettierrc deleted file mode 100644 index b2f0fa8f00e..00000000000 --- a/packages/eui-common/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parser": "typescript", - "printWidth": 80, - "semi": true, - "singleQuote": true, - "trailingComma": "es5" -} diff --git a/packages/eui-common/LICENSE.txt b/packages/eui-common/LICENSE.txt deleted file mode 100644 index 74327a8f6f3..00000000000 --- a/packages/eui-common/LICENSE.txt +++ /dev/null @@ -1,6 +0,0 @@ -Source code in this repository is covered by (i) a dual license under the Server -Side Public License, v 1 and the Elastic License 2.0 or (ii) an Apache License -2.0 compatible license or (iii) solely under the Elastic License 2.0, in each -case, as noted in the applicable header. The default throughout the repository -is a dual license under the Server Side Public License, v 1 and the Elastic -License 2.0, unless the header specifies another license. diff --git a/packages/eui-common/README.md b/packages/eui-common/README.md deleted file mode 100644 index 7531d756f9a..00000000000 --- a/packages/eui-common/README.md +++ /dev/null @@ -1 +0,0 @@ -# EUI common, shared functionality \ No newline at end of file diff --git a/packages/eui-common/babel.config.js b/packages/eui-common/babel.config.js deleted file mode 100644 index 8165fe45577..00000000000 --- a/packages/eui-common/babel.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - presets: [ - ['@babel/preset-env', { targets: { node: 'current' } }], - '@babel/preset-typescript', - ], -}; diff --git a/packages/eui-common/package.json b/packages/eui-common/package.json deleted file mode 100644 index 7b3e8b3f420..00000000000 --- a/packages/eui-common/package.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "@elastic/eui-common", - "version": "0.0.1", - "description": "Common shared EUI functionality", - "license": "SEE LICENSE IN LICENSE.txt", - "scripts": { - "build:clean": "rimraf lib", - "build": "yarn build:clean && yarn build:compile && yarn build:compile:cjs && yarn build:types", - "build:compile": "tsc --project tsconfig.json", - "build:compile:cjs": "NODE_ENV=production babel src --out-dir=lib/cjs --extensions .js,.ts,.tsx --source-maps", - "build:types": "NODE_ENV=production tsc --project tsconfig.types.json", - "build-pack": "yarn build && npm pack", - "lint": "yarn tsc --noEmit && yarn lint-es", - "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", - "test": "jest" - }, - "repository": { - "type": "git", - "url": "https://github.com/elastic/eui.git", - "directory": "packages/eui-common" - }, - "private": true, - "devDependencies": { - "@babel/cli": "^7.21.5", - "@babel/core": "^7.21.8", - "@babel/preset-env": "^7.21.5", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.5", - "@types/jest": "^29.5.12", - "@types/prettier": "2.7.3", - "@typescript-eslint/eslint-plugin": "^5.59.7", - "@typescript-eslint/parser": "^5.59.7", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jest": "^28.5.0", - "eslint-plugin-local": "^1.0.0", - "eslint-plugin-prettier": "^4.2.1", - "jest": "^29.7.0", - "prettier": "^2.8.8", - "rimraf": "^6.0.1", - "typescript": "^5.6.2" - }, - "main": "lib/cjs/index.js", - "exports": { - "./lib/*": "./lib/*", - "./scripts/*": "./scripts/*", - ".": { - "require": "./lib/cjs/index.js", - "import": "./lib/esm/index.js", - "default": "./lib/cjs/index.js" - } - }, - "files": [ - "lib/", - "src/**/*.scss", - "README.md" - ], - "installConfig": { - "hoistingLimits": "workspaces" - } -} diff --git a/packages/eui-common/scripts/eslint-plugin-local/require_license_header.js b/packages/eui-common/scripts/eslint-plugin-local/require_license_header.js deleted file mode 100644 index 23b83648dd1..00000000000 --- a/packages/eui-common/scripts/eslint-plugin-local/require_license_header.js +++ /dev/null @@ -1,132 +0,0 @@ -const eslintParser = require('@typescript-eslint/parser'); - -function assert(truth, message) { - if (truth) { - return; - } - - const error = new Error(message); - error.failedAssertion = true; - throw error; -} - -function normalizeWhitespace(string) { - return string.replace(/\s+/g, ' '); -} - -function init(context, program, initStep) { - try { - return initStep(); - } catch (error) { - if (error.failedAssertion) { - context.report({ - node: program, - message: error.message, - }); - } else { - throw error; - } - } -} - -function isHashbang(text) { - return text.trim().startsWith('#!') && !text.trim().includes('\n'); -} - -module.exports = { - meta: { - fixable: 'code', - schema: [ - { - type: 'object', - properties: { - license: { - type: 'string', - }, - }, - additionalProperties: false, - }, - ], - }, - create: (context) => { - return { - Program(program) { - const license = init(context, program, function () { - const options = context.options[0] || {}; - const license = options.license; - - assert(!!license, '"license" option is required'); - - const parsed = eslintParser.parse(license, { comment: true }); - assert( - !parsed.body.length, - '"license" option must only include a single comment' - ); - assert( - parsed.comments.length === 1, - '"license" option must only include a single comment' - ); - - return { - source: license, - nodeValue: normalizeWhitespace(parsed.comments[0].value), - }; - }); - - if (!license) { - return; - } - - const sourceCode = context.getSourceCode(); - const comment = sourceCode - .getAllComments() - .find( - (node) => normalizeWhitespace(node.value) === license.nodeValue - ); - - // no licence comment - if (!comment) { - context.report({ - message: 'File must start with a license header', - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: sourceCode.lines[0].length - 1 }, - }, - fix(fixer) { - if (isHashbang(sourceCode.lines[0])) { - return undefined; - } - - return fixer.replaceTextRange([0, 0], license.source + '\n\n'); - }, - }); - return; - } - - // ensure there is nothing before the comment - const sourceBeforeNode = sourceCode - .getText() - .slice(0, sourceCode.getIndexFromLoc(comment.loc.start)); - if (sourceBeforeNode.length && !isHashbang(sourceBeforeNode)) { - context.report({ - node: comment, - message: 'License header must be at the very beginning of the file', - fix(fixer) { - // replace leading whitespace if possible - if (sourceBeforeNode.trim() === '') { - return fixer.replaceTextRange([0, sourceBeforeNode.length], ''); - } - - // inject content at top and remove node from current location - // if removing whitespace is not possible - return [ - fixer.remove(comment), - fixer.replaceTextRange([0, 0], license.source + '\n\n'), - ]; - }, - }); - } - }, - }; - }, -}; diff --git a/packages/eui-common/scripts/eslint-plugin-local/require_license_header.test.js b/packages/eui-common/scripts/eslint-plugin-local/require_license_header.test.js deleted file mode 100644 index 904dff17bc0..00000000000 --- a/packages/eui-common/scripts/eslint-plugin-local/require_license_header.test.js +++ /dev/null @@ -1,177 +0,0 @@ -const { RuleTester } = require('eslint'); -const rule = require('./require_license_header'); -const dedent = require('dedent'); - -const ruleTester = new RuleTester({ - parser: require.resolve('@typescript-eslint/parser'), -}); - -ruleTester.run('@kbn/eslint/require-license-header', rule, { - valid: [ - { - code: dedent` - /* license */ - - console.log('foo') - `, - - options: [{ license: '/* license */' }], - }, - { - code: dedent` - // license - - console.log('foo') - `, - - options: [{ license: '// license' }], - }, - ], - - invalid: [ - // missing license option - { - code: dedent` - console.log('foo') - `, - - options: [], - errors: [ - { - message: '"license" option is required', - }, - ], - }, - - // content cannot contain multiple block comments - { - code: dedent` - console.log('foo') - `, - - options: [{ license: '/* one *//* two */' }], - errors: [ - { - message: '"license" option must only include a single comment', - }, - ], - }, - - // content cannot contain multiple line comments - { - code: dedent` - console.log('foo') - `, - - options: [{ license: `// one\n// two` }], - errors: [ - { - message: '"license" option must only include a single comment', - }, - ], - }, - - // content cannot contain expressions - { - code: dedent` - console.log('foo') - `, - - options: [ - { - license: dedent` - /* license */ - console.log('hello world'); - `, - }, - ], - errors: [ - { - message: '"license" option must only include a single comment', - }, - ], - }, - - // content is not a single comment - { - code: dedent` - console.log('foo') - `, - - options: [{ license: `console.log('hello world');` }], - errors: [ - { - message: '"license" option must only include a single comment', - }, - ], - }, - - // missing license header - { - code: dedent` - console.log('foo') - `, - - options: [{ license: '/* license */' }], - errors: [ - { - message: 'File must start with a license header', - }, - ], - - output: dedent` - /* license */ - - console.log('foo') - `, - }, - - // strips newlines before the license comment - { - code: - '\n\n' + - dedent` - /* license */ - - console.log('foo') - `, - - options: [{ license: '/* license */' }], - errors: [ - { - message: 'License header must be at the very beginning of the file', - }, - ], - - output: dedent` - /* license */ - - console.log('foo') - `, - }, - - // moves license header before other nodes if necessary - { - code: dedent` - /* not license */ - /* license */ - console.log('foo') - `, - - options: [{ license: '/* license */' }], - errors: [ - { - message: 'License header must be at the very beginning of the file', - }, - ], - - output: dedent` - /* license */ - - /* not license */ - - console.log('foo') - `, - }, - ], -}); diff --git a/packages/eui-common/src/global_styling/functions/_colors.scss b/packages/eui-common/src/global_styling/functions/_colors.scss deleted file mode 100644 index 25834e10add..00000000000 --- a/packages/eui-common/src/global_styling/functions/_colors.scss +++ /dev/null @@ -1,138 +0,0 @@ -// Converting a normal hex color to RBG -@function hexToRGB($color) { - @return 'rgb%28#{round(red($color))}, #{round(green($color))}, #{round(blue($color))}%29'; -} - -// Mixes a provided color with white. -@function tint($color, $percent) { - @return mix($euiColorGhost, $color, $percent); -} - -// Mixes a provided color with black. -@function shade($color, $percent) { - @return mix($euiColorInk, $color, $percent); -} - -// For theming. Checks the text color and tells us whether it's light or dark. -// Based on that we either tint (add white) or shade (add black). -@function tintOrShade($color, $tint, $shade) { - @if (lightness($euiTextColor) > 50) { - @return shade($color, $shade); - } @else { - @return tint($color, $tint); - } -} - -// The reverse of the above -@function shadeOrTint($color, $shade, $tint) { - @if (lightness($euiTextColor) < 50) { - @return shade($color, $shade); - } @else { - @return tint($color, $tint); - } -} - -// Similar to above, but uses the light or dark color based -// on whether it's the light or dark theme -@function lightOrDarkTheme($lightColor, $darkColor) { - @if (lightness($euiTextColor) < 50) { - @return $lightColor; - } @else { - @return $darkColor; - } -} - -// Calculates luminance, which is better than brightness for checking colors -// pow, nth functions come from the _math.scss functions -@function luminance($color) { - // Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef - $rgba: red($color), green($color), blue($color); - $rgba2: (); - - @for $i from 1 through 3 { - $rgb: nth($rgba, $i); - $rgb: $rgb / 255; - - $rgb: if($rgb < .03928, $rgb / 12.92, pow(($rgb + .055) / 1.055, 2.4)); - - $rgba2: append($rgba2, $rgb); - } - - @return .2126 * nth($rgba2, 1) + .7152 * nth($rgba2, 2) + .0722 * nth($rgba2, 3); -} - -// Calculate contrast -@function contrastRatio($background, $foreground) { - $backgroundLum: luminance($background) + .05; - $foregroundLum: luminance($foreground) + .05; - - @return max($backgroundLum, $foregroundLum) / min($backgroundLum, $foregroundLum); -} - -// Given $color, decide whether $lightText or $darkText should be used as the text color -// ex: chooseLightOrDarkText(#EEE, #FFF, #000) would return #000 because it has -// a higher contrast than #FFF against a #EEE background. -@function chooseLightOrDarkText($background, $lightText: $euiColorGhost, $darkText: $euiColorInk) { - $lightContrast: contrastRatio($background, $lightText); - $darkContrast: contrastRatio($background, $darkText); - - @if ($lightContrast > $darkContrast) { - @return $lightText; - } @else { - @return $darkText; - } -} - -// Given a $foreground and a $background, make the $foreground AA accessibility by slightly -// adjusting it till the contrast is high enough -// By default it will compare against the page background color - -// ex: makeContrastColor($lightPink, #FFF) would continually shade the pink until -// it had higher than 4.5 contrast on a white background. -$euiContrastRatioText: 4.5; -@function makeHighContrastColor($foreground, $background: $euiPageBackgroundColor, $ratio: $euiContrastRatioText) { - $contrast: contrastRatio($foreground, $background); - - // Determine the lightness factor of the background color first to - // determine whether to shade or tint the foreground. - $brightness: lightness($background); - - $highContrastTextColor: $foreground; - - @while ($contrast < $ratio) { - @if ($brightness > 50) { - $highContrastTextColor: shade($highContrastTextColor, 5%); - } @else { - $highContrastTextColor: tint($highContrastTextColor, 5%); - } - - $contrast: contrastRatio($highContrastTextColor, $background); - - @if (lightness($highContrastTextColor) < 5) { - @warn 'High enough contrast could not be determined. Most likely your background color does not adjust for light mode.'; - @return $highContrastTextColor; - } - - @if (lightness($highContrastTextColor) > 95) { - @warn 'High enough contrast could not be determined. Most likely your background color does not adjust for dark mode.'; - @return $highContrastTextColor; - } - } - - @return $highContrastTextColor; -} - -// Graphics such as stand alone icons and pieces of a graph only need a minimum ratio of 3:1 with its background. -// Therefore, we can reuse the `makeHighContrastColor()` function but only attain a min contrast of 3.0. -// It is still recommended to use `makeHighContrastColor()` to attain a 4.5:1 ratio if the graphic is small or thinly stroked. -// https://www.w3.org/WAI/GL/low-vision-a11y-tf/wiki/Informational_Graphic_Contrast_(Minimum) -$euiContrastRatioGraphic: 3; -@function makeGraphicContrastColor($color, $background: $euiPageBackgroundColor) { - @return makeHighContrastColor($color, $background, $euiContrastRatioGraphic); -} - -// Disabled content only needs a contrast of at least 2 because there is no interaction available -$euiContrastRatioDisabled: 2; -@function makeDisabledContrastColor($color, $background: $euiPageBackgroundColor) { - @return makeHighContrastColor($color, $background, $euiContrastRatioDisabled); -} diff --git a/packages/eui-common/src/global_styling/functions/_index.scss b/packages/eui-common/src/global_styling/functions/_index.scss deleted file mode 100644 index de8260b2bba..00000000000 --- a/packages/eui-common/src/global_styling/functions/_index.scss +++ /dev/null @@ -1,5 +0,0 @@ -// Math needs to be first in the load order -@import 'math'; - -// Using math, we have functions to manipulate contrast / luminosity for accessibility -@import 'colors'; diff --git a/packages/eui-common/src/global_styling/functions/_math.scss b/packages/eui-common/src/global_styling/functions/_math.scss deleted file mode 100644 index cdec36f3e60..00000000000 --- a/packages/eui-common/src/global_styling/functions/_math.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'math_pow'; \ No newline at end of file diff --git a/packages/eui-common/src/global_styling/functions/_math_pow.scss b/packages/eui-common/src/global_styling/functions/_math_pow.scss deleted file mode 100644 index 2e2d784a845..00000000000 --- a/packages/eui-common/src/global_styling/functions/_math_pow.scss +++ /dev/null @@ -1,82 +0,0 @@ -/** -The MIT License (MIT) - -Copyright (c) 2015 strarsis https://github.com/strarsis/sass-math-pow - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - */ - -@function pow($number, $exp) { - $exp1: round($exp); - $result: powInt($number, $exp1); - - @if ($exp1 != $exp) { - $result: $result * mathExp(($exp - $exp1) * mathLn($number)); - } - - @return $result; -} - -@function powInt($number, $exp) { - @if $exp == 0 { - @return 1; - } @else if $exp < 0 { - @return 1 / powInt($number, -$exp); - } @else { - $e: floor($exp / 2); - $pow: pow($number, $e); - @if $e * 2 == $exp { - @return $pow * $pow; - } @else { - @return $pow * $pow * $number; - } - } -} - -@function mathExp($value) { - $item: 1; - $result: 1; - - @for $index from 1 to 100 { - $item: $item * $value / $index; - $result: $result + $item; - } - - @return $result; -} - -@function mathLn($value) { - $tenExp: 0; - $lnTen: 2.30258509; - - @while ($value > 1) { - $tenExp: $tenExp + 1; - $value: $value / 10; - } - - $item: -1; - $result: 0; - - @for $index from 1 to 100 { - $item: $item * (1 - $value); - $result: $result + $item / $index; - } - - @return $result + $tenExp * $lnTen; -} diff --git a/packages/eui-common/src/global_styling/functions/index.ts b/packages/eui-common/src/global_styling/functions/index.ts deleted file mode 100644 index 5b07f8b8473..00000000000 --- a/packages/eui-common/src/global_styling/functions/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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. - */ - -export * from './size'; diff --git a/packages/eui-common/src/global_styling/functions/size.ts b/packages/eui-common/src/global_styling/functions/size.ts deleted file mode 100644 index a96b5b85452..00000000000 --- a/packages/eui-common/src/global_styling/functions/size.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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. - */ - -/* TODO: move to a shared module package */ - -/** - * Calculates the `px` value based on a scale multiplier - * @param scale - The font scale multiplier - * * - * @param themeOrBase - Theme base value - * * - * @returns string - Rem unit aligned to baseline - */ - -export const sizeToPixel = - (scale: number = 1) => - (themeOrBase: number | { base: number; [key: string]: any }) => { - const base = - typeof themeOrBase === 'object' ? themeOrBase.base : themeOrBase; - return `${base * scale}px`; - }; diff --git a/packages/eui-common/src/global_styling/index.scss b/packages/eui-common/src/global_styling/index.scss deleted file mode 100644 index cc27e6b91a5..00000000000 --- a/packages/eui-common/src/global_styling/index.scss +++ /dev/null @@ -1,15 +0,0 @@ -// Core - -// Functions need to be first, since we use them in our variables and mixin definitions -@import 'functions/index'; - -// Mixins provide generic code expansion through helpers -@import 'mixins/index'; - -// Utility classes provide one-off selectors for common css problems -@import 'utility/index'; - -// The reset file has moved to global_styles.tsx - -// Customization of the React Date Picker -@import 'react_date_picker/index'; diff --git a/packages/eui-common/src/global_styling/mixins/_button.scss b/packages/eui-common/src/global_styling/mixins/_button.scss deleted file mode 100644 index 47c87b6e742..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_button.scss +++ /dev/null @@ -1,149 +0,0 @@ -// Provides a solid reset and base for handling sizing layout -// Does not include any visual styles -@mixin euiButtonBase { - display: inline-block; - appearance: none; - cursor: pointer; - height: $euiButtonHeight; - line-height: $euiButtonHeight; // prevents descenders from getting cut off - text-align: center; - white-space: nowrap; - max-width: 100%; - vertical-align: middle; -} - -// Adds the focus (and hover) animation for translating up 1px -@mixin euiButtonFocus { - @include euiCanAnimate { - transition: transform $euiAnimSpeedNormal ease-in-out, background-color $euiAnimSpeedNormal ease-in-out; - - &:hover:not(:disabled) { - transform: translateY(-1px); - } - - &:focus { - animation: euiButtonActive $euiAnimSpeedNormal $euiAnimSlightBounce; - } - - &:active:not(:disabled) { - transform: translateY(1px); - } - } -} - -// All of the button base styles including the base, focus, font, and initial styles -// Does not include individual alterations like color or sizes -@mixin euiButton { - @include euiButtonBase; - @include euiFont; - @include euiFontSize; - @include euiButtonFocus; - - font-weight: $euiButtonFontWeight; - text-decoration: none; - outline-offset: -1px; - - &:hover:not(:disabled), - &:focus { - text-decoration: underline; - } -} - -// Correctly lays out the contents of a button when using the proper dom elements of: -// -// 1. Apply margin to all but last item in the flex. -// 2. Margin gets flipped because of the row-reverse. -@mixin euiButtonContent($isReverse: false) { - height: 100%; - width: 100%; - vertical-align: middle; - - .euiButtonContent__icon, - .euiButtonContent__spinner { - flex-shrink: 0; // Ensures the icons/spinner don't scale down below their intended size - } - - @if ($isReverse) { - flex-direction: row-reverse; - - > * + * { - margin-inline-start: 0; // 1, 2 - margin-inline-end: $euiSizeS; // 1, 2 - } - } @else { - display: flex; - justify-content: center; - align-items: center; - - > * + * { - margin-inline-start: $euiSizeS; // 1 - } - } -} - -@mixin euiButtonContentDisabled { - pointer-events: auto; - cursor: not-allowed; - - &:hover, - &:focus, - &:focus-within { - text-decoration: none; - } - - .euiButtonContent__spinner { - border-color: euiLoadingSpinnerBorderColors(currentColor); - } -} - -/* - * Creates the Amsterdam style of button with a transparent background - */ -@mixin euiButtonDefaultStyle($color: 'primary', $includeStates: true, $transparency: $euiButtonDefaultTransparency) { - $backgroundColor: $color; - - @if (map-has-key($euiButtonTypes, $color)) { - $backgroundColor: map-get($euiButtonTypes, $color); - } - - $percentConversion: $transparency * 100%; - // This variable simulates the possibly darkest background the button could be on - // Simulates the 20% opaque color on top of the page background color - $backgroundColorSimulated: mix($euiPageBackgroundColor, $backgroundColor, $percentConversion); - // Then we can calculate the darkest text color needed - color: makeHighContrastColor($backgroundColor, $backgroundColorSimulated); - // But still use transparency - background-color: transparentize($backgroundColor, $transparency); - - @if ($includeStates) { - &:not([class*='isDisabled']) { - &:hover, - &:focus { - // Duplicated from inert state simply to override default theme - background-color: transparentize($backgroundColor, $transparency); - } - } - } -} - -/* - * Creates the Amsterdam style of fill button - */ -@mixin euiButtonFillStyle($color: 'primary') { - $backgroundColor: $color; - - @if (map-has-key($euiButtonTypes, $color)) { - $backgroundColor: map-get($euiButtonTypes, $color); - } - - background-color: $backgroundColor; - color: chooseLightOrDarkText($backgroundColor); -} - -// Keyframe animation declarations can be found in -// utility/animations.scss diff --git a/packages/eui-common/src/global_styling/mixins/_form.scss b/packages/eui-common/src/global_styling/mixins/_form.scss deleted file mode 100644 index 326a8491f87..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_form.scss +++ /dev/null @@ -1,273 +0,0 @@ -@mixin euiFormControlLayoutPadding($numOfIcons, $side: 'right', $compressed: false) { - $iconSize: $euiSize; - $iconPadding: $euiFormControlPadding; - $marginBetweenIcons: $euiFormControlPadding / 2; - - @if ($compressed) { - $iconPadding: $euiFormControlCompressedPadding; - } - - @if variable-exists(numOfIcons) == false { - @error '$numOfIcons:integer (1-3) must be provided to @mixin euiFormControlLayoutPadding().'; - } @else if $numOfIcons == 1 { - padding-#{$side}: $iconPadding + $iconSize + $iconPadding; - } @else if $numOfIcons == 2 { - padding-#{$side}: $iconPadding + $iconSize + $marginBetweenIcons + $iconSize + $iconPadding; - } @else if $numOfIcons == 3 { - padding-#{$side}: $iconPadding + $iconSize + $marginBetweenIcons + $iconSize + $marginBetweenIcons + $iconSize + $iconPadding; - } -} - -@mixin euiPlaceholderPerBrowser { - // stylelint-disable selector-no-vendor-prefix - // Each prefix must be its own content block - &::-webkit-input-placeholder { @content; opacity: 1; } - &::-moz-placeholder { @content; opacity: 1; } - &:-ms-input-placeholder { @content; opacity: 1; } - &:-moz-placeholder { @content; opacity: 1; } - &::placeholder { @content; opacity: 1; } -} - -@function euiFormControlGradient($color: $euiColorPrimary) { - @return linear-gradient(to top, - $color, - $color 2px, - transparent 2px, - transparent 100% - ); -} - -@mixin euiFormControlText { - @include euiFont; - font-size: $euiFontSizeS; - color: $euiTextColor; - - @include euiPlaceholderPerBrowser { - color: $euiFormControlPlaceholderText; - } -} - -@mixin euiFormControlSize( - $height: $euiFormControlHeight, - $includeAlternates: false -) { - // Default - max-width: $euiFormMaxWidth; - width: 100%; - height: $height; - - @if ($includeAlternates) { - &--fullWidth { - max-width: 100%; - } - - &--compressed { - height: $euiFormControlCompressedHeight; - } - - &--inGroup { - height: 100%; - } - } -} - -@mixin euiFormControlWithIcon($isIconOptional: false, $side: 'left', $compressed: false) { - @if ($isIconOptional) { - @at-root { - #{&}--withIcon { - @include euiFormControlLayoutPadding(1, $side, $compressed); - } - } - } @else { - @include euiFormControlLayoutPadding(1, $side, $compressed); - } -} - -@mixin euiFormControlIsLoading($isNextToIcon: false) { - @at-root { - #{&}-isLoading { - @if ($isNextToIcon) { - @include euiFormControlLayoutPadding(2); - } @else { - @include euiFormControlLayoutPadding(1); - } - } - - #{&}-isLoading#{&}--compressed { - @if ($isNextToIcon) { - @include euiFormControlLayoutPadding(2, $compressed: true); - } @else { - @include euiFormControlLayoutPadding(1, $compressed: true); - } - } - } -} - -// 1. Must supply both values to background-size or some browsers apply the single value to both directions - -@mixin euiFormControlDefaultShadow($borderOnly: false) { - background-color: $euiFormBackgroundColor; - background-repeat: no-repeat; - background-size: 0% 100%; // 1 - - @if ($borderOnly) { - box-shadow: inset 0 0 0 1px $euiFormBorderColor; - } @else { - box-shadow: - #{$euiFormControlBoxShadow}, - inset 0 0 0 1px $euiFormBorderColor; - } - - transition: - box-shadow $euiAnimSpeedFast ease-in, - background-image $euiAnimSpeedFast ease-in, - background-size $euiAnimSpeedFast ease-in, - background-color $euiAnimSpeedFast ease-in; - - // Fixes bug in Firefox where adding a transition to the background-color - // caused a flash of differently styled dropdown. - @supports (-moz-appearance: none) { - // List *must* be in the same order as the above. - transition-property: box-shadow, background-image, background-size; - } -} - -@mixin euiFormControlFocusStyle($borderOnly: false) { - background-color: tintOrShade($euiColorEmptyShade, 0%, 40%); - background-image: euiFormControlGradient(); - background-size: 100% 100%; // 1 - outline: none; // Blanket remove all outlines relying on our own bottom border - - @if ($borderOnly) { - box-shadow: inset 0 0 0 1px $euiFormBorderColor; - } @else { - box-shadow: inset 0 0 0 1px $euiFormBorderColor; - } -} - -@mixin euiFormControlInvalidStyle { - background-image: euiFormControlGradient($euiColorDanger); - background-size: 100%; -} - -@mixin euiFormControlDisabledTextStyle { - color: $euiFormControlDisabledColor; - -webkit-text-fill-color: $euiFormControlDisabledColor; // Required for Safari -} - -@mixin euiFormControlDisabledStyle { - @include euiFormControlDisabledTextStyle; - cursor: not-allowed; - background: $euiFormBackgroundDisabledColor; - box-shadow: inset 0 0 0 1px $euiFormBorderDisabledColor; - - @include euiPlaceholderPerBrowser { - color: $euiFormControlDisabledColor; - } -} - -@mixin euiFormControlReadOnlyStyle { - cursor: default; - color: $euiTextColor; - -webkit-text-fill-color: $euiTextColor; // Required for Safari - // Use transparency since there is no border and in case form is on a non-white background - background: $euiFormBackgroundReadOnlyColor; - border-color: transparent; - box-shadow: inset 0 0 0 1px $euiFormBorderDisabledColor; -} - -// 2. Override invalid state with focus state. - -@mixin euiFormControlStyle($borderOnly: false, $includeStates: true, $includeSizes: true) { - @include euiFormControlSize($includeAlternates: $includeSizes); - @include euiFormControlDefaultShadow; - @include euiFormControlText; - - border: none; - border-radius: $euiFormControlBorderRadius; - padding: $euiFormControlPadding; - - @if ($includeStates) { - &:invalid { // 2 - @include euiFormControlInvalidStyle; - } - - &:focus { // 2 - @include euiFormControlFocusStyle; - } - - &:disabled { - @include euiFormControlDisabledStyle; - } - - &[readOnly] { - @include euiFormControlReadOnlyStyle; - } - - // Needs to be set for autofill - &:-webkit-autofill { - -webkit-text-fill-color: lightOrDarkTheme($euiColorDarkestShade, $euiColorLightShade); - - ~ .euiFormControlLayoutIcons { - color: lightOrDarkTheme($euiColorDarkestShade, $euiColorLightShade); - } - } - } - - @if ($includeSizes) { - &--compressed { - @include euiFormControlStyleCompressed($borderOnly, $includeStates); - } - - &--inGroup { - // stylelint-disable-next-line declaration-no-important - box-shadow: none !important; - border-radius: 0; - } - } -} - -@mixin euiFormControlStyleCompressed($borderOnly: false, $includeStates: true) { - @include euiFormControlDefaultShadow($borderOnly: true); - padding: $euiFormControlCompressedPadding; - border-radius: $euiFormControlCompressedBorderRadius; - - @if ($includeStates) { - &:invalid { // 2 - @include euiFormControlInvalidStyle; - } - - &:focus { // 2 - @include euiFormControlFocusStyle($borderOnly: true); - } - - &:disabled { - @include euiFormControlDisabledStyle; - } - - &[readOnly] { - @include euiFormControlReadOnlyStyle; - } - } -} - -@mixin euiHiddenSelectableInput { - position: absolute; - // stylelint-disable-next-line declaration-no-important - opacity: 0 !important; // Make sure it's still hidden when :disabled - width: 100%; - height: 100%; - cursor: pointer; -} - -// Adjusts form controls border radius -@mixin euiFormControlSideBorderRadius($borderRadius, $side, $internal: false) { - @if $internal == true { - $borderRadius: $borderRadius - 1; - } - @if $side == 'left' { - border-radius: $borderRadius 0 0 $borderRadius; - } @else if $side == 'right' { - border-radius: 0 $borderRadius $borderRadius 0; - } -} diff --git a/packages/eui-common/src/global_styling/mixins/_helpers.scss b/packages/eui-common/src/global_styling/mixins/_helpers.scss deleted file mode 100644 index 00688ef63ef..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_helpers.scss +++ /dev/null @@ -1,126 +0,0 @@ -// Helper mixins - -// Set scroll bar appearance on Chrome (and firefox). -@mixin euiScrollBar($thumbColor: $euiColorDarkShade, $trackBackgroundColor: transparent, $size: 'thin') { - // Firefox's scrollbar coloring cascades, but the sizing does not, - // so it's being added to this mixin for allowing support wherever custom scrollbars are - scrollbar-color: transparentize($thumbColor, .5) $trackBackgroundColor; // Firefox support - - @if ($size == 'thin') { - scrollbar-width: thin; - } - - // stylelint-disable selector-no-vendor-prefix - &::-webkit-scrollbar { - width: $euiScrollBar; - height: $euiScrollBar; - } - - &::-webkit-scrollbar-thumb { - background-color: transparentize($thumbColor, .5); - background-clip: content-box; - border-radius: $euiScrollBar; - - @if ($size == 'thin') { - border: $euiScrollBarCornerThin solid $trackBackgroundColor; - } @else { - border: $euiScrollBarCorner solid $trackBackgroundColor; - } - } - - &::-webkit-scrollbar-corner, - &::-webkit-scrollbar-track { - background-color: $trackBackgroundColor; - } -} - -/** - * 1. Focus rings shouldn't be visible on scrollable regions, but a11y requires them to be focusable. - * Browser's supporting `:focus-visible` will still show outline on keyboard focus only. - * Others like Safari, won't show anything at all. - * 2. Force the `:focus-visible` when the `tabindex=0` (is tabbable) - */ - -// Just overflow and scrollbars -@mixin euiYScroll { - @include euiScrollBar; - height: 100%; - overflow-y: auto; - overflow-x: hidden; - - &:focus { - outline: none; /* 1 */ - } - - &[tabindex='0']:focus:focus-visible { - outline-style: auto; /* 2 */ - } -} - -@mixin euiXScroll { - @include euiScrollBar; - overflow-x: auto; - - &:focus { - outline: none; /* 1 */ - } - - &[tabindex='0']:focus:focus-visible { - outline-style: auto; /* 2 */ - } -} - -// The full overflow with shadow -@mixin euiYScrollWithShadows { - @include euiYScroll; - @include euiOverflowShadow('y'); -} - -@mixin euiXScrollWithShadows { - @include euiXScroll; - @include euiOverflowShadow('x'); -} - -/** - * For quickly applying a full-height element whether using flex or not - */ -@mixin euiFullHeight { - height: 100%; - flex: 1 1 auto; - overflow: hidden; -} - -// Hiding elements offscreen to only be read by screen reader -// See https://github.com/elastic/eui/pull/5130 and https://github.com/elastic/eui/pull/5152 for more info -@mixin euiScreenReaderOnly { - // Take the element out of the layout - position: absolute; - // Keep it vertically inline - top: auto; - // Chrome requires a left value, and Selenium (used by Kibana's FTR) requires an off-screen position for its .getVisibleText() to not register SR-only text - left: -10000px; - // The element must have a size (for some screen readers) - width: 1px; - height: 1px; - // But reduce the visible size to nothing - clip: rect(0 0 0 0); - clip-path: inset(50%); - // And ensure no overflows occur - overflow: hidden; - // Chrome requires the negative margin to not cause overflows of parent containers - margin: -1px; -} - -// Doesn't have reduced motion turned on -@mixin euiCanAnimate { - @media screen and (prefers-reduced-motion: no-preference) { - @content; - } -} - -// Does have reduced motion turned on -@mixin euiCantAnimate { - @media screen and (prefers-reduced-motion: reduce) { - @content; - } -} diff --git a/packages/eui-common/src/global_styling/mixins/_index.scss b/packages/eui-common/src/global_styling/mixins/_index.scss deleted file mode 100644 index 7d0cba8a92e..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_index.scss +++ /dev/null @@ -1,14 +0,0 @@ -@import 'responsive'; -@import 'shadow'; -@import 'size'; -@import 'typography'; -@import 'helpers'; -@import 'states'; - -@import 'button'; -@import 'form'; -@import 'loading'; -@import 'link'; -@import 'panel'; -@import 'range'; -@import 'tool_tip'; diff --git a/packages/eui-common/src/global_styling/mixins/_link.scss b/packages/eui-common/src/global_styling/mixins/_link.scss deleted file mode 100644 index 98dac59b9cc..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_link.scss +++ /dev/null @@ -1,11 +0,0 @@ -@mixin euiLink { - text-align: left; - - &:hover { - text-decoration: underline; - } - - &:focus { - text-decoration: underline; - } -} diff --git a/packages/eui-common/src/global_styling/mixins/_loading.scss b/packages/eui-common/src/global_styling/mixins/_loading.scss deleted file mode 100644 index 0f72a8433f7..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_loading.scss +++ /dev/null @@ -1,6 +0,0 @@ -@function euiLoadingSpinnerBorderColors( - $main: $euiColorLightShade, - $highlight: $euiColorPrimary -) { - @return $highlight $main $main $main; -} diff --git a/packages/eui-common/src/global_styling/mixins/_panel.scss b/packages/eui-common/src/global_styling/mixins/_panel.scss deleted file mode 100644 index 4eb0a5fb55a..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_panel.scss +++ /dev/null @@ -1,55 +0,0 @@ -@mixin euiPanel($selector) { - @if variable-exists(selector) == false { - @error 'A $selector must be provided to @mixin euiPanel().'; - } @else { - #{$selector} { - flex-grow: 1; - - &#{$selector}--flexGrowZero { - flex-grow: 0; - } - - &#{$selector}--hasShadow { - @include euiBottomShadowMedium; - } - - &#{$selector}--hasBorder { - border: $euiBorderThin; - box-shadow: none; - } - - &#{$selector}--isClickable { - // transition the shadow - transition: all $euiAnimSpeedFast $euiAnimSlightResistance; - - &:enabled { // This is a good selector for buttons since it doesn't exist on divs - // in case of button wrapper which inherently is inline-block and no width - display: block; - width: 100%; - text-align: left; - } - - &:hover, - &:focus { - @include euiBottomShadow; - transform: translateY(-2px); - cursor: pointer; - } - } - - // Border Radii - @each $modifier, $amount in $euiPanelBorderRadiusModifiers { - &#{$selector}--#{$modifier} { - border-radius: $amount; - } - } - - // Background colors - @each $modifier, $amount in $euiPanelBackgroundColorModifiers { - &#{$selector}--#{$modifier} { - background-color: $amount; - } - } - } - } -} diff --git a/packages/eui-common/src/global_styling/mixins/_range.scss b/packages/eui-common/src/global_styling/mixins/_range.scss deleted file mode 100644 index ec47e39e2d6..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_range.scss +++ /dev/null @@ -1,62 +0,0 @@ -/* -The CSS in JS version of this file lives in: - - src/components/form/range/range.styles.ts - -The following files still use the Sass version: - - src/themes/amsterdam/overrides/_color_stops.scss - - src/themes/amsterdam/overrides/_hue.scss -*/ - -@mixin euiRangeTrackSize($compressed: false) { - height: $euiRangeTrackHeight; - width: $euiRangeTrackWidth; - - @if ($compressed) { - height: $euiRangeTrackCompressedHeight; - } -} - -@mixin euiRangeTrackPerBrowser { - &::-webkit-slider-runnable-track { @content; } - &::-moz-range-track { @content; } - &::-ms-fill-lower { @content; } - &::-ms-fill-upper { @content; } -} - -@mixin euiRangeThumbBorder { - border: 2px solid $euiRangeThumbBorderColor; -} - -@mixin euiRangeThumbBoxShadow { - box-shadow: - 0 0 0 1px $euiRangeThumbBorderColor, - 0 2px 2px -1px rgba($euiShadowColor, .2), - 0 1px 5px -2px rgba($euiShadowColor, .2); -} - -@mixin euiRangeThumbFocusBoxShadow { - box-shadow: 0 0 0 2px $euiFocusRingColor; -} - -@mixin euiRangeThumbStyle { - @include euiRangeThumbBoxShadow; - @include euiRangeThumbBorder; - cursor: pointer; - background-color: $euiRangeThumbBackgroundColor; - padding: 0; - height: $euiRangeThumbHeight; - width: $euiRangeThumbWidth; - box-sizing: border-box; // required for firefox or the border makes the width and height to increase -} - -@mixin euiRangeThumbPerBrowser { - &::-webkit-slider-thumb { @content; } - &::-moz-range-thumb { @content; } - &::-ms-thumb { @content; } -} - -@mixin euiRangeThumbFocus { - @include euiRangeThumbBorder; - @include euiRangeThumbFocusBoxShadow; - background-color: $euiColorPrimary; -} diff --git a/packages/eui-common/src/global_styling/mixins/_responsive.scss b/packages/eui-common/src/global_styling/mixins/_responsive.scss deleted file mode 100644 index 0fa3a9b08a8..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_responsive.scss +++ /dev/null @@ -1,44 +0,0 @@ -// A sem-complicated mixin for breakpoints, that takes any number of -// named breakpoints that exists in $euiBreakpoints. - -@mixin euiBreakpoint($sizes...) { - // Loop through each size parameter - @each $size in $sizes { - // Store the location of the size in the list to check against - $index: index($euiBreakpointKeys, $size); - - // Check to make sure it exists in the allowed breakpoint names - @if ( $index ) { - - // Set the min size to the value of the size - $minSize: map-get($euiBreakpoints, $size); - - // If it is the last item, don't give it a max-width - @if ( $index == length($euiBreakpointKeys) ) { - @media only screen and (min-width: $minSize) { - @content; - } - // If it's not the last item, add a max-width - } @else { - - // Set the max size to the value of the next size (-1px as to not overlap) - $maxSize: map-get($euiBreakpoints, nth($euiBreakpointKeys, $index + 1)) - 1px; - - // If it's the the first item, don't set a min-width - @if ( $index == 1 ) { - @media only screen and (max-width: $maxSize) { - @content; - } - // Otherwise it should have a min and max width - } @else { - @media only screen and (min-width: $minSize) and (max-width: $maxSize) { - @content; - } - } - } - // If it's not a known breakpoint, throw a warning - } @else { - @warn "euiBreakpoint(): '#{$size}' is not a valid size in $euiBreakpoints. Accepted values are '#{$euiBreakpointKeys}'"; - } - } -} diff --git a/packages/eui-common/src/global_styling/mixins/_shadow.scss b/packages/eui-common/src/global_styling/mixins/_shadow.scss deleted file mode 100644 index 1bc64eb085b..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_shadow.scss +++ /dev/null @@ -1,108 +0,0 @@ -@function shadowOpacity($opacity) { - @if (lightness($euiTextColor) < 50) { - @return $opacity * 1; - } @else { - @return $opacity * 2.5; - } -} - -@mixin euiSlightShadow($color: $euiShadowColor) { - box-shadow: - 0 .8px .8px rgba($color, shadowOpacity(.04)), - 0 2.3px 2px rgba($color, shadowOpacity(.03)); -} - -@mixin euiBottomShadowSmall($color: $euiShadowColor) { - box-shadow: - 0 .7px 1.4px rgba($color, shadowOpacity(.07)), - 0 1.9px 4px rgba($color, shadowOpacity(.05)), - 0 4.5px 10px rgba($color, shadowOpacity(.05)); -} - -@mixin euiBottomShadowMedium($color: $euiShadowColor) { - box-shadow: - 0 .9px 4px -1px rgba($color, shadowOpacity(.08)), - 0 2.6px 8px -1px rgba($color, shadowOpacity(.06)), - 0 5.7px 12px -1px rgba($color, shadowOpacity(.05)), - 0 15px 15px -1px rgba($color, shadowOpacity(.04)); -} - -// Similar to shadow medium but without the bottom depth. Useful for popovers -// that drop UP rather than DOWN. -@mixin euiBottomShadowFlat($color: $euiShadowColor) { - box-shadow: - 0 0 .8px rgba($color, shadowOpacity(.06)), - 0 0 2px rgba($color, shadowOpacity(.04)), - 0 0 5px rgba($color, shadowOpacity(.04)), - 0 0 17px rgba($color, shadowOpacity(.03)); -} - -@mixin euiBottomShadow($color: $euiShadowColor) { - box-shadow: - 0 1px 5px rgba($color, shadowOpacity(.1)), - 0 3.6px 13px rgba($color, shadowOpacity(.07)), - 0 8.4px 23px rgba($color, shadowOpacity(.06)), - 0 23px 35px rgba($color, shadowOpacity(.05)); -} - -@mixin euiBottomShadowLarge( - $color: $euiShadowColor, - $opacity: 0, - $reverse: false -) { - @if ($reverse) { - box-shadow: - 0 -2.7px 9px rgba($color, shadowOpacity(.13)), - 0 -9.4px 24px rgba($color, shadowOpacity(.09)), - 0 -21.8px 43px rgba($color, shadowOpacity(.08)); - } @else { - box-shadow: - 0 2.7px 9px rgba($color, shadowOpacity(.13)), - 0 9.4px 24px rgba($color, shadowOpacity(.09)), - 0 21.8px 43px rgba($color, shadowOpacity(.08)); - } -} - -@mixin euiSlightShadowHover($color: $euiShadowColor) { - box-shadow: - 0 1px 5px rgba($color, shadowOpacity(.1)), - 0 3.6px 13px rgba($color, shadowOpacity(.07)), - 0 8.4px 23px rgba($color, shadowOpacity(.06)), - 0 23px 35px rgba($color, shadowOpacity(.05)); -} - -// stylelint-disable color-named -@mixin euiOverflowShadow($direction: 'y', $side: 'both') { - $hideHeight: $euiScrollBarCornerThin * 1.25; - $gradient: null; - $gradientStart: - transparentize(red, .9) 0%, - transparentize(red, 0) $hideHeight; - $gradientEnd: - transparentize(red, 0) calc(100% - #{$hideHeight}), - transparentize(red, .9) 100%; - @if ($side == 'both' or $side == 'start' or $side == 'end') { - @if ($side == 'both') { - $gradient: $gradientStart, $gradientEnd; - } @else if ($side == 'start') { - $gradient: $gradientStart; - } @else { - $gradient: $gradientEnd; - } - } @else { - @warn "euiOverflowShadow() expects side to be 'both', 'start' or 'end' but got '#{$side}'"; - } - - @if ($direction == 'y') { - mask-image: linear-gradient(to bottom, #{$gradient}); - } @else if ($direction == 'x') { - mask-image: linear-gradient(to right, #{$gradient}); - } @else { - @warn "euiOverflowShadow() expects direction to be 'y' or 'x' but got '#{$direction}'"; - } - - // Chrome+Edge has a very bizarre edge case bug where `mask-image` stops working - // This workaround forces a stacking context on the scrolling container, which - // hopefully addresses the bug. @see https://github.com/elastic/eui/pull/7855 - transform: translateZ(0); -} diff --git a/packages/eui-common/src/global_styling/mixins/_size.scss b/packages/eui-common/src/global_styling/mixins/_size.scss deleted file mode 100644 index 809dc870bf8..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_size.scss +++ /dev/null @@ -1,4 +0,0 @@ -@mixin size($size) { - width: $size; - height: $size; -} diff --git a/packages/eui-common/src/global_styling/mixins/_states.scss b/packages/eui-common/src/global_styling/mixins/_states.scss deleted file mode 100644 index a2d1bc83aef..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_states.scss +++ /dev/null @@ -1,50 +0,0 @@ -@mixin euiFocusRing($size: 'small', $amsterdamOnlyProp: null) { - @if $size == 'large' { - // It's always OK to use the focus animation. This will take precedence over times we turn it off individually like EuiButtonEmpty - // stylelint-disable-next-line declaration-no-important - animation: $euiAnimSpeedSlow $euiAnimSlightResistance 1 normal forwards focusRingAnimateLarge !important; - } @else { - // stylelint-disable-next-line declaration-no-important - animation: $euiAnimSpeedSlow $euiAnimSlightResistance 1 normal forwards focusRingAnimate !important; - } -} - -// Keyframe animation declarations can be found in -// utility/animations.scss - -@mixin euiFocusBackground($color: $euiColorPrimary) { - background-color: tintOrShade($euiColorPrimary, ((1 - $euiFocusTransparency) * 100%), ((1 - $euiFocusTransparency) * 100%)); -} - -@mixin euiHoverState { - cursor: pointer; - text-decoration: underline; -} - -@mixin euiFocusState($color: $euiColorPrimary) { - @include euiHoverState; - @include euiFocusBackground($color); -} - -@mixin euiDisabledState($color: $euiButtonColorDisabledText) { - cursor: not-allowed; - text-decoration: none; - - @if ($color) { - color: $color; - } -} - -@mixin euiInteractiveStates($focusColor: $euiColorPrimary, $disabledColor: $euiButtonColorDisabledText) { - &:hover { - @include euiHoverState; - } - - &:focus { - @include euiFocusState($focusColor); - } - - &:disabled { - @include euiDisabledState($disabledColor); - } -} diff --git a/packages/eui-common/src/global_styling/mixins/_tool_tip.scss b/packages/eui-common/src/global_styling/mixins/_tool_tip.scss deleted file mode 100644 index d8feb0d4258..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_tool_tip.scss +++ /dev/null @@ -1,25 +0,0 @@ -@mixin euiToolTipStyle($size: null) { - @include euiBottomShadow($color: $euiColorInk); - - $euiTooltipBackgroundColor: tintOrShade($euiColorFullShade, 25%, 100%) !default; - $euiTooltipBorderColor: tintOrShade($euiColorFullShade, 35%, 80%) !default; - - border-radius: $euiBorderRadius; - background-color: $euiTooltipBackgroundColor; - color: $euiColorGhost; - z-index: $euiZLevel9; - max-width: 256px; - overflow-wrap: break-word; - padding: $euiSizeS; - - .euiHorizontalRule { - background-color: $euiTooltipBorderColor; - } -} - -@mixin euiToolTipTitle { - font-weight: $euiFontWeightBold; - border-bottom: solid $euiBorderWidthThin $euiTooltipBorderColor; - padding-bottom: $euiSizeXS; - margin-bottom: $euiSizeXS; -} \ No newline at end of file diff --git a/packages/eui-common/src/global_styling/mixins/_typography.scss b/packages/eui-common/src/global_styling/mixins/_typography.scss deleted file mode 100644 index 7090f0e2371..00000000000 --- a/packages/eui-common/src/global_styling/mixins/_typography.scss +++ /dev/null @@ -1,167 +0,0 @@ -// stylelint-disable property-no-vendor-prefix -// stylelint-disable declaration-no-important - -@function fontSizeToRemOrEm($size, $sizingMethod: 'rem') { - @if ($sizingMethod == 'rem') { - @return #{$size / $euiFontSize}rem; - } @else if ($sizingMethod == 'em') { - @return #{$size / $euiFontSize}em; - } -} - -// It can also be applied to calculate paddings -@function marginToRemOrEm($elementSize, $elementFontSize, $sizingMethod: 'rem') { - @if ($sizingMethod == 'rem') { - @return #{$elementSize / $euiFontSize}rem; - } @else if ($sizingMethod == 'em') { - @return #{$elementSize / $elementFontSize}em; - } -} - -// Spit out rem and px -@mixin fontSize($size: $euiFontSize, $sizingMethod: 'rem') { - @if ($sizingMethod == 'rem') { - font-size: $size; - font-size: fontSizeToRemOrEm($size, 'rem'); - } @else if ($sizingMethod == 'em') { - font-size: fontSizeToRemOrEm($size, 'em'); - } -} - -@mixin lineHeightFromBaseline($multiplier: 3) { - line-height: lineHeightFromBaseline($multiplier); -} - -// Some mixins that help us deal with browser scaling of text more consistently. -// Essentially, fonts across eui should scale against the root html element, not -// against parent inheritance. - -// Our base fonts - -@mixin euiFont { - font-family: $euiFontFamily; - font-weight: $euiFontWeightRegular; - letter-spacing: -.005em; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - font-kerning: normal; -} - -@mixin euiCodeFont { - font-family: $euiCodeFontFamily; - letter-spacing: normal; -} - -@mixin euiText { - color: $euiTextColor; - font-weight: $euiFontWeightRegular; -} - -@mixin euiTitle($size: 'm') { - @include euiTextBreakWord; - color: $euiTitleColor; - - @if (map-has-key($euiTitles, $size)) { - @each $property, $value in map-get($euiTitles, $size) { - @if ($property == 'font-size') { - @include fontSize($value); - } @else { - #{$property}: $value; - } - } - } @else { - @include fontSize($size); - @include lineHeightFromBaseline(3); - } -} - -// Font sizing extends, using rem mixin - -@mixin euiFontSizeXS { - @include fontSize($euiFontSizeXS); - line-height: $euiLineHeight; -} - -@mixin euiFontSizeS { - @include fontSize($euiFontSizeS); - line-height: $euiLineHeight; -} - -@mixin euiFontSize { - @include fontSize($euiFontSize); - line-height: $euiLineHeight; -} - -@mixin euiFontSizeM { - @include fontSize($euiFontSizeM); - line-height: $euiLineHeight; -} - -@mixin euiFontSizeL { - @include fontSize($euiFontSizeL); - line-height: $euiLineHeight; -} - -@mixin euiFontSizeXL { - @each $property, $value in map-get($euiTitles, 'm') { - @if ($property == 'font-size') { - @include fontSize($value); - } @else { - #{$property}: $value; - } - } - line-height: 1.25; -} - -@mixin euiFontSizeXXL { - @each $property, $value in map-get($euiTitles, 'l') { - @if ($property == 'font-size') { - @include fontSize($value); - } @else { - #{$property}: $value; - } - } - line-height: 1.25; -} - -@mixin euiTextBreakWord { - // https://css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/ - overflow-wrap: break-word !important; // makes sure the long string will wrap and not bust out of the container - word-break: break-word; -} - -/** - * Text truncation - * - * Prevent text from wrapping onto multiple lines, and truncate with an ellipsis. - * - * 1. Ensure that the node has a maximum width after which truncation can occur. - */ -@mixin euiTextTruncate { - max-width: 100%; // 1 - overflow: hidden !important; - text-overflow: ellipsis !important; - white-space: nowrap !important; -} - -@mixin euiNumberFormat { - font-feature-settings: $euiFontFeatureSettings, 'tnum' 1; // Fixed-width numbers for tabular data -} - -/** - * Text weight shifting - * - * When changing the font-weight based the state of the component - * this mixin will ensure that the sizing is dependent on the boldest - * weight so it doesn't shifter sibling content. - */ -@mixin euiTextShift($fontWeight: $euiFontWeightBold, $attr: 'data-text') { - &::after { - display: block; - content: attr(#{$attr}); - font-weight: $fontWeight; - height: 0; - overflow: hidden; - visibility: hidden; - } -} diff --git a/packages/eui-common/src/global_styling/react_date_picker/_date_picker.scss b/packages/eui-common/src/global_styling/react_date_picker/_date_picker.scss deleted file mode 100644 index 84208a3a648..00000000000 --- a/packages/eui-common/src/global_styling/react_date_picker/_date_picker.scss +++ /dev/null @@ -1,772 +0,0 @@ -/* This file is a heavy retheme of react-datepicker's Sass as of v1.4.0 -** https://github.com/Hacker0x01/react-datepicker -** -** In places where features were disabled, I've commented out the original Sass -** selectors rather than removing it so we can better understand what's changed. -** Commented out selectors that don't have properties indicate that we are not -** using those dom elements for styling of any kind. For example, react-datepicker -** has lots of pointer arrows attached to its popovers, but we choose not to render -** then in any way. -** -** Similarly, you will also find several times where we use display: none to -** completely remove extraneous UI (they had some overly obvious legends for example). -*/ - - -// Because we don't have control over react-datepicker's dom we use SVG URIs for the navigation arrows. -// There is one for light and dark. -@mixin datePickerArrow { - background-position: center; - @if (lightness($euiColorEmptyShade) > 50) { - background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiI+ICA8ZGVmcz4gICAgPHBhdGggaWQ9ImFycm93X2Rvd24tYSIgZD0iTTEzLjA2ODg1MDgsNS4xNTcyNTAzOCBMOC4zODQyMzk3NSw5Ljc2ODI3NDI4IEM4LjE3MDU0NDE1LDkuOTc4NjEzMDggNy44Mjk5OTIxNCw5Ljk3OTE0MDk1IDcuNjE1NzYwMjUsOS43NjgyNzQyOCBMMi45MzExNDkxNSw1LjE1NzI1MDM4IEMyLjcxODEzNTksNC45NDc1ODMyMSAyLjM3Mjc3MzE5LDQuOTQ3NTgzMjEgMi4xNTk3NTk5NCw1LjE1NzI1MDM4IEMxLjk0Njc0NjY5LDUuMzY2OTE3NTYgMS45NDY3NDY2OSw1LjcwNjg1NTIyIDIuMTU5NzU5OTQsNS45MTY1MjI0IEw2Ljg0NDM3MTA0LDEwLjUyNzU0NjMgQzcuNDg1MTc0MjQsMTEuMTU4MjgzNiA4LjUxNjQ0OTc5LDExLjE1NjY4NTEgOS4xNTU2Mjg5NiwxMC41Mjc1NDYzIEwxMy44NDAyNDAxLDUuOTE2NTIyNCBDMTQuMDUzMjUzMyw1LjcwNjg1NTIyIDE0LjA1MzI1MzMsNS4zNjY5MTc1NiAxMy44NDAyNDAxLDUuMTU3MjUwMzggQzEzLjYyNzIyNjgsNC45NDc1ODMyMSAxMy4yODE4NjQxLDQuOTQ3NTgzMjEgMTMuMDY4ODUwOCw1LjE1NzI1MDM4IFoiLz4gIDwvZGVmcz4gIDxnIGZpbGwtcnVsZT0iZXZlbm9kZCI+ICAgIDx1c2UgZmlsbC1ydWxlPSJub256ZXJvIiB4bGluazpocmVmPSIjYXJyb3dfZG93bi1hIi8+ICA8L2c+PC9zdmc+); - } @else { - background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiI+ICA8ZGVmcz4gICAgPHBhdGggaWQ9ImRvd25hcnJvd3doaXRlLWEiIGQ9Ik0xMy4wNjg4NTA4LDUuMTU3MjUwMzggTDguMzg0MjM5NzUsOS43NjgyNzQyOCBDOC4xNzA1NDQxNSw5Ljk3ODYxMzA4IDcuODI5OTkyMTQsOS45NzkxNDA5NSA3LjYxNTc2MDI1LDkuNzY4Mjc0MjggTDIuOTMxMTQ5MTUsNS4xNTcyNTAzOCBDMi43MTgxMzU5LDQuOTQ3NTgzMjEgMi4zNzI3NzMxOSw0Ljk0NzU4MzIxIDIuMTU5NzU5OTQsNS4xNTcyNTAzOCBDMS45NDY3NDY2OSw1LjM2NjkxNzU2IDEuOTQ2NzQ2NjksNS43MDY4NTUyMiAyLjE1OTc1OTk0LDUuOTE2NTIyNCBMNi44NDQzNzEwNCwxMC41Mjc1NDYzIEM3LjQ4NTE3NDI0LDExLjE1ODI4MzYgOC41MTY0NDk3OSwxMS4xNTY2ODUxIDkuMTU1NjI4OTYsMTAuNTI3NTQ2MyBMMTMuODQwMjQwMSw1LjkxNjUyMjQgQzE0LjA1MzI1MzMsNS43MDY4NTUyMiAxNC4wNTMyNTMzLDUuMzY2OTE3NTYgMTMuODQwMjQwMSw1LjE1NzI1MDM4IEMxMy42MjcyMjY4LDQuOTQ3NTgzMjEgMTMuMjgxODY0MSw0Ljk0NzU4MzIxIDEzLjA2ODg1MDgsNS4xNTcyNTAzOCBaIi8+ICA8L2RlZnM+ICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICA8dXNlIGZpbGw9IiNGRkYiIGZpbGwtcnVsZT0ibm9uemVybyIgeGxpbms6aHJlZj0iI2Rvd25hcnJvd3doaXRlLWEiLz4gIDwvZz48L3N2Zz4=); - } -} - -// The only "new" css in this component is a wrapper class for dealing with shadows. -// This is mostly here so that we can provide an inline version that doesn't have the -// shadows and depth. -.euiDatePicker { - .euiFormControlLayout { - height: auto; - } - - &.euiDatePicker--shadow { - .react-datepicker-popper { - @include euiBottomShadowMedium; - - border: $euiBorderThin; - background-color: $euiColorEmptyShade; - border-radius: 0 0 $euiBorderRadius $euiBorderRadius; - } - - // If the shadow is on, and it is inline, we need to put the shadow on the datepicker - // itself rather than the popper. - &.euiDatePicker--inline { - .react-datepicker { - @include euiBottomShadowMedium; - - border: $euiBorderThin; - background-color: $euiColorEmptyShade; - border-radius: $euiBorderRadius; - } - } - } -} - -// .react-datepicker-wrapper { -// } - -.react-datepicker { - @include euiFont; - font-size: $euiFontSizeXS; - color: $euiColorFullShade; - display: flex; - position: relative; - border-radius: $euiBorderRadius; -} - -// When in time only mode we make the dropdown look more like the combo box styling. -.react-datepicker--time-only { - - .react-datepicker__time-container { - - .react-datepicker__time { - - .react-datepicker__time-box { - width: 100%; - - .react-datepicker__time-list li.react-datepicker__time-list-item { - font-size: $euiFontSizeS; - text-align: left; - padding-left: $euiSizeXL + $euiSizeXS; - padding-right: $euiSizeXL + $euiSizeXS; - color: $euiTextColor; - - &.react-datepicker__time-list-item--selected { - color: $euiColorGhost; - } - - &.react-datepicker__time-list-item--disabled{ - color: $euiColorDisabledText - } - } - } - } - } - - - .react-datepicker__time-container { - border-left: 0; - } - - // .react-datepicker__triangle { - // } - // .react-datepicker__time { - // } - // .react-datepicker__time-box { - // } -} - -// .react-datepicker__triangle { -// } - -.euiDatePicker.euiDatePicker--shadow .react-datepicker-popper { - z-index: $euiZContentMenu; - animation: euiAnimFadeIn $euiAnimSpeedFast ease-in; - - &[data-placement^="bottom"] { - - // .react-datepicker__triangle { - // } - } - - &[data-placement^="top"] { - @include euiBottomShadowFlat; - - border-radius: $euiBorderRadius $euiBorderRadius 0 0; - - // .react-datepicker__triangle { - // } - } - - &[data-placement^="right"] { - margin-left: 0; - - // .react-datepicker__triangle { - // } - } - - &[data-placement^="left"] { - margin-right: 0; - - // .react-datepicker__triangle { - // } - } -} - -.react-datepicker__header { - text-align: center; - border-top-left-radius: $euiBorderRadius; - border-top-right-radius: $euiBorderRadius; - - &--time { - display: none; - } -} - -.react-datepicker__header__dropdown { - padding: $euiSize 0 $euiSizeS 0; -} - -.react-datepicker__year-dropdown-container--select, -.react-datepicker__month-dropdown-container--select, -.react-datepicker__month-year-dropdown-container--select, -.react-datepicker__year-dropdown-container--scroll, -.react-datepicker__month-dropdown-container--scroll, -.react-datepicker__month-year-dropdown-container--scroll { - display: inline-block; - margin: 0 $euiSizeXS; -} - -.react-datepicker__current-month, -.react-datepicker-time__header { - display: none; -} - -.react-datepicker-time__header { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.react-datepicker__navigation { - cursor: pointer; - position: absolute; - // Pixel pushing because these are icons against text - top: $euiSize + ($euiSizeXS / 2); - width: 0; - padding: 0; - z-index: 1; - text-indent: -999em; - overflow: hidden; - - &--previous { - @include datePickerArrow; - left: $euiSize + $euiSizeXS; - height: $euiSize; - width: $euiSize; - transform: rotate(90deg); - transition: transform $euiAnimSpeedExtraFast ease-in-out; - - &:hover, &:focus { - border-radius: $euiBorderRadius; - transform: scale(1.2) rotate(90deg); - } - - &:hover { - background-color: $euiColorLightestShade; - box-shadow: 0 0 0 ($euiSizeXS / 2) $euiColorLightestShade; - } - - &:focus { - background-color: $euiFocusBackgroundColor; - box-shadow: 0 0 0 ($euiSizeXS / 2) $euiFocusBackgroundColor; - } - - &--disabled, - &--disabled:hover { - cursor: not-allowed ; - opacity: .2; - } - } - - &--next { - @include datePickerArrow; - // Pixel value because of some padding on the icon - right: 20px; - height: $euiSize; - width: $euiSize; - transform: rotate(-90deg); - - &--with-time:not(&--with-today-button) { - // This a pixel value against the width of the cal. It needs - // to be left because the timepicker adds more width - left: 248px; - } - - &:hover, &:focus { - border-radius: $euiBorderRadius; - transform: scale(1.2) rotate(-90deg); - } - - &:hover { - background-color: $euiColorLightestShade; - box-shadow: 0 0 0 ($euiSizeXS / 2) $euiColorLightestShade; - } - - &:focus { - background-color: $euiFocusBackgroundColor; - box-shadow: 0 0 0 ($euiSizeXS / 2) $euiFocusBackgroundColor; - } - - &--disabled, - &--disabled:hover { - cursor: not-allowed ; - opacity: .2; - } - } - - &--years { - position: relative; - top: 0; - display: block; - margin-left: auto; - margin-right: auto; - - &-previous { - top: $euiSizeXS; - border-top-color: $euiColorLightestShade; - - &:hover { - border-top-color: darken($euiColorLightestShade, 10%); - } - } - - &-upcoming { - top: -$euiSizeXS; - border-bottom-color: $euiColorLightestShade; - - &:hover { - border-bottom-color: darken($euiColorLightestShade, 10%); - } - } - } -} - -// .react-datepicker__month-container { -// } - -.react-datepicker__month { - margin: 0 $euiSize $euiSize $euiSize; - text-align: center; - border-radius: $euiBorderRadius; -} - -.react-datepicker__time-container { - border-left: $euiBorderColor; - width: auto; - display: flex; - padding: $euiSize 0; - border-radius: 0 $euiBorderRadius $euiBorderRadius 0; - flex-grow: 1; - - // &--with-today-button { - // } - - .react-datepicker__time { - position: relative; - flex-grow: 1; - display: flex; - padding-left: $euiSizeXS; - flex-direction: column; - - .react-datepicker__time-box { - width: auto; - display: flex; - flex-direction: column; - flex-grow: 1; - - ul.react-datepicker__time-list { - @include euiScrollBar; - height: 204px !important; - display: flex; - flex-direction: column; - flex-grow: 1; - overflow-y: auto; - align-items: center; - - li.react-datepicker__time-list-item { - padding: $euiSizeXS $euiSizeS; - margin-bottom: $euiSizeXS; - text-align: right; - color: $euiColorDarkShade; - white-space: nowrap; - // IE needs this to fix collapsing flex - line-height: $euiSizeM; - - &:hover, - &:focus { - cursor: pointer; - text-decoration: underline; - } - &--selected { - background-color: $euiColorPrimary; - color: white; - border-radius: $euiBorderRadius / 2; - &:hover { - background-color: $euiColorPrimary; - } - } - &--disabled { - color: $euiColorLightShade; - - &:hover { - cursor: not-allowed; - text-decoration: none; - background-color: transparent; - } - } - } - } - } - } -} - -.react-datepicker__week-number { - color: $euiColorLightestShade; - display: inline-block; - width: $euiSizeXL; - line-height: $euiSizeXL - $euiSizeXS; - text-align: center; - margin: 0 $euiSizeXS; - &.react-datepicker__week-number--clickable { - cursor: pointer; - &:hover { - border-radius: $euiBorderRadius; - background-color: $euiColorEmptyShade; - } - } -} - -.react-datepicker__day-names, -.react-datepicker__week { - white-space: nowrap; -} - -.react-datepicker__day-name, -.react-datepicker__day, -.react-datepicker__time-name { - color: $euiColorFullShade; - display: inline-block; - width: $euiSizeXL; - line-height: $euiSizeXL - $euiSizeXS; - text-align: center; - margin: 0 $euiSizeXS / 2; -} - -.react-datepicker__day-name { - color: $euiColorDarkShade; - text-transform: uppercase; -} - -.react-datepicker__day { - cursor: pointer; - border: solid 2px transparent; - transition: transform $euiAnimSpeedExtraFast ease-in-out; - - &:hover:not(&--disabled) { - text-decoration: underline; - font-weight: $euiFontWeightBold; - transform: scale(1.2); - } - - &--today { - font-weight: bold; - color: $euiColorPrimary; - } - &--outside-month { - color: $euiColorDarkShade; - } - - &--highlighted { - border-radius: $euiBorderRadius; - background-color: $euiColorSuccess; - color: $euiColorGhost; - - &:hover { - background-color: darken($euiColorSuccess, 5%); - } - } - - &--in-range { - background-color: transparentize($euiColorPrimary, .9); - color: $euiColorFullShade; - border-radius: 0; - border-top: solid 6px $euiColorEmptyShade; - border-bottom: solid 6px $euiColorEmptyShade; - border-right: none; - border-left: none; - line-height: $euiSizeL - $euiSizeXS; - } - - &--selected, - &--in-selecting-range { - height: $euiSizeXL; - margin: 0 $euiSizeXS / 2; - border-radius: $euiBorderRadius; - background-color: $euiColorPrimary; - line-height: $euiSizeL + $euiSizeXS; - border: solid $euiSizeXS / 2 $euiColorPrimary; - color: $euiColorGhost; - - &:hover { - background-color: darken($euiColorPrimary, 5%); - } - } - - &--keyboard-selected { - border-radius: $euiBorderRadius; - border: solid $euiSizeXS / 2 $euiColorPrimary; - font-weight: $euiFontWeightBold; - - &:hover { - background-color: darken($euiColorPrimary, 5%); - color: $euiColorGhost; - } - } - - &--in-selecting-range:not(&--in-range) { - background-color: rgba($euiColorPrimary, 0.5); - } - - &--in-range:not(&--in-selecting-range) { - .react-datepicker__month--selecting-range & { - background-color: $euiColorEmptyShade; - color: $euiColorFullShade; - } - } - - &--disabled { - cursor: not-allowed; - color: $euiColorLightShade; - - &:hover { - background-color: transparent; - } - } -} - -.react-datepicker__input-container { - position: relative; -} - -.react-datepicker__year-read-view { - font-weight: $euiFontWeightLight; - color: $euiColorDarkShade; -} - -.react-datepicker__month-read-view { - font-weight: $euiFontWeightMedium; -} - -.react-datepicker__year-read-view, -.react-datepicker__month-read-view, -.react-datepicker__month-year-read-view { - font-size: $euiFontSizeL; - - &:hover { - cursor: pointer; - color: $euiColorPrimary; - - .react-datepicker__year-read-view--down-arrow, - .react-datepicker__month-read-view--down-arrow { - border-top-color: darken($euiColorLightestShade, 10%); - } - } - - &--down-arrow { - display: none; - } -} - -.react-datepicker__year-dropdown, -.react-datepicker__month-dropdown, -.react-datepicker__month-year-dropdown { - background-color: $euiColorEmptyShade; - position: absolute; - width: 100%; - height: 100%; - left: 0; - top: 0; - bottom: 0; - right: 0; - z-index: 1; - text-align: center; - border-radius: $euiBorderRadius; - display: flex; - flex-wrap: wrap; - animation: euiAnimFadeIn $euiAnimSpeedFast ease-in; - align-content: space-around; - align-items: center; - padding: $euiSizeS; - - - &:hover { - cursor: pointer; - } - - // &--scrollable { - // height: 150px; - // overflow-y: scroll; - // } -} - -// Strike that, reverse it Willy Wonka style -.react-datepicker__year-dropdown { - flex-wrap: wrap-reverse; - flex-direction: row-reverse; - justify-content: flex-end; -} - -.react-datepicker__year-option, -.react-datepicker__month-option, -.react-datepicker__month-year-option { - font-size: $euiFontSizeXS; - padding: $euiSizeS; - color: $euiColorDarkestShade; - flex-basis: 33.3%; - - &:first-of-type { - border-top-left-radius: $euiBorderRadius; - border-top-right-radius: $euiBorderRadius; - } - - &:last-of-type { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - border-bottom-left-radius: $euiBorderRadius; - border-bottom-right-radius: $euiBorderRadius; - } - - &:hover { - background-color: $euiColorLightestShade; - - .react-datepicker__navigation--years-upcoming { - border-bottom-color: darken($euiColorLightestShade, 10%); - } - - .react-datepicker__navigation--years-previous { - border-top-color: darken($euiColorLightestShade, 10%); - } - } - - &--selected { - display: none; - } -} - -.react-datepicker__screenReaderOnly { - position: absolute; - left: -10000px; - top: auto; - width: 1px; - height: 1px; - overflow: hidden; -} - -.react-datepicker__year-option--preselected, -.react-datepicker__month-option--preselected { - background: $euiFocusBackgroundColor; -} - -.react-datepicker__year-option--selected_year.react-datepicker__year-option--preselected, -.react-datepicker__month-option--selected_month.react-datepicker__month-option--preselected{ - background: $euiColorPrimary; -} - -.react-datepicker__time-list-item--preselected, -.react-datepicker__year-option--preselected, -.react-datepicker__month-option--preselected { - background: darken($euiFocusBackgroundColor, 5%); -} - -.react-datepicker__time-container--focus { - background: $euiFocusBackgroundColor; -} - -.react-datepicker__month-read-view:focus, -.react-datepicker__year-read-view:focus { - text-decoration: underline; -} - -.react-datepicker__month--accessible:focus { - background: $euiFocusBackgroundColor; - - .react-datepicker__day--in-range:not(.react-datepicker__day--selected) { - border-top-color: $euiFocusBackgroundColor; - border-bottom-color: $euiFocusBackgroundColor; - } -} -.react-datepicker__navigation:focus { - background-color: $euiFocusBackgroundColor; -} - -// These selectors are not a typo. react-datepicker has a bug where these selectors -// output as "--selected_year". Sass has trouble compiling .--selected_year, so instead -// we use this generic selector get around it. -.react-datepicker__year-option--selected_year, -.react-datepicker__month-option--selected_month { - background: $euiColorPrimary; - color: $euiColorEmptyShade; - font-weight: $euiFontWeightBold; - border-radius: $euiBorderRadius; -} - -.react-datepicker__focusTrap { - display: flex; -} - -// The below is for the portal version of react-datepicker which we do not use. -// It is shown here just to know what their baseline includes. - -// .react-datepicker__close-icon { -// background-color: transparent; -// border: 0; -// cursor: pointer; -// display: inline-block; -// height: 0; -// outline: 0; -// padding: 0; -// vertical-align: middle; -// -// &::after { -// background-color: $euiColorPrimary; -// border-radius: 50%; -// bottom: 0; -// box-sizing: border-box; -// color: #fff; -// content: "\00d7"; -// cursor: pointer; -// font-size: 12px; -// height: 16px; -// width: 16px; -// line-height: 1; -// margin: -8px auto 0; -// padding: 2px; -// position: absolute; -// right: 7px; -// text-align: center; -// top: 50%; -// } -// } -// -// .react-datepicker__today-button { -// background: $euiColorEmptyShade; -// border-top: 1px solid $euiBorderColor; -// cursor: pointer; -// text-align: center; -// font-weight: bold; -// padding: 5px 0; -// clear: left; -// } -// -// .react-datepicker__portal { -// position: fixed; -// width: 100vw; -// height: 100vh; -// background-color: rgba(0, 0, 0, 0.8); -// left: 0; -// top: 0; -// justify-content: center; -// align-items: center; -// display: flex; -// z-index: 2147483647; -// -// .react-datepicker__day-name, -// .react-datepicker__day, -// .react-datepicker__time-name { -// width: 3rem; -// line-height: 3rem; -// } -// -// // Resize for small screens -// @media (max-width: 400px), (max-height: 550px) { -// .react-datepicker__day-name, -// .react-datepicker__day, -// .react-datepicker__time-name { -// width: 2rem; -// line-height: 2rem; -// } -// } -// -// .react-datepicker__current-month, -// .react-datepicker-time__header { -// font-size: $euiFontSizeXS * 1.8; -// } -// -// .react-datepicker__navigation { -// border: 1.8 * $euiSize solid transparent; -// } -// -// .react-datepicker__navigation--previous { -// border-right-color: $euiColorLightestShade; -// -// &:hover { -// border-right-color: darken($euiColorLightestShade, 10%); -// } -// -// &--disabled, -// &--disabled:hover { -// border-right-color: $datepicker__navigation-disabled-color; -// cursor: default; -// } -// } -// -// .react-datepicker__navigation--next { -// border-left-color: $euiColorLightestShade; -// -// &:hover { -// border-left-color: darken($euiColorLightestShade, 10%); -// } -// -// &--disabled, -// &--disabled:hover { -// border-left-color: $datepicker__navigation-disabled-color; -// cursor: default; -// } -// } -// } diff --git a/packages/eui-common/src/global_styling/react_date_picker/_index.scss b/packages/eui-common/src/global_styling/react_date_picker/_index.scss deleted file mode 100644 index 48ea2f99771..00000000000 --- a/packages/eui-common/src/global_styling/react_date_picker/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'variables'; -@import 'date_picker'; diff --git a/packages/eui-common/src/global_styling/react_date_picker/_variables.scss b/packages/eui-common/src/global_styling/react_date_picker/_variables.scss deleted file mode 100644 index 6a5abd4e528..00000000000 --- a/packages/eui-common/src/global_styling/react_date_picker/_variables.scss +++ /dev/null @@ -1 +0,0 @@ -$euiDatePickerCalendarWidth: 284px; \ No newline at end of file diff --git a/packages/eui-common/src/global_styling/utility/_animations.scss b/packages/eui-common/src/global_styling/utility/_animations.scss deleted file mode 100644 index c0cb6e7365a..00000000000 --- a/packages/eui-common/src/global_styling/utility/_animations.scss +++ /dev/null @@ -1,55 +0,0 @@ -// Animations as utility so they don't get duplicated in compiled CSS - -@keyframes euiAnimFadeIn { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} - -@keyframes euiGrow { - 0% { - opacity: 0; - } - - 1% { - opacity: 0; - transform: scale(0); - } - - 100% { - opacity: 1; - transform: scale(1); - } -} - -@keyframes focusRingAnimate { - 0% { - box-shadow: 0 0 0 $euiFocusRingAnimStartSize $euiFocusRingAnimStartColor; - } - - 100% { - box-shadow: 0 0 0 $euiFocusRingSize $euiFocusRingColor; - } -} - -@keyframes focusRingAnimateLarge { - 0% { - box-shadow: 0 0 0 $euiFocusRingAnimStartSizeLarge $euiFocusRingAnimStartColor; - } - - 100% { - box-shadow: 0 0 0 $euiFocusRingSizeLarge $euiFocusRingColor; - } -} - -// Component specific - -@keyframes euiButtonActive { - 50% { - transform: translateY(1px); - } -} diff --git a/packages/eui-common/src/global_styling/utility/_index.scss b/packages/eui-common/src/global_styling/utility/_index.scss deleted file mode 100644 index 5c978807848..00000000000 --- a/packages/eui-common/src/global_styling/utility/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'animations'; diff --git a/packages/eui-common/src/index.ts b/packages/eui-common/src/index.ts deleted file mode 100644 index e86804db831..00000000000 --- a/packages/eui-common/src/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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. - */ - -export * from './types'; -export * from './global_styling/functions'; diff --git a/packages/eui-common/src/types.ts b/packages/eui-common/src/types.ts deleted file mode 100644 index 68c72d586df..00000000000 --- a/packages/eui-common/src/types.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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. - */ - -/* TODO: duplicated types from /eui/src/components/common - extract to shared location */ - -/** - * Like `keyof typeof`, but for getting values instead of keys - * ValueOf - * Results in `'value1' | 'value2'` - */ -export type ValueOf = T[keyof T]; - -/** - * Replaces all properties on any type as optional, includes nested types - * - * @example - * ```ts - * interface Person { - * name: string; - * age?: number; - * spouse: Person; - * children: Person[]; - * } - * type PartialPerson = RecursivePartial; - * // results in - * interface PartialPerson { - * name?: string; - * age?: number; - * spouse?: RecursivePartial; - * children?: RecursivePartial[] - * } - * ``` - */ -export type RecursivePartial = { - [P in keyof T]?: T[P] extends NonAny[] // checks for nested any[] - ? T[P] - : T[P] extends readonly NonAny[] // checks for nested ReadonlyArray - ? T[P] - : T[P] extends Array - ? Array> - : T[P] extends ReadonlyArray - ? ReadonlyArray> - : T[P] extends Set // checks for Sets - ? Set> - : T[P] extends Map // checks for Maps - ? Map> - : T[P] extends NonAny // checks for primitive values - ? T[P] - : RecursivePartial; // recurse for all non-array and non-primitive values -}; -type NonAny = number | boolean | string | symbol | null; diff --git a/packages/eui-common/tsconfig.cjs.json b/packages/eui-common/tsconfig.cjs.json deleted file mode 100644 index 6becea42efa..00000000000 --- a/packages/eui-common/tsconfig.cjs.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "rootDir": "src", - "outDir": "lib/cjs", - "target": "es6", - "module": "CommonJS", - "lib": [ - "es6", - "DOM" - ], - "moduleResolution": "Node", - "declaration": true, - "sourceMap": true, - "noEmitHelpers": true, - "incremental": true, - "esModuleInterop": true, - "strict": true, - "skipLibCheck": true, - "tsBuildInfoFile": "lib/cjs/.tsbuildinfo", - "importHelpers": false, - }, - "include": [ - "src" - ], - "exclude": [ - "node_modules" - ], -} \ No newline at end of file diff --git a/packages/eui-common/tsconfig.json b/packages/eui-common/tsconfig.json deleted file mode 100644 index 055614f8c47..00000000000 --- a/packages/eui-common/tsconfig.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "rootDir": "src", - "outDir": "lib/esm", - "target": "ES2020", - "module": "ESNext", - "lib": [ - "ESNext", - "DOM" - ], - "moduleResolution": "Node", - "declaration": true, - "sourceMap": true, - "noEmitHelpers": true, - "incremental": true, - "esModuleInterop": true, - "strict": true, - "skipLibCheck": true, - "tsBuildInfoFile": "lib/esm/.tsbuildinfo" - }, - "include": [ - "src" - ], - "exclude": [ - "node_modules" - ], -} \ No newline at end of file diff --git a/packages/eui-common/tsconfig.types.json b/packages/eui-common/tsconfig.types.json deleted file mode 100644 index 54e2031daae..00000000000 --- a/packages/eui-common/tsconfig.types.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "./tsconfig.cjs.json", - "compilerOptions": { - "outDir": "lib/cjs", - "declaration": true, - "declarationMap": true, - "isolatedModules": false, - "noEmit": false, - "allowJs": false, - "emitDeclarationOnly": true - }, - "exclude": ["node_modules", "**/*.test.ts"] -} \ No newline at end of file diff --git a/packages/eui-theme-base/.babelrc.js b/packages/eui-theme-base/.babelrc.js deleted file mode 100644 index 0fc74dd1fe9..00000000000 --- a/packages/eui-theme-base/.babelrc.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = { - // We need to preserve comments as they are used by webpack for - // naming chunks during code-splitting. The compression step during - // bundling will remove them later. - comments: true, - - presets: [ - [ - '@babel/env', - { - // `targets` property set via `.browserslistrc` - useBuiltIns: process.env.NO_COREJS_POLYFILL ? false : 'usage', - corejs: !process.env.NO_COREJS_POLYFILL ? '3.6' : undefined, - modules: process.env.BABEL_MODULES - ? process.env.BABEL_MODULES === 'false' - ? false - : process.env.BABEL_MODULES - : 'commonjs', // babel's default is commonjs - }, - ], - ['@babel/react', { runtime: 'classic' }], - [ - '@babel/typescript', - { isTSX: true, allExtensions: true, allowDeclareFields: true }, - ], - ], -}; diff --git a/packages/eui-theme-base/.eslintignore b/packages/eui-theme-base/.eslintignore deleted file mode 100644 index 4874b17b0b8..00000000000 --- a/packages/eui-theme-base/.eslintignore +++ /dev/null @@ -1,9 +0,0 @@ -dist -node_modules -lib -types -**/*.d.ts -package.json -scripts -.eslintrc.js -babel.config.js diff --git a/packages/eui-theme-base/.eslintplugin.js b/packages/eui-theme-base/.eslintplugin.js deleted file mode 100644 index 3a2357171e8..00000000000 --- a/packages/eui-theme-base/.eslintplugin.js +++ /dev/null @@ -1,3 +0,0 @@ -exports.rules = { - 'require-license-header': require('@elastic/eui-common/scripts/eslint-plugin-local/require_license_header.js'), -}; diff --git a/packages/eui-theme-base/.eslintrc.js b/packages/eui-theme-base/.eslintrc.js deleted file mode 100644 index e33853c0255..00000000000 --- a/packages/eui-theme-base/.eslintrc.js +++ /dev/null @@ -1,114 +0,0 @@ -const SSPL_ELASTIC_2_0_LICENSE_HEADER = ` -/* - * 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. - */ -`; - -module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: ['./tsconfig.json'], - ecmaFeatures: { - jsx: true, - }, - }, - settings: { - 'import/resolver': { - node: { - extensions: ['.ts', '.tsx', '.js', '.json'], - }, - }, - }, - extends: [ - 'plugin:@typescript-eslint/recommended', - // Prettier options need to come last, in order to override other style rules - 'plugin:prettier/recommended', - ], - plugins: ['local', 'import'], - rules: { - 'block-scoped-var': 'error', - camelcase: 'off', - 'dot-notation': ['error', { allowKeywords: true }], - eqeqeq: ['error', 'always', { null: 'ignore' }], - 'guard-for-in': 'error', - 'new-cap': ['error', { capIsNewExceptions: ['Private'] }], - 'no-caller': 'error', - 'no-const-assign': 'error', - 'no-debugger': 'error', - 'no-empty': ['error', { allowEmptyCatch: true }], - 'no-eval': 'error', - 'no-extend-native': 'error', - 'no-global-assign': 'error', - 'no-loop-func': 'error', - 'no-restricted-globals': ['error', 'context'], - 'no-script-url': 'error', - 'no-sequences': 'error', - 'no-var': 'error', - 'no-with': 'error', - 'prefer-const': 'error', - 'prefer-template': 'error', - strict: ['error', 'never'], - 'valid-typeof': 'error', - - 'local/require-license-header': [ - 'warn', - { - license: SSPL_ELASTIC_2_0_LICENSE_HEADER, - }, - ], - - 'import/no-unresolved': ['error', { amd: true, commonjs: true }], - 'import/namespace': 'error', - 'import/default': 'error', - 'import/export': 'error', - 'import/no-named-as-default': 'error', - 'import/no-named-as-default-member': 'error', - 'import/no-duplicates': 'error', - - '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], - '@typescript-eslint/ban-types': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-member-accessibility': 'off', - '@typescript-eslint/indent': 'off', - '@typescript-eslint/ban-tslint-comment': 'error', - '@typescript-eslint/no-empty-interface': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-parameter-properties': 'off', - '@typescript-eslint/no-triple-slash-reference': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { argsIgnorePattern: '^_', ignoreRestSiblings: true }, - ], - '@typescript-eslint/no-use-before-define': 'off', - '@typescript-eslint/no-empty-function': 'off', - // It"s all very well saying that some types are trivially inferrable, - // but being explicit is still clearer. - '@typescript-eslint/no-inferrable-types': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/naming-convention': 'off', - '@typescript-eslint/ban-ts-comment': [ - 'error', - { - 'ts-ignore': 'allow-with-description', - 'ts-expect-error': 'allow-with-description', - }, - ], - '@typescript-eslint/consistent-type-exports': [ - 'error', - { fixMixedExportsWithInlineTypeSpecifier: false }, - ], - }, - overrides: [ - { - files: ['*.d.ts'], - rules: { - 'react/prefer-es6-class': 'off', - }, - }, - ], -}; diff --git a/packages/eui-theme-base/.gitignore b/packages/eui-theme-base/.gitignore deleted file mode 100644 index 4450fe8d868..00000000000 --- a/packages/eui-theme-base/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -# Dependencies -/node_modules - -# Production -/lib - -yarn-debug.log* -yarn-error.log* - -# Build-related files -.eslintcache \ No newline at end of file diff --git a/packages/eui-theme-base/.prettierrc b/packages/eui-theme-base/.prettierrc deleted file mode 100644 index b2f0fa8f00e..00000000000 --- a/packages/eui-theme-base/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parser": "typescript", - "printWidth": 80, - "semi": true, - "singleQuote": true, - "trailingComma": "es5" -} diff --git a/packages/eui-theme-base/.stylelintrc.js b/packages/eui-theme-base/.stylelintrc.js deleted file mode 100644 index 42adc41f28c..00000000000 --- a/packages/eui-theme-base/.stylelintrc.js +++ /dev/null @@ -1,163 +0,0 @@ -const camelCaseRegex = '^[a-z][\\w-]*$'; // Note: also allows `_` as part of BEM naming -const camelCaseValueRegex = '/^[a-z][\\w.]*$/'; // Note: also allows `.` for JS objects -const cssInJsVarRegex = '/\\${[a-zA-Z]+/'; - -module.exports = { - // @see https://stylelint.io/user-guide/rules - rules: { - // Enforce camelCase naming - 'selector-class-pattern': camelCaseRegex, - 'keyframes-name-pattern': camelCaseRegex, - 'custom-property-pattern': camelCaseRegex, - - // Opinionated rules - 'declaration-no-important': true, - 'max-nesting-depth': [ - 2, - { - ignore: ['blockless-at-rules', 'pseudo-classes'], - }, - ], - 'block-no-empty': true, - 'selector-no-qualifying-type': [ - true, - { - ignore: ['attribute'], // Allows input[type=search] - }, - ], - - // Non-Prettier newline rules - // Put a line-break between sections of CSS, but allow quick one-liners for legibility - 'rule-empty-line-before': [ - 'always-multi-line', - { - ignore: ['first-nested', 'after-comment'], - }, - ], - 'comment-empty-line-before': null, - 'declaration-empty-line-before': null, - - // Value preferences - 'number-max-precision': null, - // Attempt to catch/flag non-variable color values - 'color-named': 'never', - 'color-no-hex': true, - // Prefer lowercase values, except for font names and currentColor - 'value-keyword-case': [ - 'lower', - { - ignoreProperties: ['font-family', '/^\\$eui[\\w]+/'], // Allow fonts and Sass variables - ignoreKeywords: ['currentColor'], - }, - ], - 'declaration-block-no-duplicate-properties': [ - true, - { - ignore: ['consecutive-duplicates'], // We occasionally use duplicate property values for cross-browser fallbacks - }, - ], - - // TODO: It may be worth investigating and updating these rules to their more modern counterparts - 'color-function-notation': 'legacy', - 'alpha-value-notation': 'number', - - // Disable various opinionated extended stylelint rules that EUI has not previously enforced - 'no-descending-specificity': null, - 'keyframe-selector-notation': null, - 'declaration-block-no-redundant-longhand-properties': null, - }, - overrides: [ - { - // TODO: Remove Sass-specific config & rules once we're completely off Sass - files: ['**/*.scss'], - ignoreFiles: [ - 'generator-eui/**/*.scss', - 'src/global_styling/react_date_picker/**/*.scss', - 'src/themes/amsterdam/global_styling/react_date_picker/**/*.scss', - 'src/components/date_picker/react-datepicker/**/*.scss', - ], - extends: [ - 'stylelint-config-standard-scss', - 'stylelint-config-prettier-scss', - ], - // @see https://github.com/stylelint-scss/stylelint-scss#list-of-rules - rules: { - // Casing - 'scss/dollar-variable-pattern': camelCaseRegex, - 'scss/at-mixin-pattern': camelCaseRegex, - 'scss/at-function-pattern': camelCaseRegex, - 'function-name-case': [ - 'lower', - { - ignoreFunctions: [`/${camelCaseRegex}/`, 'MIN'], - }, - ], - - // Whitespace/newlines - 'scss/at-if-closing-brace-space-after': 'always-intermediate', - 'scss/operator-no-unspaced': true, - - // Formatting rules deprecated as of v15 - keep them in Sass styles just in case until end of migration - // @see https://github.com/stylelint/stylelint/blob/main/docs/user-guide/rules.md#deprecated - 'color-hex-case': 'upper', - 'string-quotes': 'single', - // 2 spaces for indentation - indentation: [2, { indentInsideParens: 'once-at-root-twice-in-block' }], - // Mimic 1tbs `} else {` brace style, like our JS - 'block-opening-brace-space-before': 'always', - 'block-closing-brace-newline-before': 'always-multi-line', - // Ensure multiple selectors on one line each - 'selector-list-comma-newline-before': 'never-multi-line', - 'selector-list-comma-newline-after': 'always', - // Trim unnecessary newlines/whitespace - 'block-closing-brace-empty-line-before': 'never', - 'max-empty-lines': 1, - 'no-eol-whitespace': true, - // Enforce spacing around various syntax symbols (colons, operators, etc.) - 'declaration-colon-space-after': 'always-single-line', - 'declaration-colon-space-before': 'never', - 'function-calc-no-unspaced-operator': true, - 'selector-combinator-space-before': 'always', - 'selector-combinator-space-after': 'always', - // Ensure trailing semicolons are always present on non-oneliners - 'declaration-block-semicolon-newline-after': 'always-multi-line', - - // Disable various opinionated extended stylelint rules that EUI has not previously enforced - 'scss/no-global-function-names': null, - 'scss/dollar-variable-empty-line-before': null, - 'scss/at-rule-conditional-no-parentheses': null, - 'scss/double-slash-comment-empty-line-before': null, - 'scss/at-if-no-null': null, - 'selector-not-notation': null, // Enforce comma notation for CSS-in-JS moving forward - }, - }, - { - files: ['**/*.styles.ts', '**/*.ts', '**/*.tsx'], - extends: ['stylelint-config-standard'], - customSyntax: 'postcss-styled-syntax', - rules: { - // Unfortunately, double slash comments must be replaced with standard CSS /* */ comments - // Otherwise we get a parsing error - see https://github.com/hudochenkov/postcss-styled-syntax#known-issues - 'no-invalid-double-slash-comments': true, - // Empty style keys should be allowed, as Emotion still uses them for generating classNames - 'no-empty-source': null, - // Don't lint casing on interpolated JS vars - 'function-name-case': ['lower', { ignoreFunctions: [cssInJsVarRegex] }], - 'function-no-unknown': [true, { ignoreFunctions: [cssInJsVarRegex] }], - 'value-keyword-case': [ - 'lower', - { - ignoreProperties: ['font-family'], - ignoreKeywords: [camelCaseValueRegex], - }, - ], - // This is set to deprecate after stylelint v16, but in the meanwhile, is helpful - // for finding extraneous semicolons after utils that already output semicolons (e.g. logicalCSS()) - 'no-extra-semicolons': true, - - // Emotion uses the `label` property to generate the output className string - 'property-no-unknown': [true, { ignoreProperties: 'label' }], - }, - }, - ], -}; diff --git a/packages/eui-theme-base/LICENSE.txt b/packages/eui-theme-base/LICENSE.txt deleted file mode 100644 index 74327a8f6f3..00000000000 --- a/packages/eui-theme-base/LICENSE.txt +++ /dev/null @@ -1,6 +0,0 @@ -Source code in this repository is covered by (i) a dual license under the Server -Side Public License, v 1 and the Elastic License 2.0 or (ii) an Apache License -2.0 compatible license or (iii) solely under the Elastic License 2.0, in each -case, as noted in the applicable header. The default throughout the repository -is a dual license under the Server Side Public License, v 1 and the Elastic -License 2.0, unless the header specifies another license. diff --git a/packages/eui-theme-base/README.md b/packages/eui-theme-base/README.md deleted file mode 100644 index 77f336dbb81..00000000000 --- a/packages/eui-theme-base/README.md +++ /dev/null @@ -1 +0,0 @@ -# EUI base theme functionality and styling \ No newline at end of file diff --git a/packages/eui-theme-base/babel.config.js b/packages/eui-theme-base/babel.config.js deleted file mode 100644 index 8165fe45577..00000000000 --- a/packages/eui-theme-base/babel.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - presets: [ - ['@babel/preset-env', { targets: { node: 'current' } }], - '@babel/preset-typescript', - ], -}; diff --git a/packages/eui-theme-base/package.json b/packages/eui-theme-base/package.json deleted file mode 100644 index 2f9731eab86..00000000000 --- a/packages/eui-theme-base/package.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "name": "@elastic/eui-theme-base", - "version": "0.0.1", - "description": "EUI theme base", - "license": "SEE LICENSE IN LICENSE.txt", - "scripts": { - "build:clean": "rimraf lib/", - "build": "yarn build:clean && yarn build:compile && yarn build:compile:cjs && yarn build:types", - "build:compile": "tsc --project tsconfig.json", - "build:compile:cjs": "NODE_ENV=production babel src --out-dir=lib/cjs --extensions .js,.ts,.tsx --source-maps", - "build:types": "NODE_ENV=production tsc --project tsconfig.types.json", - "build-pack": "yarn build && npm pack", - "lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-sass", - "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", - "lint-sass": "yarn stylelint \"**/*.scss\" --quiet-deprecation-warnings", - "test": "jest" - }, - "repository": { - "type": "git", - "url": "https://github.com/elastic/eui.git", - "directory": "packages/eui-theme-base" - }, - "private": true, - "devDependencies": { - "@babel/cli": "^7.21.5", - "@babel/core": "^7.21.8", - "@babel/preset-env": "^7.21.5", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.5", - "@elastic/eui-common": "workspace:^", - "@types/jest": "^29.5.12", - "@types/prettier": "2.7.3", - "@typescript-eslint/eslint-plugin": "^5.59.7", - "@typescript-eslint/parser": "^5.59.7", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jest": "^28.5.0", - "eslint-plugin-local": "^1.0.0", - "eslint-plugin-prettier": "^4.2.1", - "jest": "^29.7.0", - "prettier": "^2.8.8", - "rimraf": "^6.0.1", - "stylelint": "^15.7.0", - "stylelint-config-prettier-scss": "^1.0.0", - "stylelint-config-standard": "^33.0.0", - "stylelint-config-standard-scss": "^9.0.0", - "typescript": "4.5.3" - }, - "peerDependencies": { - "@elastic/eui-common": "0.0.1" - }, - "main": "lib/cjs/index.js", - "exports": { - "./lib/*": "./lib/*", - ".": { - "require": "./lib/cjs/index.js", - "import": "./lib/esm/index.js", - "default": "./lib/cjs/index.js" - } - }, - "files": [ - "lib/", - "src/**/*.scss", - "README.md" - ], - "installConfig": { - "hoistingLimits": "workspaces" - } -} diff --git a/packages/eui-theme-base/src/index.ts b/packages/eui-theme-base/src/index.ts deleted file mode 100644 index 4434190910f..00000000000 --- a/packages/eui-theme-base/src/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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. - */ - -export * from './types'; -export * from './variables'; -export * from './utils'; diff --git a/packages/eui-theme-base/src/types.ts b/packages/eui-theme-base/src/types.ts deleted file mode 100644 index ba2d7392666..00000000000 --- a/packages/eui-theme-base/src/types.ts +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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 type { CSSObject } from '@emotion/react'; -import type { RecursivePartial, ValueOf } from '@elastic/eui-common'; - -import { _EuiThemeAnimation } from './variables/animations'; -import { _EuiThemeBreakpoints } from './variables/breakpoint'; -import { _EuiThemeBorder } from './variables/borders'; -import { _EuiThemeColors } from './variables/colors'; -import { _EuiThemeBase, _EuiThemeSizes } from './variables/size'; -import { _EuiThemeFont } from './variables/typography'; -import { _EuiThemeFocus } from './variables/states'; -import { _EuiThemeLevels } from './variables/levels'; - -export const COLOR_MODES_STANDARD = { - light: 'LIGHT', - dark: 'DARK', -} as const; -export const COLOR_MODES_INVERSE = 'INVERSE' as const; - -export type EuiThemeColorModeInverse = typeof COLOR_MODES_INVERSE; -export type EuiThemeColorModeStandard = ValueOf; -export type EuiThemeColorMode = - | 'light' - | 'dark' - | EuiThemeColorModeStandard - | 'inverse' - | EuiThemeColorModeInverse; - -export type ColorModeSwitch = - | { - [key in EuiThemeColorModeStandard]: T; - } - | T; - -export type StrictColorModeSwitch = { - [key in EuiThemeColorModeStandard]: T; -}; - -export type EuiThemeShape = { - colors: _EuiThemeColors; - /** - Default value: 16 */ - base: _EuiThemeBase; - /** - * @see {@link https://eui.elastic.co/#/theming/sizing | Reference} for more information - */ - size: _EuiThemeSizes; - font: _EuiThemeFont; - border: _EuiThemeBorder; - focus: _EuiThemeFocus; - animation: _EuiThemeAnimation; - breakpoint: _EuiThemeBreakpoints; - levels: _EuiThemeLevels; -}; - -export type EuiThemeSystem = { - root: EuiThemeShape & T; - model: EuiThemeShape & T; - key: string; -}; - -export type EuiThemeModifications = RecursivePartial; - -export type ComputedThemeShape< - T, - P = string | number | bigint | boolean | null | undefined -> = T extends P | ColorModeSwitch - ? T extends ColorModeSwitch - ? X extends P - ? X - : { - [K in keyof (X & - Exclude< - T, - keyof X | keyof StrictColorModeSwitch - >)]: ComputedThemeShape< - (X & Exclude)[K], - P - >; - } - : T - : { - [K in keyof T]: ComputedThemeShape; - }; - -export type EuiThemeComputed = ComputedThemeShape & { - themeName: string; -}; - -export type EuiThemeNested = { - isGlobalTheme: boolean; - hasDifferentColorFromGlobalTheme: boolean; - bodyColor: string; - colorClassName: string; - setGlobalCSSVariables: Function; - globalCSSVariables?: CSSObject; - setNearestThemeCSSVariables: Function; - themeCSSVariables?: CSSObject; -}; diff --git a/packages/eui-theme-base/src/utils.test.ts b/packages/eui-theme-base/src/utils.test.ts deleted file mode 100644 index c654e4d3c22..00000000000 --- a/packages/eui-theme-base/src/utils.test.ts +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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 { - isInverseColorMode, - getColorMode, - getOn, - setOn, - computed, - Computed, - getComputed, - buildTheme, - mergeDeep, -} from './utils'; - -describe('isInverseColorMode', () => { - it("true only if 'inverse'", () => { - expect(isInverseColorMode('LIGHT')).toBe(false); - expect(isInverseColorMode('DARK')).toBe(false); - expect(isInverseColorMode('custom')).toBe(false); - expect(isInverseColorMode()).toBe(false); - expect(isInverseColorMode('INVERSE')).toBe(true); - }); -}); - -describe('getColorMode', () => { - it("defaults to 'LIGHT'", () => { - expect(getColorMode()).toEqual('LIGHT'); - }); - it('uses `parentMode` as fallback', () => { - expect(getColorMode(undefined, 'DARK')).toEqual('DARK'); - }); - it("understands 'INVERSE'", () => { - expect(getColorMode('INVERSE', 'DARK')).toEqual('LIGHT'); - expect(getColorMode('INVERSE', 'LIGHT')).toEqual('DARK'); - expect(getColorMode('INVERSE')).toEqual('LIGHT'); - }); -}); - -describe('getOn', () => { - const obj = { - parent: { - child: 'childVal', - }, - other: { - thing: { - string: 'stringVal', - nested: ['array'], - number: 0, - func: () => {}, - }, - }, - colors: { - LIGHT: { primary: '#000' }, - DARK: { primary: '#FFF' }, - }, - }; - it('gets values at the given path', () => { - expect(getOn(obj, 'parent')).toEqual({ - child: 'childVal', - }); - expect(getOn(obj, 'parent.child')).toEqual('childVal'); - expect(getOn(obj, 'other.thing.string')).toEqual('stringVal'); - }); - it('gets values of various kinds', () => { - expect(getOn(obj, 'other.thing.nested')).toEqual(['array']); - expect(getOn(obj, 'other.thing.number')).toEqual(0); - expect(getOn(obj, 'other.thing.func')).toBeInstanceOf(Function); - }); - it('can shortcut color modes', () => { - expect(getOn(obj, 'colors.primary', 'LIGHT')).toEqual('#000'); - expect(getOn(obj, 'colors.primary', 'DARK')).toEqual('#FFF'); - }); - it('will not error', () => { - expect(getOn(obj, 'nope')).toBe(undefined); - expect(getOn(obj, 'other.nope')).toBe(undefined); - expect(getOn(obj, 'other.thing.nope')).toBe(undefined); - }); -}); - -describe('setOn', () => { - let obj: {}; - beforeEach(() => { - obj = { - existing: { - nested: { - val: 'value', - }, - }, - }; - }); - it('sets values at the given path', () => { - setOn(obj, 'existing.new', 'value'); - expect(obj).toEqual({ - existing: { nested: { val: 'value' }, new: 'value' }, - }); - setOn(obj, 'existing.nested.new', 'value'); - expect(obj).toEqual({ - existing: { nested: { val: 'value', new: 'value' }, new: 'value' }, - }); - }); - it('deep arbitrary creation', () => { - setOn(obj, 'trail.blazing.happening.now', 'wow'); - expect(obj).toEqual({ - existing: { nested: { val: 'value' } }, - trail: { blazing: { happening: { now: 'wow' } } }, - }); - }); - it('overrides existing path value', () => { - setOn(obj, 'existing.nested', 'diff'); - expect(obj).toEqual({ - existing: { - nested: 'diff', - }, - }); - }); -}); - -describe('computed', () => { - it('should transform to Computed with dependencies array', () => { - const output = computed(([path]) => path, ['path.to']); - expect(output).toBeInstanceOf(Computed); - expect(output.computer).toBeInstanceOf(Function); - expect(output.dependencies).toEqual(['path.to']); - }); - it('should transform to Computed with single dependency', () => { - const output = computed((path) => path, 'path.to'); - expect(output).toBeInstanceOf(Computed); - expect(output.computer).toBeInstanceOf(Function); - expect(output.dependencies).toEqual('path.to'); - }); - it('should transform to Computed without dependencies array', () => { - const output = computed((path) => path); - expect(output).toBeInstanceOf(Computed); - }); -}); - -const theme = buildTheme( - { - colors: { - LIGHT: { - primary: '#000', - secondary: computed(([primary]) => `${primary}000`, ['colors.primary']), - }, - DARK: { - primary: '#FFF', - secondary: computed((theme) => `${theme.colors.primary}FFF`), - }, - }, - sizes: { - small: 8, - }, - }, - 'minimal' -); -describe('getComputed', () => { - it('computes all values and returns only the current color mode', () => { - // @ts-expect-error intentionally not using a full EUI theme definition - expect(getComputed(theme, {}, 'LIGHT')).toEqual({ - colors: { primary: '#000', secondary: '#000000' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - // @ts-expect-error intentionally not using a full EUI theme definition - expect(getComputed(theme, {}, 'DARK')).toEqual({ - colors: { primary: '#FFF', secondary: '#FFFFFF' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - }); - it('respects simple overrides', () => { - expect( - // @ts-expect-error intentionally not using a full EUI theme definition - getComputed(theme, buildTheme({ sizes: { small: 4 } }, ''), 'LIGHT') - ).toEqual({ - colors: { primary: '#000', secondary: '#000000' }, - sizes: { small: 4 }, - themeName: 'minimal', - }); - }); - it('respects overrides in computation', () => { - expect( - getComputed( - // @ts-expect-error intentionally not using a full EUI theme definition - theme, - buildTheme({ colors: { LIGHT: { primary: '#CCC' } } }, ''), - 'LIGHT' - ) - ).toEqual({ - colors: { primary: '#CCC', secondary: '#CCC000' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - }); - it('respects property extensions', () => { - expect( - getComputed( - // @ts-expect-error intentionally not using a full EUI theme definition - theme, - buildTheme({ colors: { LIGHT: { tertiary: '#333' } } }, ''), - 'LIGHT' - ) - ).toEqual({ - colors: { primary: '#000', secondary: '#000000', tertiary: '#333' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - }); - it('respects section extensions', () => { - expect( - getComputed( - // @ts-expect-error intentionally not using a full EUI theme definition - theme, - buildTheme({ custom: { myProp: '#333' } }, ''), - 'LIGHT' - ) - ).toEqual({ - colors: { primary: '#000', secondary: '#000000' }, - sizes: { small: 8 }, - custom: { myProp: '#333' }, - themeName: 'minimal', - }); - }); - it('respects extensions in computation', () => { - expect( - getComputed( - // @ts-expect-error intentionally not using a full EUI theme definition - theme, - buildTheme( - { - colors: { - LIGHT: { - tertiary: computed( - ([primary]) => `${primary}333`, - ['colors.primary'] - ), - }, - }, - }, - '' - ), - 'LIGHT' - ) - ).toEqual({ - colors: { primary: '#000', secondary: '#000000', tertiary: '#000333' }, - sizes: { small: 8 }, - themeName: 'minimal', - }); - }); -}); - -describe('buildTheme', () => { - it('builds an EUI theme system', () => { - // TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property 'length' which is either non-existant or configurable in the proxy target - // expect(theme).toEqual(Proxy); // get() trap returns theme.model - // expect(theme.root).toEqual(Proxy); - expect(theme.key).toEqual('minimal'); - }); -}); - -describe('mergeDeep', () => { - it('merge simple objects, second into first', () => { - expect(mergeDeep({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 }); - expect(mergeDeep({ a: 1 }, { a: 2 })).toEqual({ a: 2 }); - }); - it('merge complex objects, second into first', () => { - expect( - mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { d: 4 } } }) - ).toEqual({ a: 1, b: { c: { d: 4 } } }); - expect( - mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { e: 5 } } }) - ).toEqual({ a: 1, b: { c: { d: 3, e: 5 } } }); - }); -}); diff --git a/packages/eui-theme-base/src/utils.ts b/packages/eui-theme-base/src/utils.ts deleted file mode 100644 index 06e288afd7b..00000000000 --- a/packages/eui-theme-base/src/utils.ts +++ /dev/null @@ -1,392 +0,0 @@ -/* - * 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 { - EuiThemeColorMode, - EuiThemeColorModeInverse, - EuiThemeColorModeStandard, - EuiThemeModifications, - EuiThemeSystem, - EuiThemeShape, - EuiThemeComputed, - COLOR_MODES_STANDARD, - COLOR_MODES_INVERSE, -} from './types'; - -export const DEFAULT_COLOR_MODE = COLOR_MODES_STANDARD.light; - -/** - * Returns whether the parameter is an object - * @param {any} obj - Anything - */ -const isObject = (obj: any) => obj && typeof obj === 'object'; - -/** - * Returns whether the provided color mode is `inverse` - * @param {string} colorMode - `light`, `dark`, or `inverse` - */ -export const isInverseColorMode = ( - colorMode?: string -): colorMode is EuiThemeColorModeInverse => { - return colorMode === COLOR_MODES_INVERSE; -}; - -/** - * Returns the color mode configured in the current EuiThemeProvider. - * Returns the parent color mode if none is explicity set. - * @param {string} colorMode - `light`, `dark`, or `inverse` - * @param {string} parentColorMode - `LIGHT` or `DARK`; used as the fallback - */ -export const getColorMode = ( - colorMode?: EuiThemeColorMode, - parentColorMode?: EuiThemeColorModeStandard -): EuiThemeColorModeStandard => { - if (colorMode == null) { - return parentColorMode || DEFAULT_COLOR_MODE; - } - const mode = colorMode.toUpperCase() as - | EuiThemeColorModeInverse - | EuiThemeColorModeStandard; - if (isInverseColorMode(mode)) { - return parentColorMode === COLOR_MODES_STANDARD.dark || - parentColorMode === undefined - ? COLOR_MODES_STANDARD.light - : COLOR_MODES_STANDARD.dark; - } else { - return mode; - } -}; - -/** - * Returns a value at a given path on an object. - * If `colorMode` is provided, will scope the value to the appropriate color mode key (LIGHT\DARK) - * @param {object} model - Object - * @param {string} _path - Dot-notated string to a path on the object - * @param {string} colorMode - `light` or `dark` - */ -export const getOn = ( - model: { [key: string]: any }, - _path: string, - colorMode?: EuiThemeColorModeStandard -) => { - const path = _path.split('.'); - let node = model; - while (path.length) { - const segment = path.shift()!; - - if (node.hasOwnProperty(segment) === false) { - if ( - colorMode && - node.hasOwnProperty(colorMode) === true && - node[colorMode].hasOwnProperty(segment) === true - ) { - if (node[colorMode][segment] instanceof Computed) { - node = node[colorMode][segment].getValue(null, {}, node, colorMode); - } else { - node = node[colorMode][segment]; - } - } else { - return undefined; - } - } else { - if (node[segment] instanceof Computed) { - node = node[segment].getValue(null, {}, node, colorMode); - } else { - node = node[segment]; - } - } - } - - return node; -}; - -/** - * Sets a value at a given path on an object. - * @param {object} model - Object - * @param {string} _path - Dot-notated string to a path on the object - * @param {any} string - The value to set - */ -export const setOn = ( - model: { [key: string]: any }, - _path: string, - value: any -) => { - const path = _path.split('.'); - const propertyName = path.pop()!; - let node = model; - - while (path.length) { - const segment = path.shift()!; - if (node.hasOwnProperty(segment) === false) { - node[segment] = {}; - } - node = node[segment]; - } - - node[propertyName] = value; - return true; -}; - -/** - * Creates a class to store the `computer` method and its eventual parameters. - * Allows for on-demand computation with up-to-date parameters via `getValue` method. - * @constructor - * @param {function} computer - Function to be computed - * @param {string | array} dependencies - Dependencies passed to the `computer` as parameters - */ -export class Computed { - constructor( - public computer: (...values: any[]) => T, - public dependencies: string | string[] = [] - ) {} - - /** - * Executes the `computer` method with the current state of the theme - * by taking into account previously computed values and modifications. - * @param {Proxy | object} base - Computed or uncomputed theme - * @param {Proxy | object} modifications - Theme value overrides - * @param {object} working - Partially computed theme - * @param {string} colorMode - `light` or `dark` - */ - getValue( - base: EuiThemeSystem | EuiThemeShape | null, - modifications: EuiThemeModifications = {}, - working: Partial, - colorMode?: EuiThemeColorModeStandard - ) { - if (!this.dependencies.length) { - return this.computer(working); - } - if (!Array.isArray(this.dependencies)) { - return this.computer( - getOn(working, this.dependencies) ?? - getOn(modifications, this.dependencies, colorMode) ?? - (base ? getOn(base, this.dependencies, colorMode) : working) - ); - } - return this.computer( - this.dependencies.map((dependency) => { - return ( - getOn(working, dependency) ?? - getOn(modifications, dependency, colorMode) ?? - (base ? getOn(base, dependency, colorMode) : working) - ); - }) - ); - } -} - -/** - * Returns a Class (`Computed`) that stores the arbitrary computer method - * and references to its optional dependecies. - * @param {function} computer - Arbitrary method to be called at compute time. - * @param {string | array} dependencies - Values that will be provided to `computer` at compute time. - */ -export function computed(computer: (value: EuiThemeComputed) => T): T; -export function computed( - computer: (value: any[]) => T, - dependencies: string[] -): T; -export function computed( - computer: (value: any) => T, - dependencies: string -): T; -export function computed( - comp: ((value: T) => T) | ((value: any) => T) | ((value: any[]) => T), - dep?: string | string[] -) { - return new Computed(comp, dep); -} - -/** - * Type guard to check for a Computed object based on object shape - * without relying on the Computed class directly - */ -const isComputedLike = (key: object): key is Computed => { - if (typeof key !== 'object' || Array.isArray(key)) return false; - - return key.hasOwnProperty('dependencies') && key.hasOwnProperty('computer'); -}; - -/** - * Takes an uncomputed theme, and computes and returns all values taking - * into consideration value overrides and configured color mode. - * Overrides take precedence, and only values in the current color mode - * are computed and returned. - * @param {Proxy} base - Object to transform into Proxy - * @param {Proxy | object} over - Unique identifier or name - * @param {string} colorMode - `light` or `dark` - */ -export const getComputed = ( - base: EuiThemeSystem, - over: Partial>, - colorMode: EuiThemeColorModeStandard -): EuiThemeComputed => { - const output: Partial = { themeName: base.key }; - - function loop( - base: { [key: string]: any }, - over: { [key: string]: any }, - checkExisting: boolean = false, - path?: string - ) { - Object.keys(base).forEach((key) => { - let newPath = path ? `${path}.${key}` : `${key}`; - // @ts-expect-error `key` is not necessarily a colorMode key - if ([...Object.values(COLOR_MODES_STANDARD), colorMode].includes(key)) { - if (key !== colorMode) { - return; - } else { - const colorModeSegment = new RegExp( - `(\\.${colorMode}\\b)|(\\b${colorMode}\\.)` - ); - newPath = newPath.replace(colorModeSegment, ''); - } - } - const existing = checkExisting && getOn(output, newPath); - if (!existing || isObject(existing)) { - // NOTE: the class type check for Computed is not true for themes created externally; - // we additionally check on the object shape to confirm a Computed value - const baseValue = - base[key] instanceof Computed || isComputedLike(base[key]) - ? base[key].getValue(base.root, over.root, output, colorMode) - : base[key]; - const overValue = - over[key] instanceof Computed || isComputedLike(over[key]) - ? over[key].getValue(base.root, over.root, output, colorMode) - : over[key]; - if (isObject(baseValue) && !Array.isArray(baseValue)) { - loop(baseValue, overValue ?? {}, checkExisting, newPath); - } else { - setOn(output, newPath, overValue ?? baseValue); - } - } - }); - } - // Compute standard theme values and apply overrides - loop(base, over); - // Compute and apply extension values only - loop(over, {}, true); - return output as EuiThemeComputed; -}; - -/** - * Builds a Proxy with a custom `handler` designed to self-reference values - * and prevent arbitrary value overrides. - * @param {object} model - Object to transform into Proxy - * @param {string} key - Unique identifier or name - */ -export const buildTheme = (model: T, key: string) => { - const handler: ProxyHandler> = { - getPrototypeOf(target) { - return Reflect.getPrototypeOf(target.model); - }, - - setPrototypeOf(target, prototype) { - return Reflect.setPrototypeOf(target.model, prototype); - }, - - isExtensible(target) { - return Reflect.isExtensible(target); - }, - - preventExtensions(target) { - return Reflect.preventExtensions(target.model); - }, - - getOwnPropertyDescriptor(target, key) { - return Reflect.getOwnPropertyDescriptor(target.model, key); - }, - - defineProperty(target, property, attributes) { - return Reflect.defineProperty(target.model, property, attributes); - }, - - has(target, property) { - return Reflect.has(target.model, property); - }, - - get(_target, property) { - if (property === 'key') { - return _target[property]; - } - - // prevent Safari from locking up when the proxy is used in dev tools - // as it doesn't support getPrototypeOf - if (property === '__proto__') return {}; - - const target = property === 'root' ? _target : _target.model || _target; - // @ts-ignore `string` index signature - const value = target[property]; - if (isObject(value) && !Array.isArray(value)) { - return new Proxy( - { - model: value, - root: _target.root, - key: `_${_target.key}`, - }, - handler - ); - } else { - return value; - } - }, - - set(target: any) { - return target; - }, - - deleteProperty(target: any) { - return target; - }, - - ownKeys(target) { - return Reflect.ownKeys(target.model); - }, - - apply(target: any) { - return target; - }, - - construct(target: any) { - return target; - }, - }; - const themeProxy = new Proxy({ model, root: model, key }, handler); - - return themeProxy; -}; - -/** - * Deeply merges two objects, using `source` values whenever possible. - * @param {object} _target - Object with fallback values - * @param {object} source - Object with desired values - */ -export const mergeDeep = ( - _target: { [key: string]: any }, - source: { [key: string]: any } = {} -) => { - const target = { ..._target }; - - if (!isObject(target) || !isObject(source)) { - return source; - } - - Object.keys(source).forEach((key) => { - const targetValue = target[key]; - const sourceValue = source[key]; - - if (isObject(targetValue) && isObject(sourceValue)) { - target[key] = mergeDeep({ ...targetValue }, { ...sourceValue }); - } else { - target[key] = sourceValue; - } - }); - - return target; -}; diff --git a/packages/eui-theme-base/src/variables/_animations.scss b/packages/eui-theme-base/src/variables/_animations.scss deleted file mode 100644 index 93b9daf1641..00000000000 --- a/packages/eui-theme-base/src/variables/_animations.scss +++ /dev/null @@ -1,13 +0,0 @@ -// Animations - -$euiAnimSlightBounce: cubic-bezier(.34, 1.61, .7, 1) !default; -$euiAnimSlightResistance: cubic-bezier(.694, .0482, .335, 1) !default; - -$euiAnimSpeedExtraFast: 90ms !default; -$euiAnimSpeedFast: 150ms !default; -$euiAnimSpeedNormal: 250ms !default; -$euiAnimSpeedSlow: 350ms !default; -$euiAnimSpeedExtraSlow: 500ms !default; - -// Keyframe animation declarations can be found in -// eui/utility/animations.scss diff --git a/packages/eui-theme-base/src/variables/_borders.scss b/packages/eui-theme-base/src/variables/_borders.scss deleted file mode 100644 index 6fa0216ff3b..00000000000 --- a/packages/eui-theme-base/src/variables/_borders.scss +++ /dev/null @@ -1,11 +0,0 @@ -// Borders - -$euiBorderWidthThin: 1px !default; -$euiBorderWidthThick: 2px !default; - -$euiBorderColor: $euiColorLightShade !default; -$euiBorderRadius: $euiSizeS * .75 !default; -$euiBorderRadiusSmall: $euiSizeS * .5 !default; -$euiBorderThick: $euiBorderWidthThick solid $euiBorderColor !default; -$euiBorderThin: $euiBorderWidthThin solid $euiBorderColor !default; -$euiBorderEditable: $euiBorderWidthThick dotted $euiBorderColor !default; diff --git a/packages/eui-theme-base/src/variables/_buttons.scss b/packages/eui-theme-base/src/variables/_buttons.scss deleted file mode 100644 index 4d4e8a5f0b1..00000000000 --- a/packages/eui-theme-base/src/variables/_buttons.scss +++ /dev/null @@ -1,18 +0,0 @@ -$euiButtonHeight: $euiSizeXXL !default; -$euiButtonHeightSmall: $euiSizeXL !default; -$euiButtonHeightXSmall: $euiSizeL !default; - -// Modifier naming and colors. -$euiButtonTypes: ( - primary: $euiColorPrimary, - accent: $euiColorAccent, - success: $euiColorSuccess, - warning: $euiColorWarning, - danger: $euiColorDanger, - ghost: $euiColorGhost, // Ghost is special, and does not care about theming. - text: $euiColorDarkShade, // Reserved for special use cases -) !default; - -// TODO: Remove this once elastic-charts no longer uses this variable -// @see https://github.com/elastic/elastic-charts/pull/2528 -$euiButtonColorDisabledText: $euiColorDisabledText; diff --git a/packages/eui-theme-base/src/variables/_colors_vis.scss b/packages/eui-theme-base/src/variables/_colors_vis.scss deleted file mode 100644 index cfffdf5e55d..00000000000 --- a/packages/eui-theme-base/src/variables/_colors_vis.scss +++ /dev/null @@ -1,72 +0,0 @@ -// Visualization colors -// stylelint-disable color-no-hex - -// Maps allow for easier JSON usage -// Use map_merge($euiColorVisColors, $yourMap) to change individual colors after importing ths file -// The `behindText` variant is a direct copy of the hex output by the JS euiPaletteColorBlindBehindText() function -$euiPaletteColorBlind: ( - euiColorVis0: ( - graphic: #54B399, - behindText: #6DCCB1, - ), - euiColorVis1: ( - graphic: #6092C0, - behindText: #79AAD9, - ), - euiColorVis2: ( - graphic: #D36086, - behindText: #EE789D, - ), - euiColorVis3: ( - graphic: #9170B8, - behindText: #A987D1, - ), - euiColorVis4: ( - graphic: #CA8EAE, - behindText: #E4A6C7, - ), - euiColorVis5: ( - graphic: #D6BF57, - behindText: #F1D86F, - ), - euiColorVis6: ( - graphic: #B9A888, - behindText: #D2C0A0, - ), - euiColorVis7: ( - graphic: #DA8B45, - behindText: #F5A35C, - ), - euiColorVis8: ( - graphic: #AA6556, - behindText: #C47C6C, - ), - euiColorVis9: ( - graphic: #E7664C, - behindText: #FF7E62, - ) -) !default; - -$euiPaletteColorBlindKeys: map-keys($euiPaletteColorBlind); - -$euiColorVis0: map-get(map-get($euiPaletteColorBlind, 'euiColorVis0'), 'graphic') !default; -$euiColorVis1: map-get(map-get($euiPaletteColorBlind, 'euiColorVis1'), 'graphic') !default; -$euiColorVis2: map-get(map-get($euiPaletteColorBlind, 'euiColorVis2'), 'graphic') !default; -$euiColorVis3: map-get(map-get($euiPaletteColorBlind, 'euiColorVis3'), 'graphic') !default; -$euiColorVis4: map-get(map-get($euiPaletteColorBlind, 'euiColorVis4'), 'graphic') !default; -$euiColorVis5: map-get(map-get($euiPaletteColorBlind, 'euiColorVis5'), 'graphic') !default; -$euiColorVis6: map-get(map-get($euiPaletteColorBlind, 'euiColorVis6'), 'graphic') !default; -$euiColorVis7: map-get(map-get($euiPaletteColorBlind, 'euiColorVis7'), 'graphic') !default; -$euiColorVis8: map-get(map-get($euiPaletteColorBlind, 'euiColorVis8'), 'graphic') !default; -$euiColorVis9: map-get(map-get($euiPaletteColorBlind, 'euiColorVis9'), 'graphic') !default; - -$euiColorVis0_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis0'), 'behindText') !default; -$euiColorVis1_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis1'), 'behindText') !default; -$euiColorVis2_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis2'), 'behindText') !default; -$euiColorVis3_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis3'), 'behindText') !default; -$euiColorVis4_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis4'), 'behindText') !default; -$euiColorVis5_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis5'), 'behindText') !default; -$euiColorVis6_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis6'), 'behindText') !default; -$euiColorVis7_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis7'), 'behindText') !default; -$euiColorVis8_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis8'), 'behindText') !default; -$euiColorVis9_behindText: map-get(map-get($euiPaletteColorBlind, 'euiColorVis9'), 'behindText') !default; diff --git a/packages/eui-theme-base/src/variables/_colors_vis.ts b/packages/eui-theme-base/src/variables/_colors_vis.ts deleted file mode 100644 index 4459b04ff8c..00000000000 --- a/packages/eui-theme-base/src/variables/_colors_vis.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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. - */ - -/** - * NOTE: These were quick conversions of their Sass counterparts. - * They have yet to be used/tested. - * TODO: Make the graphic version available from `euiPaletteColorBlind()` - */ - -// Maps allow for easier JSON usage -// Use map_merge(euiColorVisColors, $yourMap) to change individual colors after importing ths file -// The `behindText` variant is a direct copy of the hex output by the JS euiPaletteColorBlindBehindText() function -const euiPaletteColorBlind = { - euiColorVis0: { - graphic: '#54B399', - }, - euiColorVis1: { - graphic: '#6092C0', - }, - euiColorVis2: { - graphic: '#D36086', - }, - euiColorVis3: { - graphic: '#9170B8', - }, - euiColorVis4: { - graphic: '#CA8EAE', - }, - euiColorVis5: { - graphic: '#D6BF57', - }, - euiColorVis6: { - graphic: '#B9A888', - }, - euiColorVis7: { - graphic: '#DA8B45', - }, - euiColorVis8: { - graphic: '#AA6556', - }, - euiColorVis9: { - graphic: '#E7664C', - }, -}; - -export const colorVis = { - euiColorVis0: euiPaletteColorBlind.euiColorVis0.graphic, - euiColorVis1: euiPaletteColorBlind.euiColorVis1.graphic, - euiColorVis2: euiPaletteColorBlind.euiColorVis2.graphic, - euiColorVis3: euiPaletteColorBlind.euiColorVis3.graphic, - euiColorVis4: euiPaletteColorBlind.euiColorVis4.graphic, - euiColorVis5: euiPaletteColorBlind.euiColorVis5.graphic, - euiColorVis6: euiPaletteColorBlind.euiColorVis6.graphic, - euiColorVis7: euiPaletteColorBlind.euiColorVis7.graphic, - euiColorVis8: euiPaletteColorBlind.euiColorVis8.graphic, - euiColorVis9: euiPaletteColorBlind.euiColorVis9.graphic, -}; diff --git a/packages/eui-theme-base/src/variables/_font_weight.scss b/packages/eui-theme-base/src/variables/_font_weight.scss deleted file mode 100644 index f5dfd287835..00000000000 --- a/packages/eui-theme-base/src/variables/_font_weight.scss +++ /dev/null @@ -1,10 +0,0 @@ -// Separated out to its own file for easy import into docs - -// Font weights -$euiFontWeightLight: 300 !default; -$euiFontWeightRegular: 400 !default; -$euiFontWeightMedium: 500 !default; -$euiFontWeightSemiBold: 600 !default; -$euiFontWeightBold: 700 !default; -$euiCodeFontWeightRegular: 400 !default; -$euiCodeFontWeightBold: 700 !default; diff --git a/packages/eui-theme-base/src/variables/_form.scss b/packages/eui-theme-base/src/variables/_form.scss deleted file mode 100644 index 41c5dfad04e..00000000000 --- a/packages/eui-theme-base/src/variables/_form.scss +++ /dev/null @@ -1,21 +0,0 @@ -// Sizing -$euiFormMaxWidth: $euiSizeXXL * 10 !default; -$euiFormControlHeight: $euiSizeXXL !default; -$euiFormControlCompressedHeight: $euiSizeXL !default; -$euiFormControlPadding: $euiSizeM !default; -$euiFormControlCompressedPadding: $euiSizeS !default; -$euiFormControlBorderRadius: $euiBorderRadius !default; -$euiFormControlCompressedBorderRadius: $euiBorderRadiusSmall !default; - -// Coloring -$euiFormBackgroundColor: tintOrShade($euiColorLightestShade, 60%, 40%) !default; -$euiFormBackgroundDisabledColor: darken($euiColorLightestShade, 2%) !default; -$euiFormBackgroundReadOnlyColor: $euiColorEmptyShade !default; -$euiFormBorderOpaqueColor: shadeOrTint(desaturate(adjust-hue($euiColorPrimary, 22), 22.95), 26%, 100%) !default; -$euiFormBorderColor: transparentize($euiFormBorderOpaqueColor, .9) !default; -$euiFormBorderDisabledColor: transparentize($euiFormBorderOpaqueColor, .9) !default; -$euiFormControlDisabledColor: $euiColorMediumShade !default; -$euiFormControlBoxShadow: 0 0 transparent !default; -$euiFormControlPlaceholderText: makeHighContrastColor($euiTextSubduedColor, $euiFormBackgroundColor) !default; -$euiFormInputGroupLabelBackground: tintOrShade($euiColorLightShade, 50%, 15%) !default; -$euiFormInputGroupBorder: none !default; \ No newline at end of file diff --git a/packages/eui-theme-base/src/variables/_index.scss b/packages/eui-theme-base/src/variables/_index.scss deleted file mode 100644 index 993979a78a5..00000000000 --- a/packages/eui-theme-base/src/variables/_index.scss +++ /dev/null @@ -1,23 +0,0 @@ -// -------------------------------------------------------------------------------------- -// EUI global variables -// -------------------------------------------------------------------------------------- -// This module contains all global variables available within EUI. Every variable in this -// document should be prefixed with $eui. This lets us know where the variable is -// coming from when looking inside the individual component files. Any component local -// variables should be declared at the top of those documents prefixed with $componentName. - -// Global colors are established and importer per theme, before this manifest -// Import order is important. Size, vis colors, ...etc are used in other variables. -@import 'size'; -@import 'colors_vis'; -@import 'animations'; -@import 'font_weight'; -@import 'typography'; -@import 'borders'; -@import 'responsive'; -@import 'shadows'; -@import 'states'; -@import 'z_index'; - -@import 'buttons'; -@import 'form'; diff --git a/packages/eui-theme-base/src/variables/_responsive.scss b/packages/eui-theme-base/src/variables/_responsive.scss deleted file mode 100644 index de6e8ca5b83..00000000000 --- a/packages/eui-theme-base/src/variables/_responsive.scss +++ /dev/null @@ -1,9 +0,0 @@ -$euiBreakpoints: ( - 'xs': 0, - 's': 575px, - 'm': 768px, - 'l': 992px, - 'xl': 1200px -) !default; - -$euiBreakpointKeys: map-keys($euiBreakpoints); diff --git a/packages/eui-theme-base/src/variables/_shadows.scss b/packages/eui-theme-base/src/variables/_shadows.scss deleted file mode 100644 index 05e445f27a1..00000000000 --- a/packages/eui-theme-base/src/variables/_shadows.scss +++ /dev/null @@ -1,2 +0,0 @@ -// Shadows -$euiShadowColor: $euiColorInk !default; diff --git a/packages/eui-theme-base/src/variables/_size.scss b/packages/eui-theme-base/src/variables/_size.scss deleted file mode 100644 index f07645832d1..00000000000 --- a/packages/eui-theme-base/src/variables/_size.scss +++ /dev/null @@ -1,15 +0,0 @@ -$euiSize: 16px !default; - -$euiSizeXS: $euiSize * .25 !default; -$euiSizeS: $euiSize * .5 !default; -$euiSizeM: $euiSize * .75 !default; -$euiSizeL: $euiSize * 1.5 !default; -$euiSizeXL: $euiSize * 2 !default; -$euiSizeXXL: $euiSize * 2.5 !default; - -$euiButtonMinWidth: $euiSize * 7 !default; - -$euiScrollBar: $euiSize !default; -// Corner sizes are used as an inset border and therefore a smaller corner size means a larger thumb -$euiScrollBarCorner: $euiSizeXS !default; -$euiScrollBarCornerThin: $euiSizeS * .75 !default; diff --git a/packages/eui-theme-base/src/variables/_states.scss b/packages/eui-theme-base/src/variables/_states.scss deleted file mode 100644 index fba4cc59caa..00000000000 --- a/packages/eui-theme-base/src/variables/_states.scss +++ /dev/null @@ -1,14 +0,0 @@ -// Colors -$euiFocusRingColor: rgba($euiColorPrimary, .3) !default; -$euiFocusRingAnimStartColor: rgba($euiColorPrimary, 0) !default; -$euiFocusRingAnimStartSize: 6px !default; -$euiFocusRingAnimStartSizeLarge: 10px !default; - -// Sizing -$euiFocusRingSizeLarge: $euiSizeXS !default; -$euiFocusRingSize: $euiFocusRingSizeLarge * .75 !default; - -// Transparency -$euiFocusTransparency: lightOrDarkTheme(.1, .2) !default; -$euiFocusTransparencyPercent: lightOrDarkTheme(90%, 80%) !default; -$euiFocusBackgroundColor: tintOrShade($euiColorPrimary, $euiFocusTransparencyPercent, $euiFocusTransparencyPercent) !default; diff --git a/packages/eui-theme-base/src/variables/_typography.scss b/packages/eui-theme-base/src/variables/_typography.scss deleted file mode 100644 index 1ca62f3248c..00000000000 --- a/packages/eui-theme-base/src/variables/_typography.scss +++ /dev/null @@ -1,75 +0,0 @@ -// Families -$euiFontFamily: 'Inter', BlinkMacSystemFont, Helvetica, Arial, sans-serif !default; -$euiCodeFontFamily: 'Roboto Mono', Menlo, Courier, monospace !default; - -// Careful using ligatures. Code editors like ACE will often error because of width calculations -$euiFontFeatureSettings: 'calt' 1, 'kern' 1, 'liga' 1 !default; - -// Font sizes -- scale is loosely based on Major Third (1.250) -$euiTextScale: 2.25, 1.75, 1.25, 1.125, 1, .875, .75 !default; - -$euiFontSize: $euiSize !default; // 5th position in scale -$euiFontSizeXS: $euiFontSize * nth($euiTextScale, 7) !default; // 12px -$euiFontSizeS: $euiFontSize * nth($euiTextScale, 6) !default; // 14px -$euiFontSizeM: $euiFontSize * nth($euiTextScale, 4) !default; // 18px -$euiFontSizeL: $euiFontSize * nth($euiTextScale, 3) !default; // 20px -$euiFontSizeXL: $euiFontSize * nth($euiTextScale, 2) !default; // 28px -$euiFontSizeXXL: $euiFontSize * nth($euiTextScale, 1) !default; // 36px - -// Line height -$euiLineHeight: 1.5 !default; -$euiBodyLineHeight: 1 !default; - -// Normally functions are imported before variables in `_index.scss` files -// But because they need to consume some typography variables they need to live here -@function convertToRem($size) { - @return #{$size / $euiFontSize}rem; -} - -// Our base gridline is at 1/2 the font-size, ensure line-heights stay on that gridline. -// EX: A proper line-height for text is 1.5 times the font-size. -// If our base font size (euiFontSize) is 16, our baseline is 8 (16*1.5 / 3). To ensure the -// text stays on the baseline, we pass a multiplier to calculate a line-height in rems. -@function lineHeightFromBaseline($multiplier: 3) { - @return convertToRem(($euiFontSize / 2) * $multiplier); -} - -// Titles map -// Lists all the properties per EuiTitle size that then gets looped through to create the selectors. -// The map allows for tokenization and easier customization per theme, otherwise you'd have to override the selectors themselves -$euiTitles: ( - 'xxxs': ( - 'font-size': $euiFontSizeXS, - 'line-height': lineHeightFromBaseline(3), - 'font-weight': $euiFontWeightBold, - ), - 'xxs': ( - 'font-size': $euiFontSizeS, - 'line-height': lineHeightFromBaseline(3), - 'font-weight': $euiFontWeightBold, - ), - 'xs': ( - 'font-size': $euiFontSize, - 'line-height': lineHeightFromBaseline(3), - 'font-weight': $euiFontWeightSemiBold, - 'letter-spacing': -.02em, - ), - 's': ( - 'font-size': $euiFontSizeL, - 'line-height': lineHeightFromBaseline(4), - 'font-weight': $euiFontWeightMedium, - 'letter-spacing': -.025em, - ), - 'm': ( - 'font-size': $euiFontSizeXL, - 'line-height': lineHeightFromBaseline(5), - 'font-weight': $euiFontWeightLight, - 'letter-spacing': -.04em, - ), - 'l': ( - 'font-size': $euiFontSizeXXL, - 'line-height': lineHeightFromBaseline(6), - 'font-weight': $euiFontWeightLight, - 'letter-spacing': -.03em, - ), -) !default; diff --git a/packages/eui-theme-base/src/variables/_z_index.scss b/packages/eui-theme-base/src/variables/_z_index.scss deleted file mode 100644 index 2448a34c61a..00000000000 --- a/packages/eui-theme-base/src/variables/_z_index.scss +++ /dev/null @@ -1,34 +0,0 @@ -// Z-Index - -// Remember that z-index is relative to parent and based on the stacking context. -// z-indexes only compete against other z-indexes when they exist as children of -// that shared parent. - -// That means a popover with a settings of 2, will still show above a modal -// with a setting of 100, if it is within that modal and not besides it. - -// Generally that means it's a good idea to consider things added to this file -// as competitive only as siblings. - -// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context - -$euiZLevel0: 0; -$euiZLevel1: 1000; -$euiZLevel2: 2000; -$euiZLevel3: 3000; -$euiZLevel4: 4000; -$euiZLevel5: 5000; -$euiZLevel6: 6000; -$euiZLevel7: 7000; -$euiZLevel8: 8000; -$euiZLevel9: 9000; - -$euiZToastList: $euiZLevel9; -$euiZModal: $euiZLevel8; -$euiZMask: $euiZLevel6; -$euiZNavigation: $euiZLevel6; -$euiZContentMenu: $euiZLevel2; -$euiZHeader: $euiZLevel1; -$euiZFlyout: $euiZHeader; -$euiZMaskBelowHeader: $euiZHeader; -$euiZContent: $euiZLevel0; diff --git a/packages/eui-theme-base/src/variables/animations.ts b/packages/eui-theme-base/src/variables/animations.ts deleted file mode 100644 index 46bce009c92..00000000000 --- a/packages/eui-theme-base/src/variables/animations.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 { CSSProperties } from 'react'; - -/** - * A constant storing the `prefers-reduced-motion` media query - * so that when it is turned off, animations are not run. - */ -export const euiCanAnimate = - '@media screen and (prefers-reduced-motion: no-preference)'; - -/** - * A constant storing the `prefers-reduced-motion` media query that will - * only apply the content if the setting is off (reduce). - */ -export const euiCantAnimate = - '@media screen and (prefers-reduced-motion: reduce)'; - -/** - * Speeds / Durations / Delays - */ - -export const EuiThemeAnimationSpeeds = [ - 'extraFast', - 'fast', - 'normal', - 'slow', - 'extraSlow', -] as const; - -export type _EuiThemeAnimationSpeed = (typeof EuiThemeAnimationSpeeds)[number]; - -export type _EuiThemeAnimationSpeeds = { - /** - Default value: 90ms */ - extraFast: CSSProperties['animationDuration']; - /** - Default value: 150ms */ - fast: CSSProperties['animationDuration']; - /** - Default value: 250ms */ - normal: CSSProperties['animationDuration']; - /** - Default value: 350ms */ - slow: CSSProperties['animationDuration']; - /** - Default value: 500ms */ - extraSlow: CSSProperties['animationDuration']; -}; - -/** - * Easings / Timing functions - */ - -export const EuiThemeAnimationEasings = ['bounce', 'resistance'] as const; - -export type _EuiThemeAnimationEasing = - (typeof EuiThemeAnimationEasings)[number]; - -export type _EuiThemeAnimationEasings = Record< - _EuiThemeAnimationEasing, - CSSProperties['animationTimingFunction'] ->; - -export type _EuiThemeAnimation = _EuiThemeAnimationEasings & - _EuiThemeAnimationSpeeds; diff --git a/packages/eui-theme-base/src/variables/borders.ts b/packages/eui-theme-base/src/variables/borders.ts deleted file mode 100644 index 3673010aba2..00000000000 --- a/packages/eui-theme-base/src/variables/borders.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 { CSSProperties } from 'react'; -import { ColorModeSwitch } from '../types'; - -export interface _EuiThemeBorderWidthValues { - /** - * Thinnest width for border - * - Default value: 1px - */ - thin: CSSProperties['borderWidth']; - /** - * Thickest width for border - * - Default value: 2px - */ - thick: CSSProperties['borderWidth']; -} - -export interface _EuiThemeBorderRadiusValues { - /** - * Primary corner radius size - * - Default value: 6px - */ - medium: CSSProperties['borderRadius']; - /** - * Small corner radius size - * - Default value: 4px - */ - small: CSSProperties['borderRadius']; -} - -export interface _EuiThemeBorderColorValues { - /** - * Color for all borders; Default is `colors.lightShade` - */ - color: ColorModeSwitch; -} - -export interface _EuiThemeBorderValues extends _EuiThemeBorderColorValues { - /** - * Varied thicknesses for borders - */ - width: _EuiThemeBorderWidthValues; - /** - * Varied border radii - */ - radius: _EuiThemeBorderRadiusValues; -} - -export interface _EuiThemeBorderTypes { - /** - * Full `border` property string computed using `border.width.thin` and `border.color` - * - Default value: 1px solid [colors.lightShade] - */ - thin: CSSProperties['border']; - /** - * Full `border` property string computed using `border.width.thick` and `border.color` - * - Default value: 2px solid [colors.lightShade] - */ - thick: CSSProperties['border']; - /** - * Full editable style `border` property string computed using `border.width.thick` and `border.color` - * - Default value: 2px dotted [colors.lightShade] - */ - editable: CSSProperties['border']; -} - -export type _EuiThemeBorder = _EuiThemeBorderValues & _EuiThemeBorderTypes; diff --git a/packages/eui-theme-base/src/variables/breakpoint.ts b/packages/eui-theme-base/src/variables/breakpoint.ts deleted file mode 100644 index 68aef1fba38..00000000000 --- a/packages/eui-theme-base/src/variables/breakpoint.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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. - */ - -export const EuiThemeBreakpoints = ['xs', 's', 'm', 'l', 'xl'] as const; - -// This type cannot be a string enum / must be a generic string -// in case consumers add custom breakpoint sizes, such as xxl or xxs -export type _EuiThemeBreakpoint = string; - -// Explicitly list out each key so we can document default values -// via JSDoc (which is available to devs in IDE via intellisense) -export type _EuiThemeBreakpoints = Record<_EuiThemeBreakpoint, number> & { - /** - Default value: 0 */ - xs: number; - /** - Default value: 575 */ - s: number; - /** - Default value: 768 */ - m: number; - /** - Default value: 992 */ - l: number; - /** - Default value: 1200 */ - xl: number; -}; diff --git a/packages/eui-theme-base/src/variables/colors.ts b/packages/eui-theme-base/src/variables/colors.ts deleted file mode 100644 index 8604ecafba4..00000000000 --- a/packages/eui-theme-base/src/variables/colors.ts +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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 { ColorModeSwitch, StrictColorModeSwitch } from '../types'; - -/** - * Top 5 colors - */ -export type _EuiThemeBrandColors = { - /** - * Main brand color and used for most **call to actions** like buttons and links. - */ - primary: ColorModeSwitch; - /** - * Pulls attention to key indicators like **notifications** or number of selections. - */ - accent: ColorModeSwitch; - /** - * Used for **positive** messages/graphics and additive actions. - */ - success: ColorModeSwitch; - /** - * Used for **warnings** and actions that have a potential to be destructive. - */ - warning: ColorModeSwitch; - /** - * Used for **negative** messages/graphics like errors and destructive actions. - */ - danger: ColorModeSwitch; -}; - -/** - * Every brand color must have a contrast computed text equivelant - */ -export type _EuiThemeBrandTextColors = { - /** - * Typically computed against `colors.primary` - */ - primaryText: ColorModeSwitch; - /** - * Typically computed against `colors.accent` - */ - accentText: ColorModeSwitch; - /** - * Typically computed against `colors.success` - */ - successText: ColorModeSwitch; - /** - * Typically computed against `colors.warning` - */ - warningText: ColorModeSwitch; - /** - * Typically computed against `colors.danger` - */ - dangerText: ColorModeSwitch; -}; - -export type _EuiThemeShadeColors = { - /** - * Used as the background color of primary **page content and panels** including modals and flyouts. - */ - emptyShade: ColorModeSwitch; - /** - * Used to lightly shade areas that contain **secondary content** or contain panel-like components. - */ - lightestShade: ColorModeSwitch; - /** - * Used for most **borders** and dividers (horizontal rules). - */ - lightShade: ColorModeSwitch; - /** - * The middle gray for all themes; this is the base for `colors.subdued`. - */ - mediumShade: ColorModeSwitch; - /** - * Slightly subtle graphic color - */ - darkShade: ColorModeSwitch; - /** - * Used as the **text** color and the background color for **inverted components** like tooltips and the control bar. - */ - darkestShade: ColorModeSwitch; - /** - * The opposite of `emptyShade` - */ - fullShade: ColorModeSwitch; -}; - -export type _EuiThemeTextColors = { - /** - * Computed against `colors.darkestShade` - */ - text: ColorModeSwitch; - /** - * Computed against `colors.text` - */ - title: ColorModeSwitch; - /** - * Computed against `colors.mediumShade` - */ - subduedText: ColorModeSwitch; - /** - * Computed against `colors.primaryText` - */ - link: ColorModeSwitch; -}; - -export type _EuiThemeSpecialColors = { - /** - * The background color for the **whole window (body)** and is a computed value of `colors.lightestShade`. - * Provides denominator (background) value for **contrast calculations**. - */ - body: ColorModeSwitch; - /** - * Used to **highlight text** when matching against search strings - */ - highlight: ColorModeSwitch; - /** - * Computed against `colors.darkestShade` - */ - disabled: ColorModeSwitch; - /** - * Computed against `colors.disabled` - */ - disabledText: ColorModeSwitch; - /** - * The base color for shadows that gets `transparentized` - * at a value based on the `colorMode` and then layered. - */ - shadow: ColorModeSwitch; -}; - -export type _EuiThemeConstantColors = { - /** - * Purest **white** - */ - ghost: string; - /** - * Purest **black** - */ - ink: string; -}; - -export type _EuiThemeColorsMode = _EuiThemeBrandColors & - _EuiThemeBrandTextColors & - _EuiThemeShadeColors & - _EuiThemeSpecialColors & - _EuiThemeTextColors; - -export type _EuiThemeColors = StrictColorModeSwitch<_EuiThemeColorsMode> & - _EuiThemeConstantColors; diff --git a/packages/eui-theme-base/src/variables/index.ts b/packages/eui-theme-base/src/variables/index.ts deleted file mode 100644 index 48eacef5cbb..00000000000 --- a/packages/eui-theme-base/src/variables/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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. - */ - -export * from './animations'; -export * from './borders'; -export * from './breakpoint'; -export * from './colors'; -export * from './_colors_vis'; -export * from './levels'; -export * from './size'; -export * from './shadow'; -export * from './states'; -export * from './typography'; diff --git a/packages/eui-theme-base/src/variables/levels.ts b/packages/eui-theme-base/src/variables/levels.ts deleted file mode 100644 index 7d38c71791b..00000000000 --- a/packages/eui-theme-base/src/variables/levels.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 { CSSProperties } from 'react'; - -/** - * Z-Index - * - * Remember that z-index is relative to parent and based on the stacking context. - * z-indexes only compete against other z-indexes when they exist as children of - * that shared parent. - * - * That means a popover with a settings of 2, will still show above a modal - * with a setting of 100, if it is within that modal and not besides it. - * - * Generally that means it's a good idea to consider things added to this file - * as competitive only as siblings. - * - * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context - */ - -export const EuiThemeLevels = [ - 'toast', - 'modal', - 'mask', - 'navigation', - 'menu', - 'header', - 'flyout', - 'maskBelowHeader', - 'content', -] as const; - -export type _EuiThemeLevel = (typeof EuiThemeLevels)[number]; - -export type _EuiThemeLevels = { - /** - Default value: 9000 */ - toast: NonNullable; - /** - Default value: 8000 */ - modal: NonNullable; - /** - Default value: 6000 */ - mask: NonNullable; - /** - Default value: 6000 */ - navigation: NonNullable; - /** - Default value: 2000 */ - menu: NonNullable; - /** - Default value: 1000 */ - header: NonNullable; - /** - Default value: 1000 */ - flyout: NonNullable; - /** - Default value: 1000 */ - maskBelowHeader: NonNullable; - /** - Default value: 0 */ - content: NonNullable; -}; diff --git a/packages/eui-theme-base/src/variables/shadow.ts b/packages/eui-theme-base/src/variables/shadow.ts deleted file mode 100644 index 7761fbdb9a0..00000000000 --- a/packages/eui-theme-base/src/variables/shadow.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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. - */ - -export const EuiThemeShadowSizes = ['xs', 's', 'm', 'l', 'xl'] as const; - -export type _EuiThemeShadowSize = (typeof EuiThemeShadowSizes)[number]; - -/** - * Shadow t-shirt sizes descriptions - */ -export const _EuiShadowSizesDescriptions: Record<_EuiThemeShadowSize, string> = - { - xs: 'Very subtle shadow used on small components.', - s: 'Adds subtle depth, usually used in conjunction with a border.', - m: 'Used on small sized portalled content like popovers.', - l: 'Primary shadow used in most cases to add visible depth.', - xl: 'Very large shadows used for large portalled style containers like modals and flyouts.', - }; - -export interface _EuiThemeShadowCustomColor { - color?: string; - property?: 'box-shadow' | 'filter'; -} diff --git a/packages/eui-theme-base/src/variables/size.ts b/packages/eui-theme-base/src/variables/size.ts deleted file mode 100644 index 98428346b61..00000000000 --- a/packages/eui-theme-base/src/variables/size.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - */ - -export type _EuiThemeBase = number; - -export const EuiThemeSizes = [ - 'xxs', - 'xs', - 's', - 'm', - 'base', - 'l', - 'xl', - 'xxl', - 'xxxl', - 'xxxxl', -] as const; - -export type _EuiThemeSize = (typeof EuiThemeSizes)[number]; - -export type _EuiThemeSizes = { - /** - Default value: 2px */ - xxs: string; - /** - Default value: 4px */ - xs: string; - /** - Default value: 8px */ - s: string; - /** - Default value: 12px */ - m: string; - /** - Default value: 16px */ - base: string; - /** - Default value: 24px */ - l: string; - /** - Default value: 32px */ - xl: string; - /** - Default value: 40px */ - xxl: string; - /** - Default value: 48px */ - xxxl: string; - /** - Default value: 64px */ - xxxxl: string; -}; diff --git a/packages/eui-theme-base/src/variables/states.ts b/packages/eui-theme-base/src/variables/states.ts deleted file mode 100644 index 2d0283ac949..00000000000 --- a/packages/eui-theme-base/src/variables/states.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 { CSSProperties } from 'react'; -import { ColorModeSwitch } from '../types'; - -export interface _EuiThemeFocus { - /** - * Default color of the focus ring, some components may override this property - * - Default value: currentColor - */ - color: ColorModeSwitch; - /** - * Thickness of the outline - * - Default value: 2px - */ - width: CSSProperties['borderWidth']; - /** - * Used to transparentize the focus background color - * - Default value: { LIGHT: 0.1, DARK: 0.2 } - */ - transparency: ColorModeSwitch; - /** - * Default focus background color. Not all components set a background color on focus - * - Default value: `colors.primary` computed with `focus.transparency` - */ - backgroundColor: ColorModeSwitch; -} diff --git a/packages/eui-theme-base/src/variables/typography.ts b/packages/eui-theme-base/src/variables/typography.ts deleted file mode 100644 index 80ebbc8b1cb..00000000000 --- a/packages/eui-theme-base/src/variables/typography.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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 { CSSProperties } from 'react'; - -/** - * Font units of measure - */ - -export const EuiThemeFontUnits = ['rem', 'px', 'em'] as const; - -export type _EuiThemeFontUnit = (typeof EuiThemeFontUnits)[number]; - -/* - * Font scale - */ - -export const EuiThemeFontScales = [ - 'xxxs', - 'xxs', - 'xs', - 's', - 'm', - 'l', - 'xl', - 'xxl', -] as const; - -export type _EuiThemeFontScale = (typeof EuiThemeFontScales)[number]; - -export type _EuiThemeFontScales = Record<_EuiThemeFontScale, number>; - -/* - * Font base settings - */ - -export type _EuiThemeFontBase = { - /** - * The whole font family stack for all parts of the UI. - * We encourage only customizing the first font in the stack. - */ - family: string; - /** - * The font family used for monospace UI elements like EuiCode - */ - familyCode?: string; - /** - * The font family used for serif UI elements like blockquotes within EuiText - */ - familySerif?: string; - /** - * Controls advanced features OpenType fonts. - * 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` - */ - baseline: number; - /** - * Establishes the ideal line-height percentage, but it is the `baseline` integer that establishes the final pixel/rem value - */ - lineHeightMultiplier: number; -}; - -/* - * Font weights - */ - -export const EuiThemeFontWeights = [ - 'light', - 'regular', - 'medium', - 'semiBold', - 'bold', -] as const; - -export type _EuiThemeFontWeight = (typeof EuiThemeFontWeights)[number]; - -export type _EuiThemeFontWeights = { - /** - Default value: 300 */ - light: CSSProperties['fontWeight']; - /** - Default value: 400 */ - regular: CSSProperties['fontWeight']; - /** - Default value: 500 */ - medium: CSSProperties['fontWeight']; - /** - Default value: 600 */ - semiBold: CSSProperties['fontWeight']; - /** - Default value: 700 */ - bold: CSSProperties['fontWeight']; -}; - -/** - * Body / Base styles - */ - -export interface _EuiThemeBody { - /** - * A sizing key from one of the font scales to set as the base body font-size - */ - scale: _EuiThemeFontScale; - /** - * A font weight key for setting the base body weight - */ - weight: keyof _EuiThemeFontWeights; -} - -/** - * Title styles - */ - -export interface _EuiThemeTitle { - /** - * A font weight key for setting the base weight for titles and headings - */ - weight: keyof _EuiThemeFontWeights; -} - -/* - * Font - */ - -export type _EuiThemeFont = _EuiThemeFontBase & { - scale: _EuiThemeFontScales; - /** - * @see {@link https://eui.elastic.co/#/theming/typography/values%23font-weight | Reference} for more information - */ - weight: _EuiThemeFontWeights; - body: _EuiThemeBody; - title: _EuiThemeTitle; -}; diff --git a/packages/eui-theme-base/tsconfig.cjs.json b/packages/eui-theme-base/tsconfig.cjs.json deleted file mode 100644 index 6becea42efa..00000000000 --- a/packages/eui-theme-base/tsconfig.cjs.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "rootDir": "src", - "outDir": "lib/cjs", - "target": "es6", - "module": "CommonJS", - "lib": [ - "es6", - "DOM" - ], - "moduleResolution": "Node", - "declaration": true, - "sourceMap": true, - "noEmitHelpers": true, - "incremental": true, - "esModuleInterop": true, - "strict": true, - "skipLibCheck": true, - "tsBuildInfoFile": "lib/cjs/.tsbuildinfo", - "importHelpers": false, - }, - "include": [ - "src" - ], - "exclude": [ - "node_modules" - ], -} \ No newline at end of file diff --git a/packages/eui-theme-base/tsconfig.json b/packages/eui-theme-base/tsconfig.json deleted file mode 100644 index 055614f8c47..00000000000 --- a/packages/eui-theme-base/tsconfig.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "rootDir": "src", - "outDir": "lib/esm", - "target": "ES2020", - "module": "ESNext", - "lib": [ - "ESNext", - "DOM" - ], - "moduleResolution": "Node", - "declaration": true, - "sourceMap": true, - "noEmitHelpers": true, - "incremental": true, - "esModuleInterop": true, - "strict": true, - "skipLibCheck": true, - "tsBuildInfoFile": "lib/esm/.tsbuildinfo" - }, - "include": [ - "src" - ], - "exclude": [ - "node_modules" - ], -} \ No newline at end of file diff --git a/packages/eui-theme-base/tsconfig.types.json b/packages/eui-theme-base/tsconfig.types.json deleted file mode 100644 index 54e2031daae..00000000000 --- a/packages/eui-theme-base/tsconfig.types.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "./tsconfig.cjs.json", - "compilerOptions": { - "outDir": "lib/cjs", - "declaration": true, - "declarationMap": true, - "isolatedModules": false, - "noEmit": false, - "allowJs": false, - "emitDeclarationOnly": true - }, - "exclude": ["node_modules", "**/*.test.ts"] -} \ No newline at end of file From 3a16d83310daa7313b4b394c9038fd1d2bfb5438 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Tue, 8 Oct 2024 17:28:16 +0200 Subject: [PATCH 27/32] chore: add min. README --- packages/eui-theme-borealis/README.md | 20 +++++++++++++++++++- packages/eui-theme-common/README.md | 12 +++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/eui-theme-borealis/README.md b/packages/eui-theme-borealis/README.md index f015fcd893a..cb7c237d4a2 100644 --- a/packages/eui-theme-borealis/README.md +++ b/packages/eui-theme-borealis/README.md @@ -1 +1,19 @@ -# `eui-theme-borealis` - A visual EUI theme \ No newline at end of file +# EUI theme **Borealis** + +This package contains specific style tokens for the EUI theme **Borealis** which is exported as `EuiThemeBorealis`. + +## Installing dependencies + +Please run `yarn` to install dependencies: + +```shell +yarn +``` + +## Building helper packages + +Before you run scripts, it's mandatory to build local dependency packages: + +```shell +yarn workspaces foreach -Rti --from @elastic/eui-theme-borealis run build +``` \ No newline at end of file diff --git a/packages/eui-theme-common/README.md b/packages/eui-theme-common/README.md index ff61cce2b64..294446d4b30 100644 --- a/packages/eui-theme-common/README.md +++ b/packages/eui-theme-common/README.md @@ -1 +1,11 @@ -# EUI common theming functionality and styling \ No newline at end of file +# EUI common theming functionality and styling + +This package contains common code related to theming and styling. + +## Installing dependencies + +Please run `yarn` to install dependencies: + +```shell +yarn +``` \ No newline at end of file From ce4e8e1683f3676f419e5e400df8b990d484f6f4 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Tue, 8 Oct 2024 17:28:33 +0200 Subject: [PATCH 28/32] build: add pre-push scripts --- packages/eui-theme-borealis/package.json | 3 ++- packages/eui-theme-common/package.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/eui-theme-borealis/package.json b/packages/eui-theme-borealis/package.json index 9b9151acb60..d56f9924db2 100644 --- a/packages/eui-theme-borealis/package.json +++ b/packages/eui-theme-borealis/package.json @@ -10,7 +10,8 @@ "lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-sass", "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", "lint-sass": "yarn stylelint \"**/*.scss\" --quiet-deprecation-warnings", - "test": "jest" + "test": "jest", + "pre-push": "yarn build:workspaces && yarn lint && yarn test" }, "repository": { "type": "git", diff --git a/packages/eui-theme-common/package.json b/packages/eui-theme-common/package.json index e4590fefa31..6c255e6a605 100644 --- a/packages/eui-theme-common/package.json +++ b/packages/eui-theme-common/package.json @@ -13,7 +13,8 @@ "lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-sass", "lint-es": "eslint --cache src/**/*.ts --max-warnings 0", "lint-sass": "yarn stylelint \"**/*.scss\" --quiet-deprecation-warnings", - "test": "jest" + "test": "jest", + "pre-push": "yarn lint && yarn test" }, "repository": { "type": "git", From 2532104e6b11c3372ff0af6e05a9b5afeca185a1 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Tue, 8 Oct 2024 19:37:25 +0200 Subject: [PATCH 29/32] build: update workspaces script to ensure theme-common builds first --- packages/eui/package.json | 2 +- packages/website/package.json | 2 +- yarn.lock | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/eui/package.json b/packages/eui/package.json index d627c73c0ee..ba17c438b5b 100644 --- a/packages/eui/package.json +++ b/packages/eui/package.json @@ -16,7 +16,7 @@ ], "scripts": { "start": "cross-env BABEL_MODULES=false webpack serve --config=src-docs/webpack.config.js", - "build:workspaces": "yarn workspaces foreach -Rti --from @elastic/eui --exclude @elastic/eui run build", + "build:workspaces": "yarn workspaces foreach -Rti --from @elastic/eui-theme-common run build && yarn workspaces foreach -Rti --from @elastic/eui --exclude @elastic/eui --exclude @elastic/eui-theme-common run build", "build-docs": "cross-env BABEL_MODULES=false cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 webpack --config=src-docs/webpack.config.js", "build": "node ./scripts/compile-i18n-strings.js && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && yarn compile-scss", "build-pack": "yarn build && npm pack", diff --git a/packages/website/package.json b/packages/website/package.json index f2c30552a03..a4652e87d19 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "docusaurus": "docusaurus", - "build:workspaces": "yarn workspaces foreach -Rti --from @elastic/eui-website run build", + "build:workspaces": "yarn workspaces foreach -R --from @elastic/eui-website run build:workspaces && yarn workspaces foreach -Rti --from @elastic/eui-website run build", "start": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus start", "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider docusaurus build", "swizzle": "docusaurus swizzle", diff --git a/yarn.lock b/yarn.lock index 70a6558708d..a8ea4d35828 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5771,6 +5771,8 @@ __metadata: stylelint-config-standard: "npm:^33.0.0" stylelint-config-standard-scss: "npm:^9.0.0" typescript: "npm:^5.6.2" + peerDependencies: + "@elastic/eui-theme-common": 0.0.1 languageName: unknown linkType: soft @@ -6041,6 +6043,7 @@ __metadata: peerDependencies: "@elastic/datemath": ^5.0.2 "@elastic/eui-theme-borealis": 0.0.1 + "@elastic/eui-theme-common": 0.0.1 "@emotion/css": 11.x "@emotion/react": 11.x "@types/react": ^16.9 || ^17.0 || ^18.0 From 17179a7a2e4ff732c9ea449d244e28bbd9b22517 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Wed, 9 Oct 2024 16:53:16 +0200 Subject: [PATCH 30/32] chore: ignore eslint cache file --- packages/eui-theme-borealis/.eslintcache | 1 - packages/eui-theme-borealis/.gitignore | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) delete mode 100644 packages/eui-theme-borealis/.eslintcache diff --git a/packages/eui-theme-borealis/.eslintcache b/packages/eui-theme-borealis/.eslintcache deleted file mode 100644 index 5231400c151..00000000000 --- a/packages/eui-theme-borealis/.eslintcache +++ /dev/null @@ -1 +0,0 @@ -[{"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/index.ts":"1","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_animation.ts":"2","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_borders.ts":"3","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_breakpoint.ts":"4","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors.ts":"5","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors_dark.ts":"6","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors_light.ts":"7","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_levels.ts":"8","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_size.ts":"9","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_states.ts":"10","/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_typography.ts":"11"},{"size":1110,"mtime":1728391334458,"results":"12","hashOfConfig":"13"},{"size":896,"mtime":1728391334459,"results":"14","hashOfConfig":"13"},{"size":1074,"mtime":1728391334459,"results":"15","hashOfConfig":"13"},{"size":531,"mtime":1728391334460,"results":"16","hashOfConfig":"13"},{"size":637,"mtime":1728391334460,"results":"17","hashOfConfig":"13"},{"size":2144,"mtime":1728391334461,"results":"18","hashOfConfig":"13"},{"size":2143,"mtime":1728391334461,"results":"19","hashOfConfig":"13"},{"size":615,"mtime":1728391334462,"results":"20","hashOfConfig":"13"},{"size":895,"mtime":1728391334462,"results":"21","hashOfConfig":"13"},{"size":744,"mtime":1728391334463,"results":"22","hashOfConfig":"13"},{"size":1576,"mtime":1728391334463,"results":"23","hashOfConfig":"13"},{"filePath":"24","messages":"25","suppressedMessages":"26","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1h5kx7l",{"filePath":"27","messages":"28","suppressedMessages":"29","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"30","messages":"31","suppressedMessages":"32","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"33","messages":"34","suppressedMessages":"35","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"36","messages":"37","suppressedMessages":"38","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"39","messages":"40","suppressedMessages":"41","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"42","messages":"43","suppressedMessages":"44","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"45","messages":"46","suppressedMessages":"47","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"48","messages":"49","suppressedMessages":"50","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"51","messages":"52","suppressedMessages":"53","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"54","messages":"55","suppressedMessages":"56","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/index.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_animation.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_borders.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_breakpoint.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors_dark.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_colors_light.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_levels.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_size.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_states.ts",[],[],"/Users/lenegadewoll/Documents/Projects/eui/packages/eui-theme-borealis/src/variables/_typography.ts",[],[]] \ No newline at end of file diff --git a/packages/eui-theme-borealis/.gitignore b/packages/eui-theme-borealis/.gitignore index 1a3f60d4707..4450fe8d868 100644 --- a/packages/eui-theme-borealis/.gitignore +++ b/packages/eui-theme-borealis/.gitignore @@ -5,4 +5,7 @@ /lib yarn-debug.log* -yarn-error.log* \ No newline at end of file +yarn-error.log* + +# Build-related files +.eslintcache \ No newline at end of file From 16bb57e126c4fd6ab365f7d9f45cbb591407ee51 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Wed, 9 Oct 2024 16:56:10 +0200 Subject: [PATCH 31/32] build: add missing dependencies --- packages/eui-theme-common/package.json | 10 ++++++++++ yarn.lock | 25 +++++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/eui-theme-common/package.json b/packages/eui-theme-common/package.json index 6c255e6a605..2ddafb93b6d 100644 --- a/packages/eui-theme-common/package.json +++ b/packages/eui-theme-common/package.json @@ -28,8 +28,11 @@ "@babel/preset-env": "^7.21.5", "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.21.5", + "@emotion/react": "^11.11.0", "@types/jest": "^29.5.12", "@types/prettier": "2.7.3", + "@types/react": "^16.9 || ^17.0 || ^18.0", + "@types/react-dom": "^16.9 || ^17.0 || ^18.0", "@typescript-eslint/eslint-plugin": "^5.59.7", "@typescript-eslint/parser": "^5.59.7", "eslint": "^8.41.0", @@ -40,6 +43,8 @@ "eslint-plugin-prettier": "^4.2.1", "jest": "^29.7.0", "prettier": "^2.8.8", + "react": "^18.2.0", + "react-dom": "^18.2.0", "rimraf": "^6.0.1", "stylelint": "^15.7.0", "stylelint-config-prettier-scss": "^1.0.0", @@ -47,6 +52,11 @@ "stylelint-config-standard-scss": "^9.0.0", "typescript": "4.5.3" }, + "peerDependencies": { + "@emotion/react": "11.x", + "react": "^16.12 || ^17.0 || ^18.0", + "react-dom": "^16.12 || ^17.0 || ^18.0" + }, "main": "lib/cjs/index.js", "exports": { "./lib/*": "./lib/*", diff --git a/yarn.lock b/yarn.lock index a8ea4d35828..d06703a4038 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5785,8 +5785,11 @@ __metadata: "@babel/preset-env": "npm:^7.21.5" "@babel/preset-react": "npm:^7.18.6" "@babel/preset-typescript": "npm:^7.21.5" + "@emotion/react": "npm:^11.11.0" "@types/jest": "npm:^29.5.12" "@types/prettier": "npm:2.7.3" + "@types/react": "npm:^16.9 || ^17.0 || ^18.0" + "@types/react-dom": "npm:^16.9 || ^17.0 || ^18.0" "@typescript-eslint/eslint-plugin": "npm:^5.59.7" "@typescript-eslint/parser": "npm:^5.59.7" eslint: "npm:^8.41.0" @@ -5797,12 +5800,18 @@ __metadata: eslint-plugin-prettier: "npm:^4.2.1" jest: "npm:^29.7.0" prettier: "npm:^2.8.8" + react: "npm:^18.2.0" + react-dom: "npm:^18.2.0" rimraf: "npm:^6.0.1" stylelint: "npm:^15.7.0" stylelint-config-prettier-scss: "npm:^1.0.0" stylelint-config-standard: "npm:^33.0.0" stylelint-config-standard-scss: "npm:^9.0.0" typescript: "npm:4.5.3" + peerDependencies: + "@emotion/react": 11.x + react: ^16.12 || ^17.0 || ^18.0 + react-dom: ^16.12 || ^17.0 || ^18.0 languageName: unknown linkType: soft @@ -10120,21 +10129,21 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.6": - version: 18.2.6 - resolution: "@types/react-dom@npm:18.2.6" +"@types/react-dom@npm:^16.9 || ^17.0 || ^18.0, @types/react-dom@npm:^18.3.0": + version: 18.3.0 + resolution: "@types/react-dom@npm:18.3.0" dependencies: "@types/react": "npm:*" - checksum: 10c0/bd734ca04c52b3c96891a7f9c1139486807dac7a2449fb72e8f8e23018bc6eeeb87a490a105cb39d05ccb7ddf80ed7a441e5bd3e5866c6f6ae8870cd723599e8 + checksum: 10c0/6c90d2ed72c5a0e440d2c75d99287e4b5df3e7b011838cdc03ae5cd518ab52164d86990e73246b9d812eaf02ec351d74e3b4f5bd325bf341e13bf980392fd53b languageName: node linkType: hard -"@types/react-dom@npm:^18.3.0": - version: 18.3.0 - resolution: "@types/react-dom@npm:18.3.0" +"@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.6": + version: 18.2.6 + resolution: "@types/react-dom@npm:18.2.6" dependencies: "@types/react": "npm:*" - checksum: 10c0/6c90d2ed72c5a0e440d2c75d99287e4b5df3e7b011838cdc03ae5cd518ab52164d86990e73246b9d812eaf02ec351d74e3b4f5bd325bf341e13bf980392fd53b + checksum: 10c0/bd734ca04c52b3c96891a7f9c1139486807dac7a2449fb72e8f8e23018bc6eeeb87a490a105cb39d05ccb7ddf80ed7a441e5bd3e5866c6f6ae8870cd723599e8 languageName: node linkType: hard From 033ed1c6124b2ed9acedaa44b28c3415aa2a0192 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 14 Oct 2024 17:56:01 +0200 Subject: [PATCH 32/32] refactor: udpate sass import order --- packages/eui-theme-borealis/src/theme_dark.scss | 6 ++++-- packages/eui-theme-borealis/src/theme_light.scss | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/eui-theme-borealis/src/theme_dark.scss b/packages/eui-theme-borealis/src/theme_dark.scss index f07a4678b9f..64e6b27d3a0 100644 --- a/packages/eui-theme-borealis/src/theme_dark.scss +++ b/packages/eui-theme-borealis/src/theme_dark.scss @@ -1,6 +1,8 @@ + // color mode specific variables @import './variables/colors_dark'; + // Global styling -@import './variables/index'; -@import 'node_modules/@elastic/eui-theme-common/src/global_styling/index'; \ No newline at end of file +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/index'; +@import './variables/index'; \ No newline at end of file diff --git a/packages/eui-theme-borealis/src/theme_light.scss b/packages/eui-theme-borealis/src/theme_light.scss index 8c6610678e5..29ab275fe73 100644 --- a/packages/eui-theme-borealis/src/theme_light.scss +++ b/packages/eui-theme-borealis/src/theme_light.scss @@ -1,6 +1,7 @@ // color mode specific variables @import './variables/colors_light'; + // Global styling -@import './variables/index'; -@import 'node_modules/@elastic/eui-theme-common/src/global_styling/index'; \ No newline at end of file +@import 'node_modules/@elastic/eui-theme-common/src/global_styling/index'; +@import './variables/index'; \ No newline at end of file