mirror of
https://github.com/grafana/grafana.git
synced 2024-11-26 19:00:54 -06:00
Chore: Add lint rule for no-unreduced-motion
(#85862)
* add lint rule for no-unreduced-motion * update to satisfy types
This commit is contained in:
parent
00daca7f43
commit
5e74b6962b
@ -4,7 +4,7 @@ This package contains custom eslint rules for use within the Grafana codebase on
|
||||
|
||||
## Rules
|
||||
|
||||
### `@grafana/no-aria-label-selectors`
|
||||
### `no-aria-label-selectors`
|
||||
|
||||
Require aria-label JSX properties to not include selectors from the `@grafana/e2e-selectors` package.
|
||||
|
||||
@ -12,12 +12,20 @@ Previously we hijacked the aria-label property to use as E2E selectors as an att
|
||||
|
||||
Now, we prefer using data-testid for E2E selectors.
|
||||
|
||||
### `@grafana/no-border-radius-literal`
|
||||
### `no-border-radius-literal`
|
||||
|
||||
Check if border-radius theme tokens are used.
|
||||
|
||||
To improve the consistency across Grafana we encourage devs to use tokens instead of custom values. In this case, we want the `borderRadius` to use the appropriate token such as `theme.shape.radius.default`, `theme.shape.radius.pill` or `theme.shape.radius.circle`.
|
||||
|
||||
### `@grafana/theme-token-usage`
|
||||
### `no-unreduced-motion`
|
||||
|
||||
Avoid direct use of `animation*` or `transition*` properties.
|
||||
|
||||
To account for users with motion sensitivities, these should always be wrapped in a [`prefers-reduced-motion`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) media query.
|
||||
|
||||
`@grafana/ui` exposes a `handledReducedMotion` utility function that can be used to handle this.
|
||||
|
||||
### `theme-token-usage`
|
||||
|
||||
Used to find all instances of `theme` tokens being used in the codebase and emit the counts as metrics. Should **not** be used as an actual lint rule!
|
||||
|
@ -1,9 +1,11 @@
|
||||
const noAriaLabelSelectors = require('./rules/no-aria-label-e2e-selectors.cjs');
|
||||
const noBorderRadiusLiteral = require('./rules/no-border-radius-literal.cjs');
|
||||
const noUnreducedMotion = require('./rules/no-unreduced-motion.cjs');
|
||||
const themeTokenUsage = require('./rules/theme-token-usage.cjs');
|
||||
|
||||
module.exports = {
|
||||
rules: {
|
||||
'no-unreduced-motion': noUnreducedMotion,
|
||||
'no-aria-label-selectors': noAriaLabelSelectors,
|
||||
'no-border-radius-literal': noBorderRadiusLiteral,
|
||||
'theme-token-usage': themeTokenUsage,
|
||||
|
@ -15,10 +15,7 @@ const { ESLintUtils } = require('@typescript-eslint/utils');
|
||||
|
||||
const GRAFANA_E2E_PACKAGE_NAME = '@grafana/e2e-selectors';
|
||||
|
||||
const createRule = ESLintUtils.RuleCreator(
|
||||
// TODO: find a proper url?
|
||||
(name) => `https://github.com/grafana/grafana#${name}`
|
||||
);
|
||||
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-eslint-rules/README.md#${name}`);
|
||||
|
||||
// A relative simple lint rule that will look of the `selectors` export from @grafana/e2e-selectors
|
||||
// is used in an aria-label
|
||||
@ -69,7 +66,6 @@ const rule = createRule({
|
||||
meta: {
|
||||
docs: {
|
||||
description: 'aria-label should not contain e2e selectors',
|
||||
// recommended: 'error',
|
||||
},
|
||||
messages: {
|
||||
useDataTestId: 'Use data-testid for E2E selectors instead of aria-label',
|
||||
|
@ -1,7 +1,7 @@
|
||||
// @ts-check
|
||||
const { ESLintUtils, AST_NODE_TYPES } = require('@typescript-eslint/utils');
|
||||
|
||||
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/grafana/grafana#${name}`);
|
||||
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-eslint-rules/README.md#${name}`);
|
||||
|
||||
const borderRadiusRule = createRule({
|
||||
create(context) {
|
||||
|
65
packages/grafana-eslint-rules/rules/no-unreduced-motion.cjs
Normal file
65
packages/grafana-eslint-rules/rules/no-unreduced-motion.cjs
Normal file
@ -0,0 +1,65 @@
|
||||
// @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 `handleReducedMotion` utility function or wrap in a `prefers-reduced-motion` media query.',
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
defaultOptions: [],
|
||||
});
|
||||
|
||||
module.exports = rule;
|
@ -1,7 +1,7 @@
|
||||
// @ts-check
|
||||
const { ESLintUtils, AST_NODE_TYPES } = require('@typescript-eslint/utils');
|
||||
|
||||
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/grafana/grafana#${name}`);
|
||||
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-eslint-rules/README.md#${name}`);
|
||||
|
||||
const themeTokenUsage = createRule({
|
||||
create(context) {
|
||||
|
Loading…
Reference in New Issue
Block a user