grafana/packages/grafana-eslint-rules/rules/no-unreduced-motion.cjs
Ashley Harrison c151a97110
Chore: Enable no-unreduced-motion and fix errors (#86572)
* enable `no-unreduced-motion` in betterer

* move all animation calls inside handleReducedMotion

* fix violations + enable rule

* update rule README

* remove unnecessary transition from <Collapse>

* remove handleReducedMotion utility and add handleMotion to theme

* update to use new theme value

* handle Dropdown and IconButton

* handle AppChromeMenu and update lint message

* keep rotation at a reduced speed

* handle DashboardLoading
2024-04-29 13:12:36 +01:00

66 lines
2.1 KiB
JavaScript

// @ts-check
const { ESLintUtils, AST_NODE_TYPES } = require('@typescript-eslint/utils');
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-eslint-rules/README.md#${name}`);
const restrictedProperties = ['animation', 'transition'];
const isRestrictedProperty = (/** @type string */ propertyName) => {
return restrictedProperties.some((prop) => propertyName.startsWith(prop));
};
const rule = createRule({
create(context) {
return {
CallExpression(node) {
if (
node.callee.type === AST_NODE_TYPES.Identifier &&
node.callee.name === 'css'
) {
const cssObjects = node.arguments.flatMap((node) => {
switch (node.type) {
case AST_NODE_TYPES.ObjectExpression:
return [node];
case AST_NODE_TYPES.ArrayExpression:
return node.elements.filter(v => v?.type === AST_NODE_TYPES.ObjectExpression);
default:
return [];
}
});
for (const cssObject of cssObjects) {
if (cssObject?.type === AST_NODE_TYPES.ObjectExpression) {
for (const property of cssObject.properties) {
if (
property.type === AST_NODE_TYPES.Property &&
property.key.type === AST_NODE_TYPES.Identifier &&
isRestrictedProperty(property.key.name)
) {
context.report({
node: property,
messageId: 'noUnreducedMotion',
});
}
}
}
}
}
},
};
},
name: 'no-unreduced-motion',
meta: {
type: 'problem',
docs: {
description: 'Check if animation or transition properties are used directly.',
},
messages: {
noUnreducedMotion: 'Avoid direct use of `animation*` or `transition*` properties. Use the `handleMotion` utility function from theme.transitions or wrap in a `prefers-reduced-motion` media query.',
},
schema: [],
},
defaultOptions: [],
});
module.exports = rule;