From c44cbc2d2c73560c3d7ca947b9110b55cc8d60c8 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Thu, 22 Feb 2024 13:08:42 -0800 Subject: [PATCH] [mixins] Memoize `useEuiButtonColorCSS` - use nested forEach instead of a function - invert the color/display mapping to make it easier to just return the expected colors obj - use switch + manually tweak Emotion label output to be the same as prod --- .../mixins/__snapshots__/button.test.ts.snap | 162 ++++++++++++++++++ .../global_styling/mixins/button.test.ts | 15 +- .../amsterdam/global_styling/mixins/button.ts | 95 ++++++---- 3 files changed, 234 insertions(+), 38 deletions(-) diff --git a/src/themes/amsterdam/global_styling/mixins/__snapshots__/button.test.ts.snap b/src/themes/amsterdam/global_styling/mixins/__snapshots__/button.test.ts.snap index ca0f33be03e..e1308b7893e 100644 --- a/src/themes/amsterdam/global_styling/mixins/__snapshots__/button.test.ts.snap +++ b/src/themes/amsterdam/global_styling/mixins/__snapshots__/button.test.ts.snap @@ -1,5 +1,167 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`useEuiButtonColorCSS base 1`] = ` +Object { + "accent": Object { + "map": undefined, + "name": "1uoldaz-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#a03465;background-color:#fcdcea;;;label:base-accent;", + "toString": [Function], + }, + "danger": Object { + "map": undefined, + "name": "1cquuvx-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#ab231c;background-color:#f2d4d2;;;label:base-danger;", + "toString": [Function], + }, + "disabled": Object { + "map": undefined, + "name": "13xo60b-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#a2abba;background-color:rgba(211,218,230,0.15);;;label:base-disabled;", + "toString": [Function], + }, + "primary": Object { + "map": undefined, + "name": "1thox14-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#0061a6;background-color:#cce4f5;;;label:base-primary;", + "toString": [Function], + }, + "success": Object { + "map": undefined, + "name": "1j0clgi-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#006c66;background-color:#ccf2f0;;;label:base-success;", + "toString": [Function], + }, + "text": Object { + "map": undefined, + "name": "40srs0-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#343741;background-color:#e9edf3;;;label:base-text;", + "toString": [Function], + }, + "warning": Object { + "map": undefined, + "name": "19dh407-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#83650a;background-color:#fff3d0;;;label:base-warning;", + "toString": [Function], + }, +} +`; + +exports[`useEuiButtonColorCSS empty 1`] = ` +Object { + "accent": Object { + "map": undefined, + "name": "cy4kjs-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#a03465;&:focus,&:active{background-color:rgba(240,78,152,0.1);};label:empty-accent;", + "toString": [Function], + }, + "danger": Object { + "map": undefined, + "name": "j8xrk3-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#ab231c;&:focus,&:active{background-color:rgba(189,39,30,0.1);};label:empty-danger;", + "toString": [Function], + }, + "disabled": Object { + "map": undefined, + "name": "2vymtv-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#a2abba;&:focus,&:active{background-color:transparent;};label:empty-disabled;", + "toString": [Function], + }, + "primary": Object { + "map": undefined, + "name": "15isz8i-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#0061a6;&:focus,&:active{background-color:rgba(0,119,204,0.1);};label:empty-primary;", + "toString": [Function], + }, + "success": Object { + "map": undefined, + "name": "h2w3e9-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#006c66;&:focus,&:active{background-color:rgba(0,191,179,0.1);};label:empty-success;", + "toString": [Function], + }, + "text": Object { + "map": undefined, + "name": "1dqg6bz-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#343741;&:focus,&:active{background-color:rgba(211,218,230,0.2);};label:empty-text;", + "toString": [Function], + }, + "warning": Object { + "map": undefined, + "name": "w61e3r-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#83650a;&:focus,&:active{background-color:rgba(254,197,20,0.1);};label:empty-warning;", + "toString": [Function], + }, +} +`; + +exports[`useEuiButtonColorCSS fill 1`] = ` +Object { + "accent": Object { + "map": undefined, + "name": "vi45v3-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#000;background-color:#f583b7;outline-color:#000;;label:fill-accent;", + "toString": [Function], + }, + "danger": Object { + "map": undefined, + "name": "1ge48z4-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#FFF;background-color:#BD271E;outline-color:#000;;label:fill-danger;", + "toString": [Function], + }, + "disabled": Object { + "map": undefined, + "name": "xc42v8-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#a2abba;background-color:rgba(211,218,230,0.15);outline-color:#000;;label:fill-disabled;", + "toString": [Function], + }, + "primary": Object { + "map": undefined, + "name": "btstjy-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#FFF;background-color:#07C;outline-color:#000;;label:fill-primary;", + "toString": [Function], + }, + "success": Object { + "map": undefined, + "name": "p9aexd-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#000;background-color:#4dd2ca;outline-color:#000;;label:fill-success;", + "toString": [Function], + }, + "text": Object { + "map": undefined, + "name": "5c80s5-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#FFF;background-color:#69707D;outline-color:#000;;label:fill-text;", + "toString": [Function], + }, + "warning": Object { + "map": undefined, + "name": "17xxsr5-displaysColorsMap-display-color", + "next": undefined, + "styles": "color:#000;background-color:#FEC514;outline-color:#000;;label:fill-warning;", + "toString": [Function], + }, +} +`; + exports[`useEuiButtonFocusCSS 1`] = ` Object { "map": undefined, diff --git a/src/themes/amsterdam/global_styling/mixins/button.test.ts b/src/themes/amsterdam/global_styling/mixins/button.test.ts index 1d823355c83..573024762d6 100644 --- a/src/themes/amsterdam/global_styling/mixins/button.test.ts +++ b/src/themes/amsterdam/global_styling/mixins/button.test.ts @@ -8,7 +8,20 @@ import { renderHook } from '@testing-library/react'; -import { useEuiButtonFocusCSS } from './button'; +import { + useEuiButtonColorCSS, + BUTTON_DISPLAYS, + useEuiButtonFocusCSS, +} from './button'; + +describe('useEuiButtonColorCSS', () => { + BUTTON_DISPLAYS.forEach((display) => { + test(display, () => { + const { result } = renderHook(() => useEuiButtonColorCSS({ display })); + expect(result.current).toMatchSnapshot(); + }); + }); +}); test('useEuiButtonFocusCSS', () => { const { result } = renderHook(() => useEuiButtonFocusCSS()); diff --git a/src/themes/amsterdam/global_styling/mixins/button.ts b/src/themes/amsterdam/global_styling/mixins/button.ts index ec0be75454c..373184fde10 100644 --- a/src/themes/amsterdam/global_styling/mixins/button.ts +++ b/src/themes/amsterdam/global_styling/mixins/button.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { css, keyframes } from '@emotion/react'; +import { css, keyframes, type SerializedStyles } from '@emotion/react'; import { euiBackgroundColor, euiCanAnimate } from '../../../../global_styling'; import { hexToRgb, @@ -15,7 +15,6 @@ import { shade, tint, transparentize, - useEuiTheme, UseEuiTheme, useEuiMemoizedStyles, } from '../../../../services'; @@ -28,10 +27,10 @@ export const BUTTON_COLORS = [ 'warning', 'danger', ] as const; - export type _EuiButtonColor = (typeof BUTTON_COLORS)[number]; -export type _EuiButtonDisplay = 'base' | 'fill' | 'empty'; +export const BUTTON_DISPLAYS = ['base', 'fill', 'empty'] as const; +export type _EuiButtonDisplay = (typeof BUTTON_DISPLAYS)[number]; export interface _EuiButtonOptions { display?: _EuiButtonDisplay; } @@ -177,43 +176,65 @@ export const euiButtonEmptyColor = ( * @returns An object of `_EuiButtonColor` keys including `disabled` */ export const useEuiButtonColorCSS = (options: _EuiButtonOptions = {}) => { - const euiThemeContext = useEuiTheme(); + const { display = 'base' } = options; - function stylesByDisplay(color: _EuiButtonColor | 'disabled') { - return { - base: css` - ${euiButtonColor(euiThemeContext, color)} - `, - fill: css` - ${euiButtonFillColor(euiThemeContext, color)} + const colorsDisplaysMap = useEuiMemoizedStyles(euiButtonDisplaysColors); + return colorsDisplaysMap[display]; +}; - /* Use full shade for outline-color except for dark mode text buttons which need to stay currentColor */ - outline-color: ${euiThemeContext.colorMode === 'DARK' && - color === 'text' - ? 'currentColor' - : euiThemeContext.euiTheme.colors.fullShade}; - `, - empty: css` - color: ${euiButtonEmptyColor(euiThemeContext, color).color}; +const euiButtonDisplaysColors = (euiThemeContext: UseEuiTheme) => { + const COLORS = [...BUTTON_COLORS, 'disabled'] as const; + type Colors = (typeof COLORS)[number]; - &:focus, - &:active { - background-color: ${euiButtonEmptyColor(euiThemeContext, color) - .backgroundColor}; - } - `, - }; - } + const displaysColorsMap = {} as Record< + _EuiButtonDisplay, + Record + >; - return { - text: css(stylesByDisplay('text')[options.display || 'base']), - accent: css(stylesByDisplay('accent')[options.display || 'base']), - primary: css(stylesByDisplay('primary')[options.display || 'base']), - success: css(stylesByDisplay('success')[options.display || 'base']), - warning: css(stylesByDisplay('warning')[options.display || 'base']), - danger: css(stylesByDisplay('danger')[options.display || 'base']), - disabled: css(stylesByDisplay('disabled')[options.display || 'base']), - }; + BUTTON_DISPLAYS.forEach((display) => { + displaysColorsMap[display] = {} as Record; + + COLORS.forEach((color) => { + switch (display) { + case 'base': + displaysColorsMap[display][color] = css` + ${euiButtonColor(euiThemeContext, color)} + `; + break; + case 'fill': + displaysColorsMap[display][color] = css` + ${euiButtonFillColor(euiThemeContext, color)} + + /* Use full shade for outline-color except for dark mode text buttons which need to stay currentColor */ + outline-color: ${euiThemeContext.colorMode === 'DARK' && + color === 'text' + ? 'currentColor' + : euiThemeContext.euiTheme.colors.fullShade}; + `; + break; + case 'empty': + displaysColorsMap[display][color] = css` + color: ${euiButtonEmptyColor(euiThemeContext, color).color}; + + &:focus, + &:active { + background-color: ${euiButtonEmptyColor(euiThemeContext, color) + .backgroundColor}; + } + `; + break; + } + + // Tweak auto-generated Emotion label/className output + const emotionOutput = displaysColorsMap[display][color]; + emotionOutput.styles = emotionOutput.styles.replace( + 'label:displaysColorsMap-display-color;', + `label:${display}-${color};` + ); + }); + }); + + return displaysColorsMap; }; /**