diff --git a/src-docs/src/views/loading/loading_chart.tsx b/src-docs/src/views/loading/loading_chart.tsx index 830b93fe87d..c2270054622 100644 --- a/src-docs/src/views/loading/loading_chart.tsx +++ b/src-docs/src/views/loading/loading_chart.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { EuiLoadingChart } from '../../../../src/components/loading'; +import { EuiLoadingChart } from '../../../../src'; export default () => (
diff --git a/src-docs/src/views/loading/loading_example.js b/src-docs/src/views/loading/loading_example.js index 5a20c55f077..ec48304f08e 100644 --- a/src-docs/src/views/loading/loading_example.js +++ b/src-docs/src/views/loading/loading_example.js @@ -109,7 +109,7 @@ export const LoadingExample = { ), props: { EuiLoadingChart }, demo: , - snippet: '', + snippet: ['', ''], playground: loadingChartConfig, }, { diff --git a/src/components/loading/__snapshots__/loading_chart.test.tsx.snap b/src/components/loading/__snapshots__/loading_chart.test.tsx.snap index b2e1cf89346..87b3ae3dbdc 100644 --- a/src/components/loading/__snapshots__/loading_chart.test.tsx.snap +++ b/src/components/loading/__snapshots__/loading_chart.test.tsx.snap @@ -3,96 +3,105 @@ exports[`EuiLoadingChart is rendered 1`] = ` `; exports[`EuiLoadingChart mono is rendered 1`] = ` `; exports[`EuiLoadingChart size l is rendered 1`] = ` `; exports[`EuiLoadingChart size m is rendered 1`] = ` `; exports[`EuiLoadingChart size xl is rendered 1`] = ` `; diff --git a/src/components/loading/_index.scss b/src/components/loading/_index.scss index c2990867ddc..a1074c2e433 100644 --- a/src/components/loading/_index.scss +++ b/src/components/loading/_index.scss @@ -1,6 +1,5 @@ @import 'variables'; @import 'loading_elastic'; -@import 'loading_chart'; @import 'loading_content'; @import 'loading_logo'; @import 'loading_spinner'; diff --git a/src/components/loading/_loading_chart.scss b/src/components/loading/_loading_chart.scss deleted file mode 100644 index 02ebd1f2829..00000000000 --- a/src/components/loading/_loading_chart.scss +++ /dev/null @@ -1,118 +0,0 @@ -.euiLoadingChart { - height: $euiSizeXL; - z-index: 500; - overflow: hidden; - display: inline-block; -} - -/** - * 1. Without the animation, the bars are all the same height, - * so we apply transforms only if they can't animate - */ -.euiLoadingChart__bar { - height: 100%; - width: $euiSizeS; - display: inline-block; - margin-bottom: -$euiSize; - margin-left: $euiSizeXS / 2; - - // sass-lint:disable-block mixins-before-declarations - @include euiCanAnimate { - animation: euiLoadingChart 1s infinite; - } - - &:nth-child(1) { - background-color: $euiColorVis0; - - @include euiCantAnimate { - transform: translateY(66%); /* 1 */ - } - } - - &:nth-child(2) { - background-color: $euiColorVis1; - animation-delay: .1s; - - @include euiCantAnimate { - transform: translateY(44%); /* 1 */ - } - } - - &:nth-child(3) { - background-color: $euiColorVis2; - animation-delay: .2s; - - @include euiCantAnimate { - transform: translateY(22%); /* 1 */ - } - } - - &:nth-child(4) { - background-color: $euiColorVis3; - animation-delay: .3s; - } -} - -.euiLoadingChart--mono { - .euiLoadingChart__bar { - &:nth-child(1) { - background-color: $euiColorLightShade; - } - - &:nth-child(2) { - background-color: shadeOrTint($euiColorLightShade, 4%, 4%); - } - - &:nth-child(3) { - background-color: shadeOrTint($euiColorLightShade, 8%, 8%); - } - - &:nth-child(4) { - background-color: shadeOrTint($euiColorLightShade, 12%, 12%); - } - } -} - -.euiLoadingChart--medium { - height: $euiSize; - - > span { - width: $euiSizeXS / 2; - margin-left: $euiSizeXS / 2; - margin-bottom: $euiSizeS; - } -} - -.euiLoadingChart--large { - height: $euiSizeL; - - > span { - width: $euiSizeXS; - margin-left: $euiSizeXS / 2; - margin-bottom: $euiSizeL / 2; - } -} - -.euiLoadingChart--xLarge { - height: $euiSizeXL; - - > span { - width: $euiSizeS; - margin-left: $euiSizeXS; - margin-bottom: $euiSizeXL / 2; - } -} - -@keyframes euiLoadingChart { - 0% { - transform: translateY(0); - } - - 50% { - transform: translateY(66%); - } - - 100% { - transform: translateY(0); - } -} diff --git a/src/components/loading/loading_chart.styles.ts b/src/components/loading/loading_chart.styles.ts new file mode 100644 index 00000000000..7791b535045 --- /dev/null +++ b/src/components/loading/loading_chart.styles.ts @@ -0,0 +1,84 @@ +/* + * 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 { css, keyframes } from '@emotion/react'; +import { euiPaletteColorBlind, shadeOrTint, UseEuiTheme } from '../../services'; +import { euiCanAnimate } from '../../global_styling'; + +export const euiLoadingChartStyles = ({ euiTheme }: UseEuiTheme) => ({ + euiLoadingChart: css` + overflow: hidden; + display: inline-flex; + `, + m: css` + height: ${euiTheme.size.base}; + gap: ${euiTheme.size.xxs}; + `, + l: css` + height: ${euiTheme.size.l}; + gap: ${euiTheme.size.xxs}; + `, + xl: css` + height: ${euiTheme.size.xl}; + gap: ${euiTheme.size.xs}; + `, +}); + +export const euiLoadingChartBarStyles = ({ euiTheme }: UseEuiTheme) => ({ + euiLoadingChart__bar: css` + height: 100%; + display: inline-block; + `, + m: css` + width: ${euiTheme.size.xxs}; + margin-block-end: ${euiTheme.size.s}; + `, + l: css` + width: ${euiTheme.size.xs}; + margin-block-end: ${euiTheme.size.m}; + `, + xl: css` + width: ${euiTheme.size.s}; + margin-block-end: ${euiTheme.size.base}; + `, +}); + +const barAnimation = keyframes` + 0% { + transform: translateY(0); + } + + 50% { + transform: translateY(66%); + } + + 100% { + transform: translateY(0); + } +`; + +export const _barIndex = ( + index: number, + mono: boolean, + { euiTheme, colorMode }: UseEuiTheme +) => { + const backgroundColor = mono + ? shadeOrTint(euiTheme.colors.lightShade, index * 0.04, colorMode) + : euiPaletteColorBlind()[index]; + + return css` + background-color: ${backgroundColor}; + // Without the animation, the bars are all the same height, + // so we apply transforms which are overridden by the animation if animations are allowed + transform: translateY(${22 * index}%); + + ${euiCanAnimate} { + animation: ${barAnimation} 1s ${`.${index}s`} infinite; + } + `; +}; diff --git a/src/components/loading/loading_chart.test.tsx b/src/components/loading/loading_chart.test.tsx index 7aebef83b8c..bb19647a251 100644 --- a/src/components/loading/loading_chart.test.tsx +++ b/src/components/loading/loading_chart.test.tsx @@ -9,10 +9,13 @@ import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; +import { shouldRenderCustomStyles } from '../../test/internal'; import { EuiLoadingChart, SIZES } from './loading_chart'; describe('EuiLoadingChart', () => { + shouldRenderCustomStyles(); + test('is rendered', () => { const component = render(); @@ -24,6 +27,7 @@ describe('EuiLoadingChart', () => { expect(component).toMatchSnapshot(); }); + describe('size', () => { SIZES.forEach((size) => { test(`${size} is rendered`, () => { diff --git a/src/components/loading/loading_chart.tsx b/src/components/loading/loading_chart.tsx index f345a3d6e2c..6b2784ee80f 100644 --- a/src/components/loading/loading_chart.tsx +++ b/src/components/loading/loading_chart.tsx @@ -9,6 +9,14 @@ import React, { FunctionComponent, HTMLAttributes } from 'react'; import classNames from 'classnames'; import { CommonProps, keysOf } from '../common'; +import { useEuiTheme } from '../../services'; + +import { + euiLoadingChartStyles, + euiLoadingChartBarStyles, + _barIndex, +} from './loading_chart.styles'; +import { useEuiI18n } from '../i18n'; const sizeToClassNameMap = { m: 'euiLoadingChart--medium', @@ -30,8 +38,14 @@ export const EuiLoadingChart: FunctionComponent = ({ size = 'm', mono = false, className, + 'aria-label': ariaLabel, ...rest }) => { + const defaultAriaLabel = useEuiI18n('euiLoadingChart.ariaLabel', 'Loading'); + const euiTheme = useEuiTheme(); + const styles = euiLoadingChartStyles(euiTheme); + const barStyles = euiLoadingChartBarStyles(euiTheme); + const classes = classNames( 'euiLoadingChart', { 'euiLoadingChart--mono': mono }, @@ -39,12 +53,29 @@ export const EuiLoadingChart: FunctionComponent = ({ sizeToClassNameMap[size] ); + const cssStyles = [styles.euiLoadingChart, styles[size]]; + const cssBarStyles = (index: number) => { + return [ + barStyles.euiLoadingChart__bar, + barStyles[size], + _barIndex(index, mono, euiTheme), + ]; + }; + + const bars = []; + for (let index = 0; index < 4; index++) { + bars.push(); + } + return ( - - - - - + + {bars} ); }; diff --git a/src/services/color/manipulation.ts b/src/services/color/manipulation.ts index 61b74fc518e..39e1c3a69a1 100644 --- a/src/services/color/manipulation.ts +++ b/src/services/color/manipulation.ts @@ -7,6 +7,7 @@ */ import chroma, { Color } from 'chroma-js'; +import { EuiThemeColorModeStandard } from '../theme'; import { isValidHex } from './is_valid_hex'; const inOriginalFormat = (originalColor: string, newColor: Color) => { @@ -41,6 +42,34 @@ export const shade = (color: string, ratio: number) => { return inOriginalFormat(color, shade); }; +/** + * Returns the tinted color for light mode and shaded color for dark mode + * @param color - Color to mix with white + * @param ratio - Mix weight. From 0-1. Larger value indicates more white. + * @param colorMode - Light or dark only + */ +export const tintOrShade = ( + color: string, + ratio: number, + colorMode: EuiThemeColorModeStandard +) => { + return colorMode === 'DARK' ? shade(color, ratio) : tint(color, ratio); +}; + +/** + * Returns the shaded color for light mode and tinted color for dark mode + * @param color - Color to mix with white + * @param ratio - Mix weight. From 0-1. Larger value indicates more white. + * @param colorMode - Light or dark only + */ +export const shadeOrTint = ( + color: string, + ratio: number, + colorMode: EuiThemeColorModeStandard +) => { + return colorMode === 'DARK' ? tint(color, ratio) : shade(color, ratio); +}; + /** * Increases the saturation of a color by manipulating the hsl saturation. * @param color - Color to manipulate diff --git a/src/services/index.ts b/src/services/index.ts index 351641139ba..48902a7eaa0 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -62,6 +62,8 @@ export { transparentize, tint, shade, + tintOrShade, + shadeOrTint, saturate, desaturate, lightness, diff --git a/upcoming_changelogs/5821.md b/upcoming_changelogs/5821.md new file mode 100644 index 00000000000..95369cf3da0 --- /dev/null +++ b/upcoming_changelogs/5821.md @@ -0,0 +1,5 @@ +- Improved accessibility of `EuiLoadingChart` + +**CSS-in-JS conversions** + +- Converted `EuiLoadingChart` to Emotion