Skip to content

[BUG] no-arbitrary-value rule is too broad #318

Closed
@Roanmh

Description

@Roanmh

Describe the bug

The lint rule "no-arbitrary-value" creates false-positives where square brackets are used. For example, Tailwinds uses them for attribute selectors and custom modifiers. Tailwinds also uses arbitrary values in other ways than the rule describes: Arbitrary groups and Arbitrary peers are both use the arbitrary value syntax, but feel like a different case than specifying a non-standard amount of px.

We are using the shadcn/UI component library and had to add a number of eslint-disable comments to the files. We also ran into the issue when writing transitions.

To Reproduce

  1. Write a css literal that uses square brackets, e.g. data-[state=open]:pb-8
  2. Run linter

Expected behavior

CSS lints without error

Actual behvior

  472:13  error  Arbitrary value detected in 'data-[state=open]:pb-8'                    tailwindcss/no-arbitrary-value

Environment (please complete the following information):
[can provide if needed]

Additional context
Add any other context about the problem here.

eslint config file or live demo

.eslintrc.cjs
/** @type {import('eslint').Linter.Config} */
module.exports = {
  extends: ["eslint:recommended"],
  ignorePatterns: ["build/index.js"],
  rules: {
    "no-unexpected-multiline": "error",
  },
  root: true,
  env: {
    browser: true,
    commonjs: true,
    es6: true,
  },
  parserOptions: {
    ecmaVersion: "latest",
    sourceType: "module",
    ecmaFeatures: {
      jsx: true,
    },
  },
  overrides: [
    // React
    {
      files: ["**/*.{js,jsx,ts,tsx}"],
      plugins: ["react", "jsx-a11y", "eslint-plugin-tailwindcss"],
      extends: [
        "plugin:react/recommended",
        "plugin:react/jsx-runtime",
        "plugin:jsx-a11y/recommended",
        "prettier",
        // eslint-plugin-tailwindcss recommended preset for defaults
        //"plugin:tailwindcss/recommended",
      ],
      settings: {
        react: {
          version: "detect",
        },
        formComponents: ["Form"],
        linkComponents: [
          { name: "Link", linkAttribute: "to" },
          { name: "NavLink", linkAttribute: "to" },
        ],
      },
      rules: {
        "react/jsx-no-leaked-render": [
          "warn",
          { validStrategies: ["ternary"] },
        ],
        // https://github.com/shadcn-ui/ui/issues/120#issuecomment-1742144083
        "react/prop-types": [2, { ignore: ["className"] }],
        // https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/HEAD/docs/rules/no-arbitrary-value.md
        "tailwindcss/no-arbitrary-value": ["error"],
      },
    },

    // Typescript
    {
      files: ["**/*.{ts,tsx}"],
      plugins: ["@typescript-eslint", "import"],
      parser: "@typescript-eslint/parser",
      settings: {
        "import/internal-regex": "^~/",
        "import/resolver": {
          node: {
            extensions: [".ts", ".tsx"],
          },
          typescript: {
            alwaysTryTypes: true,
          },
        },
      },
      extends: [
        "plugin:@typescript-eslint/recommended",
        "plugin:@typescript-eslint/stylistic",
        "plugin:import/recommended",
        "plugin:import/typescript",
        "prettier",
      ],
      rules: {
        "import/order": [
          "error",
          {
            alphabetize: { caseInsensitive: true, order: "asc" },
            groups: ["builtin", "external", "internal", "parent", "sibling"],
            "newlines-between": "always",
          },
        ],
      },
    },

    // Markdown
    {
      files: ["**/*.md"],
      plugins: ["markdown"],
      extends: ["plugin:markdown/recommended", "prettier"],
    },

    // Jest/Vitest
    {
      files: ["**/*.test.{js,jsx,ts,tsx}"],
      plugins: ["jest", "jest-dom", "testing-library"],
      extends: [
        "plugin:jest/recommended",
        "plugin:jest-dom/recommended",
        "plugin:testing-library/react",
        "prettier",
      ],
      env: {
        "jest/globals": true,
      },
      settings: {
        jest: {
          // we're using vitest which has a very similar API to jest
          // (so the linting plugins work nicely), but it means we have to explicitly
          // set the jest version.
          version: 28,
        },
      },
    },

    // Cypress
    {
      files: ["cypress/**/*.ts"],
      plugins: ["cypress"],
      extends: ["plugin:cypress/recommended", "prettier"],
    },

    // Node
    {
      files: [
        ".eslintrc.cjs",
        "plugin-remix.js",
        "remix.config.js",
        "mocks/**/*.js",
        "utils.js",
      ],
      env: {
        node: true,
      },
    },
  ],
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions