import js from '@eslint/js'; import tseslint from 'typescript-eslint'; import react from 'eslint-plugin-react'; import reactHooks from 'eslint-plugin-react-hooks'; import jsxA11y from 'eslint-plugin-jsx-a11y'; import prettier from 'eslint-config-prettier'; export default tseslint.config( // Global ignores { ignores: [ 'node_modules/', 'storybook-static/', 'src/theme/generated/', 'tokens/export/', 'style-dictionary/', '*.config.js', '*.config.ts', ], }, // Base JS recommended js.configs.recommended, // TypeScript recommended ...tseslint.configs.recommended, // React { plugins: { react }, settings: { react: { version: 'detect' }, }, rules: { 'react/react-in-jsx-scope': 'off', // React 18 JSX transform 'react/prop-types': 'off', // TypeScript handles this 'react/display-name': 'off', // We use manual displayName assignment }, }, // React Hooks { plugins: { 'react-hooks': reactHooks }, rules: { 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn', }, }, // Accessibility — critical for FA's elderly/distressed audience { plugins: { 'jsx-a11y': jsxA11y }, rules: { ...jsxA11y.configs.recommended.rules, }, }, // Project-specific rules { rules: { '@typescript-eslint/no-explicit-any': 'error', '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', }], 'no-console': 'warn', }, }, // Story files — relax rules for Storybook patterns { files: ['**/*.stories.tsx', '**/*.stories.ts'], rules: { 'react-hooks/rules-of-hooks': 'off', // Storybook render functions use hooks but aren't uppercase components 'no-console': 'off', // Console in story actions is expected }, }, // Prettier must be last — disables rules that conflict with formatting prettier, );