Skip to content

Commit 5d14250

Browse files
authoredFeb 10, 2025··
refactor(eslint): enhance eslint config type safety (#127)
* refactor(eslint): enhance eslint config type safety * chore(eslint): add type definitions for eslint-plugin-react-hooks * chore(eslint): install eslint type safety dev dependencies * chore(eslint): add react version detect setting * chore(storybook): remove addon-onboarding from addons each component * chore(storybook): remove chromatic storybook from addon * chore(storybook): format main.ts
1 parent 235be5d commit 5d14250

File tree

21 files changed

+233
-282
lines changed

21 files changed

+233
-282
lines changed
 

‎.templates/component/.storybook/main.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@storybook/addon-interactions',
10-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
116
framework: {
127
name: '@storybook/react-vite',
138
options: {},

‎eslint.config.ts

+34-10
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1+
import { FlatCompat } from '@eslint/eslintrc';
12
import eslint from '@eslint/js';
23
import reactPlugin from 'eslint-plugin-react';
3-
import storybook from 'eslint-plugin-storybook';
4+
import hooksPlugin from 'eslint-plugin-react-hooks';
5+
import globals from 'globals';
46
import tseslint from 'typescript-eslint';
57

6-
// @ts-ignore
7-
import hooksPlugin from 'eslint-plugin-react-hooks';
8+
const compat = new FlatCompat();
89

910
// ? https://typescript-eslint.io/getting-started#step-2-configuration
1011
export default tseslint.config(
12+
// * Base ESLint recommended configuration
1113
eslint.configs.recommended,
14+
// * TypeScript ESLint recommended configuration
1215
tseslint.configs.recommended,
16+
// * Custom rules configuration
1317
{
1418
rules: {
1519
'@typescript-eslint/ban-ts-comment': 'off',
1620
'@typescript-eslint/no-unused-vars': 'off',
1721
'@typescript-eslint/no-explicit-any': 'off',
18-
1922
'no-duplicate-imports': 'off',
2023
'no-unused-expressions': 'off',
2124
'@typescript-eslint/no-unused-expressions': [
@@ -28,15 +31,22 @@ export default tseslint.config(
2831
},
2932
},
3033

34+
// * React plugin configuration
3135
{
32-
files: ['**/*.ts', '**/*.tsx'],
36+
files: ['**/*.{ts,tsx}'],
3337
plugins: {
3438
react: reactPlugin,
35-
'react-hooks': hooksPlugin,
39+
},
40+
languageOptions: {
41+
globals: {
42+
...globals.serviceworker,
43+
...globals.browser,
44+
},
3645
},
3746
rules: {
38-
...reactPlugin.configs['jsx-runtime'].rules,
39-
...hooksPlugin.configs.recommended.rules,
47+
...reactPlugin.configs.recommended.rules,
48+
'react/react-in-jsx-scope': 'off',
49+
'react/prop-types': 'off',
4050
},
4151
settings: {
4252
react: {
@@ -45,12 +55,26 @@ export default tseslint.config(
4555
},
4656
},
4757

48-
...(storybook.configs['flat/recommended'] as any),
58+
// * React Hooks plugin configuration
59+
...compat.extends('plugin:react-hooks/recommended'),
60+
{
61+
files: ['**/*.{ts,tsx}'],
62+
plugins: {
63+
'react-hooks': hooksPlugin,
64+
},
65+
rules: {
66+
...hooksPlugin.configs.recommended.rules,
67+
},
68+
},
69+
70+
// * Storybook plugin configuration
71+
...compat.extends('plugin:storybook/recommended'),
4972
{
5073
files: ['**/*.stories.@(ts|tsx|js|jsx|mjs|cjs)'],
74+
rules: {},
5175
},
5276

53-
// ignore files
77+
// Ignore files configuration
5478
{
5579
ignores: ['**/*/dist/', '**/node_modules/', '*.config.*'],
5680
},

‎package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@commitlint/config-conventional": "^19.6.0",
2424
"@commitlint/cz-commitlint": "^19.6.1",
2525
"@commitlint/types": "^19.5.0",
26+
"@eslint/eslintrc": "^3.2.0",
2627
"@storybook/addon-docs": "^8.4.7",
2728
"@storybook/addon-essentials": "catalog:",
2829
"@storybook/addon-interactions": "catalog:",
@@ -34,6 +35,7 @@
3435
"@storybook/test": "catalog:",
3536
"@storybook/theming": "^8.4.7",
3637
"@tsconfig/strictest": "^2.0.5",
38+
"@types/eslint__eslintrc": "^2.1.2",
3739
"@types/node": "^22.8.1",
3840
"@types/react": "^18.3.12",
3941
"@types/react-dom": "^18.3.1",
@@ -42,10 +44,11 @@
4244
"chromatic": "^11.19.0",
4345
"clipanion": "4.0.0-rc.4",
4446
"commitizen": "^4.3.1",
45-
"eslint": "^9.18.0",
47+
"eslint": "^9.20.0",
4648
"eslint-plugin-react": "^7.37.3",
4749
"eslint-plugin-react-hooks": "^5.1.0",
4850
"eslint-plugin-storybook": "^0.11.2",
51+
"globals": "^15.14.0",
4952
"husky": "^9.1.7",
5053
"knip": "catalog:",
5154
"lint-staged": "^15.3.0",

‎packages/Input/.storybook/main.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@chromatic-com/storybook',
10-
'@storybook/addon-interactions',
11-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
126
framework: {
137
name: '@storybook/react-vite',
148
options: {},

‎packages/avatar/.storybook/main.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@chromatic-com/storybook',
10-
'@storybook/addon-interactions',
11-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
126
framework: {
137
name: '@storybook/react-vite',
148
options: {},

‎packages/button/.storybook/main.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@chromatic-com/storybook',
10-
'@storybook/addon-interactions',
11-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
126
framework: {
137
name: '@storybook/react-vite',
148
options: {},

‎packages/checkbox/.storybook/main.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@storybook/addon-interactions',
10-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
116
framework: {
127
name: '@storybook/react-vite',
138
options: {},

‎packages/divider/.storybook/main.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@chromatic-com/storybook',
10-
'@storybook/addon-interactions',
11-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
126
framework: {
137
name: '@storybook/react-vite',
148
options: {},

‎packages/flex/.storybook/main.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@storybook/addon-interactions',
10-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
116
framework: {
127
name: '@storybook/react-vite',
138
options: {},

‎packages/grid/.storybook/main.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@storybook/addon-interactions',
10-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
116
framework: {
127
name: '@storybook/react-vite',
138
options: {},

‎packages/grid/src/Grid.stories.tsx

+2-13
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,7 @@ export const Basic: Story = {
6363
args: {
6464
templateColumns: 'repeat(3, 1fr)',
6565
gap: '1rem',
66-
children: [
67-
<Box key="1" />,
68-
<Box key="2" />,
69-
<Box key="3" />,
70-
<Box key="4" />,
71-
<Box key="5" />,
72-
<Box key="6" />,
73-
],
66+
children: [<Box key="1" />, <Box key="2" />, <Box key="3" />, <Box key="4" />, <Box key="5" />, <Box key="6" />],
7467
},
7568
};
7669

@@ -104,11 +97,7 @@ export const GridTemplateAreas: Story = {
10497

10598
export const SpanningColumns: Story = {
10699
render: () => (
107-
<Grid.Root
108-
templateColumns="repeat(4, 1fr)"
109-
templateRows="repeat(2, 1fr)"
110-
gap="1rem"
111-
>
100+
<Grid.Root templateColumns="repeat(4, 1fr)" templateRows="repeat(2, 1fr)" gap="1rem">
112101
<Grid.Item rowSpan={2}>
113102
<Box>rowSpan 2</Box>
114103
</Grid.Item>

‎packages/grid/src/Grid.test.tsx

+13-18
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ describe('Grid', () => {
2020

2121
it('should apply additional className when provided', () => {
2222
const customClassName = faker.word.noun();
23-
render(
24-
<Grid.Root data-testid="grid-container" className={customClassName} />,
25-
);
23+
render(<Grid.Root data-testid="grid-container" className={customClassName} />);
2624
expect(screen.getByTestId('grid-container')).toHaveClass(customClassName);
2725
});
2826

@@ -146,21 +144,18 @@ describe('Grid', () => {
146144
[prop]: value,
147145
expectedValue: expectedValues?.[index] ?? value,
148146
})),
149-
)(
150-
`should apply ${style} when ${prop} prop is $${prop}`,
151-
({ [prop]: value, expectedValue }) => {
152-
render(
153-
<Grid.Root>
154-
<Grid.Item data-testid="grid-item" {...{ [prop]: value }}>
155-
item 1
156-
</Grid.Item>
157-
</Grid.Root>,
158-
);
159-
160-
const gridItem = screen.getByTestId('grid-item');
161-
expect(gridItem).toHaveStyle({ [style]: expectedValue });
162-
},
163-
);
147+
)(`should apply ${style} when ${prop} prop is $${prop}`, ({ [prop]: value, expectedValue }) => {
148+
render(
149+
<Grid.Root>
150+
<Grid.Item data-testid="grid-item" {...{ [prop]: value }}>
151+
item 1
152+
</Grid.Item>
153+
</Grid.Root>,
154+
);
155+
156+
const gridItem = screen.getByTestId('grid-item');
157+
expect(gridItem).toHaveStyle({ [style]: expectedValue });
158+
});
164159
});
165160
}
166161
});

‎packages/icon/.storybook/main.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@storybook/addon-interactions',
10-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
116
framework: {
127
name: '@storybook/react-vite',
138
options: {},

‎packages/radio-group/.storybook/main.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@chromatic-com/storybook',
10-
'@storybook/addon-interactions',
11-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
126
framework: {
137
name: '@storybook/react-vite',
148
options: {},

‎packages/reset/.storybook/main.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@storybook/addon-interactions',
10-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
116
framework: {
127
name: '@storybook/react-vite',
138
options: {},

‎packages/skeleton/.storybook/main.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@chromatic-com/storybook',
10-
'@storybook/addon-interactions',
11-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
126
framework: {
137
name: '@storybook/react-vite',
148
options: {},

‎packages/switch/.storybook/main.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@storybook/addon-interactions',
10-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
116
framework: {
127
name: '@storybook/react-vite',
138
options: {},

‎packages/tooltip/.storybook/main.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@chromatic-com/storybook',
10-
'@storybook/addon-interactions',
11-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
126
framework: {
137
name: '@storybook/react-vite',
148
options: {},

‎packages/typography/.storybook/main.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
22

33
export default {
44
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5-
addons: [
6-
'@storybook/addon-onboarding',
7-
'@storybook/addon-links',
8-
'@storybook/addon-essentials',
9-
'@chromatic-com/storybook',
10-
'@storybook/addon-interactions',
11-
],
5+
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
126
framework: {
137
name: '@storybook/react-vite',
148
options: {},

‎pnpm-lock.yaml

+150-142
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎types/index.d.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* I Typed manually since the ecosystem hasn't fully migrated to ESLint's new FlatConfig system yet.
3+
*/
4+
5+
declare module 'eslint-plugin-react-hooks' {
6+
export const configs: {
7+
recommended: {
8+
rules: {
9+
'rules-of-hooks': Linter.RuleEntry;
10+
'exhaustive-deps': Linter.RuleEntry;
11+
};
12+
};
13+
};
14+
export const rules: Record<string, Rule.RuleModule>;
15+
}

0 commit comments

Comments
 (0)
Please sign in to comment.