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 (