Configure ESLint and fix all reported issues

This commit is contained in:
Konrad Szwarc 2022-08-27 01:54:26 +02:00
parent 135ed17813
commit bf38e195ba
19 changed files with 2837 additions and 173 deletions

101
.eslintrc.json Normal file
View file

@ -0,0 +1,101 @@
{
"root": true,
"plugins": ["file-progress"],
"overrides": [
{
// All files.
"files": ["*.ts", "*.tsx", "*.cjs"],
"extends": [
"airbnb",
"plugin:eslint-comments/recommended",
"plugin:storybook/recommended",
"plugin:prettier/recommended" // This config needs to be the last one as it overrides rules from other configs.
],
"rules": {
// We prefer named exports as they ensure that import name is the same as the export name.
"import/prefer-default-export": 0,
"import/no-default-export": 2,
// Shows information about currently processing file in the console.
"file-progress/activate": 1,
// Removes eslint-disable comments when they are not needed.
"eslint-comments/no-unused-disable": 2,
// Ensure each eslint-disable has a description comment.
"eslint-comments/require-description": [2, { "ignore": ["eslint-enable"] }]
}
},
{
// TypeScript files.
"files": ["*.ts", "*.tsx"],
"plugins": ["simple-import-sort"],
"extends": [
"airbnb-typescript",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:prettier/recommended"
],
"parserOptions": {
"project": "./tsconfig.eslint.json"
},
"settings": {
"import/resolver": {
"typescript": { "project": "./tsconfig.eslint.json" }
}
},
"rules": {
// We can create an empty interface only when it extends other interface.
"@typescript-eslint/no-empty-interface": [2, { "allowSingleExtends": true }],
// Rules for imports and exports order.
"simple-import-sort/imports": [
2,
{
"groups": [
["^\\u0000"], // Side effects
["^@?\\w"], // Packages
["^"], // Absolute imports
["^\\."] // Relative imports
]
}
],
"simple-import-sort/exports": 2
}
},
{
// Files with React components.
"files": ["*.tsx"],
"extends": ["airbnb/hooks", "plugin:react/jsx-runtime", "plugin:prettier/recommended"],
"rules": {
// Write all components as arrow functions.
"react/function-component-definition": [
2,
{ "namedComponents": "arrow-function", "unnamedComponents": "arrow-function" }
],
// We use props spreading to pass props to the html elements under custom components.
"react/jsx-props-no-spreading": 0,
// Define values for optional props as by providing default arguments.
"react/require-default-props": [2, { "functions": "defaultArguments" }]
}
},
{
// Storybook stories
"files": ["*.stories.tsx"],
"rules": {
"import/no-default-export": 0
}
},
{
// Configuration files
"files": ["astro.config.ts", "tailwind.config.cjs", ".storybook/*"],
"rules": {
"import/no-default-export": 0,
"import/no-extraneous-dependencies": [2, { "devDependencies": true }]
}
}
],
"ignorePatterns": ["!.storybook"]
}

View file

@ -1,30 +1,22 @@
import type { StorybookViteConfig } from '@storybook/builder-vite'; import type { StorybookViteConfig } from '@storybook/builder-vite';
import tsconfigPaths from 'vite-tsconfig-paths'; import postcss from 'postcss';
import { mergeConfig } from 'vite'; import { mergeConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
const config: StorybookViteConfig = { const storybookViteConfig: StorybookViteConfig = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [ addons: [
'@storybook/addon-essentials', '@storybook/addon-essentials',
{ {
name: '@storybook/addon-postcss', name: '@storybook/addon-postcss',
options: { options: { postcssLoaderOptions: { implementation: postcss } },
postcssLoaderOptions: {
implementation: require('postcss'),
},
},
}, },
], ],
framework: '@storybook/react', framework: '@storybook/react',
typescript: { check: false }, typescript: { check: false },
core: { builder: '@storybook/builder-vite' }, core: { builder: '@storybook/builder-vite' },
features: { features: { storyStoreV7: true },
storyStoreV7: true, viteFinal: (config) => mergeConfig(config, { plugins: [tsconfigPaths()] }),
},
viteFinal: (config) =>
mergeConfig(config, {
plugins: [tsconfigPaths()],
}),
}; };
export default config; export default storybookViteConfig;

View file

@ -1,5 +1 @@
import 'tailwindcss/tailwind.css'; import 'tailwindcss/tailwind.css';
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
};

View file

@ -1,6 +1,6 @@
import { defineConfig } from 'astro/config';
import react from '@astrojs/react'; import react from '@astrojs/react';
import tailwind from '@astrojs/tailwind'; import tailwind from '@astrojs/tailwind';
import { defineConfig } from 'astro/config';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({

2777
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -8,10 +8,16 @@
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"astro": "astro", "astro": "astro",
"check": "tsc --jsx preserve --skipLibCheck", "lint": "eslint . --ext .cjs,.ts,.tsx --ignore-path .gitignore",
"lint:ts": "tsc --jsx preserve --skipLibCheck",
"storybook": "start-storybook -p 6006", "storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook" "build-storybook": "build-storybook"
}, },
"dependencies": {
"clsx": "^1.2.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": { "devDependencies": {
"@astrojs/react": "^1.0.0", "@astrojs/react": "^1.0.0",
"@astrojs/tailwind": "^1.0.0", "@astrojs/tailwind": "^1.0.0",
@ -22,11 +28,27 @@
"@storybook/react": "^6.5.10", "@storybook/react": "^6.5.10",
"@types/react": "^18.0.17", "@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@typescript-eslint/eslint-plugin": "^5.35.1",
"@typescript-eslint/parser": "^5.35.1",
"astro": "^1.0.8", "astro": "^1.0.8",
"clsx": "^1.2.1", "eslint": "^8.23.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-typescript": "^3.5.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-file-progress": "^1.3.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-storybook": "^0.6.4",
"postcss": "^8.4.16",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"react": "^18.2.0", "tailwindcss": "^3.1.8",
"react-dom": "^18.2.0", "vite": "^3.0.9",
"vite-tsconfig-paths": "^3.5.0" "vite-tsconfig-paths": "^3.5.0"
} }
} }

View file

@ -1,16 +1,16 @@
import type { ComponentStory, ComponentMeta } from '@storybook/react'; import type { ComponentMeta, ComponentStory } from '@storybook/react';
import ButtonComponent from './button'; import * as C from './button';
export default { export default {
title: 'Button', title: 'Button',
component: ButtonComponent, component: C.Button,
argTypes: { argTypes: {
onClick: { action: 'onClick' }, onClick: { action: 'onClick' },
}, },
} as ComponentMeta<typeof ButtonComponent>; } as ComponentMeta<typeof C.Button>;
export const Button: ComponentStory<typeof ButtonComponent> = (args) => <ButtonComponent {...args} />; export const Button: ComponentStory<typeof C.Button> = (args) => <C.Button {...args} />;
Button.args = { Button.args = {
children: 'Button text', children: 'Button text',

View file

@ -3,7 +3,7 @@ import type { ComponentPropsWithoutRef } from 'react';
interface ButtonProps extends ComponentPropsWithoutRef<'button'> {} interface ButtonProps extends ComponentPropsWithoutRef<'button'> {}
const Button = ({ className, ...props }: ButtonProps) => ( export const Button = ({ className, ...props }: ButtonProps) => (
<button <button
type="button" type="button"
className={clsx( className={clsx(
@ -13,5 +13,3 @@ const Button = ({ className, ...props }: ButtonProps) => (
{...props} {...props}
/> />
); );
export default Button;

View file

@ -1 +1 @@
export { default as Button } from './button'; export { Button } from './button';

View file

@ -1 +1 @@
export { default as LabelledValue } from './labelled-value'; export { LabelledValue } from './labelled-value';

View file

@ -1,15 +1,13 @@
import type { ComponentStory, ComponentMeta } from '@storybook/react'; import type { ComponentMeta, ComponentStory } from '@storybook/react';
import LabelledValueComponent from './labelled-value'; import * as C from './labelled-value';
export default { export default {
title: 'LabelledValue', title: 'LabelledValue',
component: LabelledValueComponent, component: C.LabelledValue,
} as ComponentMeta<typeof LabelledValueComponent>; } as ComponentMeta<typeof C.LabelledValue>;
export const LabelledValue: ComponentStory<typeof LabelledValueComponent> = (args) => ( export const LabelledValue: ComponentStory<typeof C.LabelledValue> = (args) => <C.LabelledValue {...args} />;
<LabelledValueComponent {...args} />
);
LabelledValue.args = { LabelledValue.args = {
label: 'Label', label: 'Label',

View file

@ -1,15 +1,13 @@
import type { ComponentPropsWithoutRef } from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import type { ComponentPropsWithoutRef } from 'react';
interface LabelledValueProps extends ComponentPropsWithoutRef<'div'> { interface LabelledValueProps extends ComponentPropsWithoutRef<'div'> {
label: string; label: string;
} }
const LabelledValue = ({ label, children, className, ...props }: LabelledValueProps) => ( export const LabelledValue = ({ label, children, className, ...props }: LabelledValueProps) => (
<div className={clsx('text-base space-x-1', className)} {...props}> <div className={clsx('text-base space-x-1', className)} {...props}>
<span className="font-medium text-gray-700">{label}:</span> <span className="font-medium text-gray-700">{label}:</span>
<span className="font-normal text-gray-500">{children}</span> <span className="font-normal text-gray-500">{children}</span>
</div> </div>
); );
export default LabelledValue;

View file

@ -1 +1 @@
export { default as SectionCard } from './section-card'; export { SectionCard } from './section-card';

View file

@ -1,13 +1,13 @@
import type { ComponentStory, ComponentMeta } from '@storybook/react'; import type { ComponentMeta, ComponentStory } from '@storybook/react';
import SectionCardComponent from './section-card'; import * as C from './section-card';
export default { export default {
title: 'SectionCard', title: 'SectionCard',
component: SectionCardComponent, component: C.SectionCard,
} as ComponentMeta<typeof SectionCardComponent>; } as ComponentMeta<typeof C.SectionCard>;
export const SectionCard: ComponentStory<typeof SectionCardComponent> = (args) => <SectionCardComponent {...args} />; export const SectionCard: ComponentStory<typeof C.SectionCard> = (args) => <C.SectionCard {...args} />;
SectionCard.args = { SectionCard.args = {
children: 'Card content', children: 'Card content',

View file

@ -3,8 +3,6 @@ import type { ComponentPropsWithoutRef } from 'react';
interface SectionCardProps extends ComponentPropsWithoutRef<'div'> {} interface SectionCardProps extends ComponentPropsWithoutRef<'div'> {}
const SectionCard = ({ className, ...props }: SectionCardProps) => ( export const SectionCard = ({ className, ...props }: SectionCardProps) => (
<div className={clsx('p-8 bg-white rounded-2xl shadow-lg', className)} {...props} /> <div className={clsx('p-8 bg-white rounded-2xl shadow-lg', className)} {...props} />
); );
export default SectionCard;

View file

@ -1 +1 @@
export { default as Typography } from './typography'; export { Typography } from './typography';

View file

@ -1,13 +1,13 @@
import type { ComponentStory, ComponentMeta } from '@storybook/react'; import type { ComponentMeta, ComponentStory } from '@storybook/react';
import TypographyComponent from './typography'; import * as C from './typography';
export default { export default {
title: 'Typography', title: 'Typography',
component: TypographyComponent, component: C.Typography,
} as ComponentMeta<typeof TypographyComponent>; } as ComponentMeta<typeof C.Typography>;
export const Typography: ComponentStory<typeof TypographyComponent> = (args) => <TypographyComponent {...args} />; export const Typography: ComponentStory<typeof C.Typography> = (args) => <C.Typography {...args} />;
Typography.args = { Typography.args = {
children: 'Typography text', children: 'Typography text',

View file

@ -1,5 +1,5 @@
import type { ComponentPropsWithoutRef } from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import type { ComponentPropsWithoutRef } from 'react';
type TypographyVariant = type TypographyVariant =
| 'item-title' | 'item-title'
@ -40,10 +40,8 @@ const variantToClassName = {
paragraph: 'text-base leading-relaxed font-normal text-gray-500', paragraph: 'text-base leading-relaxed font-normal text-gray-500',
}; };
const Typography = ({ variant = 'paragraph', className, ...props }: TypographyProps) => { export const Typography = ({ variant = 'paragraph', className, ...props }: TypographyProps) => {
const Element = variantToElement[variant]; const Element = variantToElement[variant];
return <Element className={clsx(variantToClassName[variant], className)} {...props} />; return <Element className={clsx(variantToClassName[variant], className)} {...props} />;
}; };
export default Typography;

4
tsconfig.eslint.json Normal file
View file

@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"include": ["**/*.ts", "**/*.tsx", "**/*.js", ".storybook/*.ts"]
}