diff --git a/packages/grafana-ui/src/components/Button/Button.test.tsx b/packages/grafana-ui/src/components/Button/Button.test.tsx deleted file mode 100644 index 68d4e1e55c4..00000000000 --- a/packages/grafana-ui/src/components/Button/Button.test.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { render } from '@testing-library/react'; -import React from 'react'; - -import { Button } from './Button'; - -describe('Button', () => { - it('spins the spinner when specified as an icon', () => { - const { container } = render(); - expect(container.querySelector('.fa-spin')).toBeInTheDocument(); - }); -}); diff --git a/packages/grafana-ui/src/components/Icon/Icon.tsx b/packages/grafana-ui/src/components/Icon/Icon.tsx index d33ed422b4d..d4ade1c4796 100644 --- a/packages/grafana-ui/src/components/Icon/Icon.tsx +++ b/packages/grafana-ui/src/components/Icon/Icon.tsx @@ -6,6 +6,7 @@ import { GrafanaTheme2, isIconName } from '@grafana/data'; import { useStyles2 } from '../../themes/ThemeContext'; import { IconName, IconType, IconSize } from '../../types/icon'; +import { spin } from '../../utils/keyframes'; import { getIconRoot, getIconSubDir, getSvgSize } from './utils'; @@ -33,6 +34,11 @@ const getIconStyles = (theme: GrafanaTheme2) => { orange: css({ fill: theme.v1.palette.orange, }), + spin: css({ + [theme.transitions.handleMotion('no-preference', 'reduce')]: { + animation: `${spin} 2s infinite linear`, + }, + }), }; }; @@ -58,7 +64,9 @@ export const Icon = React.forwardRef( styles.icon, className, type === 'mono' ? { [styles.orange]: name === 'favorite' } : '', - iconName === 'spinner' && 'fa-spin' + { + [styles.spin]: iconName === 'spinner', + } ); return ( diff --git a/packages/grafana-ui/src/components/Spinner/Spinner.tsx b/packages/grafana-ui/src/components/Spinner/Spinner.tsx index a4d45805f29..013f7332a2a 100644 --- a/packages/grafana-ui/src/components/Spinner/Spinner.tsx +++ b/packages/grafana-ui/src/components/Spinner/Spinner.tsx @@ -7,6 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '../../themes'; import { IconSize, isIconSize } from '../../types'; import { t } from '../../utils/i18n'; +import { spin } from '../../utils/keyframes'; import { Icon } from '../Icon/Icon'; import { getIconRoot, getIconSubDir } from '../Icon/utils'; @@ -46,7 +47,6 @@ export const Spinner = ({ // TODO remove once we fully remove the deprecated type if (typeof size !== 'string' || !isIconSize(size)) { const iconRoot = getIconRoot(); - const iconName = 'spinner'; const subDir = getIconSubDir(iconName, 'default'); const svgPath = `${iconRoot}${subDir}/${iconName}.svg`; return ( @@ -65,7 +65,7 @@ export const Spinner = ({ src={svgPath} width={size} height={size} - className={cx('fa-spin', deprecatedStyles.icon, className)} + className={cx(styles.spin, deprecatedStyles.icon, className)} style={style} /> @@ -84,12 +84,7 @@ export const Spinner = ({ )} > ({ inline: css({ display: 'inline-block', }), + spin: css({ + [theme.transitions.handleMotion('no-preference')]: { + animation: `${spin} 2s infinite linear`, + }, + }), }); // TODO remove once we fully remove the deprecated type diff --git a/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx b/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx index 377318481c3..f8cddcb4de8 100644 --- a/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx +++ b/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { useTheme2 } from '../ThemeContext'; +import { getAccessibilityStyles } from './accessibility'; import { getAgularPanelStyles } from './angularPanelStyles'; import { getCardStyles } from './card'; import { getCodeStyles } from './code'; @@ -24,6 +25,7 @@ export function GlobalStyles() { return (