Skip to content

Commit

Permalink
Refactor/memoize EuiLoadingChart
Browse files Browse the repository at this point in the history
- prefer static nth-child CSS over a dynamically generated function (since it's not like the bar count is customizable via prop)

- inline the bar JSX and replace for loop with Array.from

+ fix the duplicate loading i18n (should be using the shared string with the same copy)
  • Loading branch information
cee-chen committed Apr 3, 2024
1 parent 6da43a5 commit 98ebe26
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 69 deletions.
42 changes: 21 additions & 21 deletions src/components/loading/__snapshots__/loading_chart.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,37 @@ exports[`EuiLoadingChart is rendered 1`] = `
role="progressbar"
>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-nonmono-m"
/>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-nonmono-m"
/>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-nonmono-m"
/>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-nonmono-m"
/>
</span>
`;

exports[`EuiLoadingChart mono is rendered 1`] = `
<span
aria-label="Loading"
class="euiLoadingChart euiLoadingChart--mono emotion-euiLoadingChart-m"
class="euiLoadingChart emotion-euiLoadingChart-m"
role="progressbar"
>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-mono-m"
/>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-mono-m"
/>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-mono-m"
/>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-mono-m"
/>
</span>
`;
Expand All @@ -50,16 +50,16 @@ exports[`EuiLoadingChart size l is rendered 1`] = `
role="progressbar"
>
<span
class="emotion-euiLoadingChart__bar-l"
class="emotion-euiLoadingChart__bar-nonmono-l"
/>
<span
class="emotion-euiLoadingChart__bar-l"
class="emotion-euiLoadingChart__bar-nonmono-l"
/>
<span
class="emotion-euiLoadingChart__bar-l"
class="emotion-euiLoadingChart__bar-nonmono-l"
/>
<span
class="emotion-euiLoadingChart__bar-l"
class="emotion-euiLoadingChart__bar-nonmono-l"
/>
</span>
`;
Expand All @@ -71,16 +71,16 @@ exports[`EuiLoadingChart size m is rendered 1`] = `
role="progressbar"
>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-nonmono-m"
/>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-nonmono-m"
/>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-nonmono-m"
/>
<span
class="emotion-euiLoadingChart__bar-m"
class="emotion-euiLoadingChart__bar-nonmono-m"
/>
</span>
`;
Expand All @@ -92,16 +92,16 @@ exports[`EuiLoadingChart size xl is rendered 1`] = `
role="progressbar"
>
<span
class="emotion-euiLoadingChart__bar-xl"
class="emotion-euiLoadingChart__bar-nonmono-xl"
/>
<span
class="emotion-euiLoadingChart__bar-xl"
class="emotion-euiLoadingChart__bar-nonmono-xl"
/>
<span
class="emotion-euiLoadingChart__bar-xl"
class="emotion-euiLoadingChart__bar-nonmono-xl"
/>
<span
class="emotion-euiLoadingChart__bar-xl"
class="emotion-euiLoadingChart__bar-nonmono-xl"
/>
</span>
`;
70 changes: 47 additions & 23 deletions src/components/loading/loading_chart.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@

import { css, keyframes } from '@emotion/react';
import { euiPaletteColorBlind, shadeOrTint, UseEuiTheme } from '../../services';
import { euiCanAnimate, logicalCSS } from '../../global_styling';
import {
euiCanAnimate,
euiCantAnimate,
logicalCSS,
} from '../../global_styling';

const nonMonoColors = euiPaletteColorBlind();

export const euiLoadingChartStyles = ({ euiTheme }: UseEuiTheme) => ({
euiLoadingChart: css`
Expand All @@ -29,10 +35,37 @@ export const euiLoadingChartStyles = ({ euiTheme }: UseEuiTheme) => ({
`,
});

export const euiLoadingChartBarStyles = ({ euiTheme }: UseEuiTheme) => ({
export const BARS_COUNT = 4;

export const euiLoadingChartBarStyles = ({
euiTheme,
colorMode,
}: UseEuiTheme) => ({
euiLoadingChart__bar: css`
${logicalCSS('height', '100%')}
display: inline-block;
${euiCanAnimate} {
animation: ${barAnimation} 1s infinite;
${outputNthChildCss((index) => `animation-delay: 0.${index}s;`)}
}
${euiCantAnimate} {
${outputNthChildCss((index) => `transform: translateY(${22 * index}%);`)}
}
`,
nonmono: css`
${outputNthChildCss((index) => `background-color: ${nonMonoColors[index]}`)}
`,
mono: css`
${outputNthChildCss(
(index) =>
`background-color: ${shadeOrTint(
euiTheme.colors.lightShade,
index * 0.04,
colorMode
)}`
)}
`,
m: css`
${logicalCSS('width', euiTheme.size.xxs)}
Expand All @@ -48,6 +81,18 @@ export const euiLoadingChartBarStyles = ({ euiTheme }: UseEuiTheme) => ({
`,
});

/**
* Small utility helper for generating nth-child CSS for each bar
*/
const outputNthChildCss = (css: (index: number) => string) =>
Array.from(
{ length: BARS_COUNT },
(_, index) => `
&:nth-child(${index + 1}) {
${css(index)}
}`
).join();

const barAnimation = keyframes`
0% {
transform: translateY(0);
Expand All @@ -61,24 +106,3 @@ const barAnimation = keyframes`
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;
}
`;
};
42 changes: 17 additions & 25 deletions src/components/loading/loading_chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@

import React, { FunctionComponent, HTMLAttributes } from 'react';
import classNames from 'classnames';

import { useEuiMemoizedStyles } from '../../services';
import { CommonProps } from '../common';
import { useEuiTheme } from '../../services';

import { useLoadingAriaLabel } from './_loading_strings';
import {
euiLoadingChartStyles,
euiLoadingChartBarStyles,
_barIndex,
BARS_COUNT,
} from './loading_chart.styles';
import { useEuiI18n } from '../i18n';

export const SIZES = ['m', 'l', 'xl'] as const;
export type EuiLoadingChartSize = (typeof SIZES)[number];
Expand All @@ -34,30 +35,19 @@ export const EuiLoadingChart: FunctionComponent<EuiLoadingChartProps> = ({
'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 },
className
);
const classes = classNames('euiLoadingChart', className);

const styles = useEuiMemoizedStyles(euiLoadingChartStyles);
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(<span key={index} css={cssBarStyles(index)} />);
}
const barStyles = useEuiMemoizedStyles(euiLoadingChartBarStyles);
const barCssStyles = [
barStyles.euiLoadingChart__bar,
mono ? barStyles.mono : barStyles.nonmono,
barStyles[size],
];

const defaultAriaLabel = useLoadingAriaLabel();

return (
<span
Expand All @@ -67,7 +57,9 @@ export const EuiLoadingChart: FunctionComponent<EuiLoadingChartProps> = ({
aria-label={ariaLabel || defaultAriaLabel}
{...rest}
>
{bars}
{Array.from({ length: BARS_COUNT }, (_, index) => (
<span key={index} css={barCssStyles} />
))}
</span>
);
};

0 comments on commit 98ebe26

Please sign in to comment.