Files
supabase/packages/eslint-config-supabase/next.js
T
Anthony Lio e3febf3b63 feat(lint): add shadcn lint warnings (#50676)
## Problem

six apps had no shared lint checks for invalid tailwind classes,
off-scale values, and raw colors.

## Solution

add @shadcn/lint warnings with narrow exceptions for existing theme
colors and artwork. fix several invalid classes. the existing lint
command reports findings without blocking prs on the current warning
count.

## Review instructions

1. check the shared rules and app-specific exceptions.
2. run `pnpm --filter design-system lint` and confirm it reports shadcn
warnings without errors.

## Checklist

Check all before review:

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which references
[WORD_LIST](https://github.com/supabase/supabase/blob/master/apps/docs/WORD_LIST.md)
and the docs
[CONTRIBUTING](https://github.com/supabase/supabase/blob/master/apps/docs/CONTRIBUTING.md)
guide


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved vertical alignment of checkbox labels and supporting text in
dialogs, settings, and examples.
* Corrected alignment of organization member details and the color
styling of deprecated chart text.
* Standardized spacing in the date and time editor without changing its
appearance or behavior.

* **Developer Experience**
* Updated linting and UI configuration across several apps to support
consistent style checks.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-25 17:50:50 +03:00

139 lines
3.9 KiB
JavaScript

const { defineConfig } = require('eslint/config')
const { plugin: shadcn } = require('@shadcn/lint')
const prettierConfig = require('eslint-config-prettier/flat')
const { default: turboConfig } = require('eslint-config-turbo/flat')
const tanstackQuery = require('@tanstack/eslint-plugin-query')
const tsparser = require('@typescript-eslint/parser')
const nextCoreWebVitals = require('eslint-config-next/core-web-vitals')
const NEXT_PLUGIN_FILES = ['**/*.{js,jsx,mjs,ts,tsx,mts,cts}']
// Custom Supabase rules
const noAwaitBeforeCopyToClipboard = require('./rules/no-await-before-copy-to-clipboard')
const requireExplicitTabIndex = require('./rules/require-explicit-tabindex')
// Transitional config that turns off all the React Compiler hook rules that come bundled
// with core-web-vitals@16. We want to upgrade to get exhaustive-deps updates without
// blowing up our error count.
const compilerRulesOff = {}
for (const cfg of nextCoreWebVitals) {
for (const key of Object.keys(cfg.rules ?? {})) {
if (
key.startsWith('react-hooks/') &&
key !== 'react-hooks/exhaustive-deps' &&
key !== 'react-hooks/rules-of-hooks'
) {
compilerRulesOff[key] = 'off'
}
}
}
// Custom Supabase ESLint plugin
const supabasePlugin = {
rules: {
'no-await-before-copy-to-clipboard': noAwaitBeforeCopyToClipboard,
'require-explicit-tabindex': requireExplicitTabIndex,
},
}
// TypeScript ESLint config for TypeScript files
const typescriptConfig = {
name: 'typescript',
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
},
plugins: {
supabase: supabasePlugin,
},
rules: {
'@typescript-eslint/no-explicit-any': 'warn',
'supabase/no-await-before-copy-to-clipboard': 'error',
'supabase/require-explicit-tabindex': 'error',
},
}
module.exports = defineConfig([
// Global ignore for build output and static assets
{ ignores: ['.next', 'dist', 'public', '.contentlayer'] },
// eslint-config-next v16 registers its plugins for `.mts`/`.cts` (v15 didn't lint
// them at all), which newly surfaces errors in build/tooling scripts. Keep the prior
// lint surface and leave `.mts`/`.cts` unlinted; revisit as a separate change.
{ ignores: ['**/*.mts', '**/*.cts'] },
turboConfig,
prettierConfig,
{
name: 'supabase/shadcn',
files: NEXT_PLUGIN_FILES,
plugins: { shadcn },
settings: {
shadcn: {
componentImports: ['^ui(/|$)', '^ui-patterns(/|$)'],
},
},
rules: {
'shadcn/no-unknown-classes': ['warn', { allow: ['not-prose'] }],
'shadcn/no-arbitrary-values': ['warn', { allow: ['layout'] }],
'shadcn/no-raw-colors': 'warn',
},
},
tanstackQuery.configs['flat/recommended'],
{
rules: {
'@tanstack/query/exhaustive-deps': 'warn',
},
},
typescriptConfig,
...nextCoreWebVitals,
{
files: NEXT_PLUGIN_FILES,
linterOptions: {
reportUnusedDisableDirectives: 'warn',
},
rules: {
...compilerRulesOff,
'@next/next/no-html-link-for-pages': 'off',
'react/jsx-key': 'off',
'no-restricted-imports': [
'warn',
{
name: 'react-data-grid',
message: 'Please use @tanstack/react-table instead.',
},
{
name: 'react-contexify',
message: 'Please use ContextMenu from the ui package instead.',
},
],
},
},
{
// check for default exports in all files except app and pages folders.
ignores: [
'pages/**/*.ts',
'app/**/*.ts',
'pages/**/*.tsx',
'app/**/*.tsx',
'components/interfaces/**/content/**/content.tsx',
'vitest.config.ts',
'postcss.config.js',
'postcss.config.cjs',
'velite.config.js',
],
rules: {
'no-restricted-exports': [
'warn',
{
restrictDefaultExports: {
direct: true,
},
},
],
},
},
])