Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 29, 2025

Storybook init adds the eslint-plugin-storybook import but fails to register it in Next.js projects using defineConfig([...]) from eslint/config.

Changes

code/core/src/cli/eslintPlugin.ts

  • Extended configureFlatConfig Case 3 to handle CallExpressions wrapping array arguments
  • Added tracking for defineConfig imports specifically from "eslint/config"
  • Validates the callee matches the imported defineConfig identifier before modifying
  • Added type guards (t.isExpression) and null checks before unwrapping and modifying arrays

code/core/src/cli/eslintPlugin.test.ts

  • Added test case validating Next.js defineConfig pattern from "eslint/config"
  • Added test case ensuring defineConfig from other packages is not modified

Behavior

Before:

import storybook from "eslint-plugin-storybook";

const eslintConfig = defineConfig([
  ...nextVitals,
  ...nextTs,
]); // Plugin import added but not registered

After:

// Only modifies defineConfig from "eslint/config"
import { defineConfig } from "eslint/config";
import storybook from "eslint-plugin-storybook";

const eslintConfig = defineConfig([
  ...nextVitals,
  ...nextTs,
  ...storybook.configs["flat/recommended"]
]);

// defineConfig from other packages is left unchanged (import only added)
import { defineConfig } from "some-other-lib";
const config = defineConfig([...]); // Not modified

All existing ESLint config formats (direct arrays, tseslint.config(), legacy .eslintrc) remain unaffected.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Bug]: Storybook plugin not added to eslint.config during init in Next.js projects</issue_title>
<issue_description>### Describe the bug

When initializing Storybook in a Next.js project, the setup modifies the eslint.config file to include an import for the Storybook ESLint plugin, but does not actually register the plugin in the ESLint configuration array.

Current generated eslint.config:

// 👇 only the import is added, but the plugin isn't added to the config
import storybook from "eslint-plugin-storybook";

import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";

const eslintConfig = defineConfig([
  ...nextVitals,
  ...nextTs,
  // Override default ignores of eslint-config-next.
  globalIgnores([
    ".next/**",
    "out/**",
    "build/**",
    "next-env.d.ts",
  ]),
]);

export default eslintConfig;

Expected behaviour
Storybook’s init process should both:

  • Add the eslint-plugin-storybook import and
  • Extend the ESLint configuration with the Storybook plugin, e.g.:

Reproduction steps

  1. Create a new Next.js project (npx gitpick storybookjs/sandboxes/tree/next/nextjs-vite/default-ts/before-storybook)
  2. Run npx storybook@latest init
  3. Inspect the generated eslint.config.mjs (or eslint.config.mjs)

System

-

Additional context

No response</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 29, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch copilot/fix-storybook-plugin-eslint-config

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI and others added 4 commits October 29, 2025 09:43
- Modified configureFlatConfig to handle CallExpression wrappers like defineConfig([...])
- Added test case for Next.js-style ESLint configuration
- All existing tests continue to pass

Co-authored-by: yannbf <1671563+yannbf@users.noreply.github.com>
- Added proper type checks before accessing array arguments
- Verify argument is Expression or TS type before unwrapping
- Addresses code review feedback about unsafe type casting

Co-authored-by: yannbf <1671563+yannbf@users.noreply.github.com>
- Removed redundant TS type checks from type guard
- t.isExpression is sufficient since unwrapTSExpression handles TS types
- All tests continue to pass

Co-authored-by: yannbf <1671563+yannbf@users.noreply.github.com>
- Prevent potential runtime error when unwrapTSExpression returns null/undefined
- Makes code more defensive and robust
- All tests continue to pass

Co-authored-by: yannbf <1671563+yannbf@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix Storybook plugin not added to eslint.config during init Oct 29, 2025
Copilot AI requested a review from yannbf October 29, 2025 09:58
Copilot finished work on behalf of yannbf October 29, 2025 09:58

if (t.isArrayExpression(init)) {
init.elements.push(t.spreadElement(storybookConfig));
} else if (t.isCallExpression(init) && init.arguments.length > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot only if it's defineConfig from import { defineConfig } from "eslint/config"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 72ec435. Now specifically checks that defineConfig is imported from "eslint/config" before modifying the array. Added test to verify we don't modify defineConfig from other sources.

- Track eslintDefineConfigLocalName from "eslint/config" imports
- Check callee matches defineConfig before modifying array
- Add test for defineConfig from non-eslint/config source
- Ensures we don't modify arbitrary function calls

Co-authored-by: yannbf <1671563+yannbf@users.noreply.github.com>
Copilot AI changed the title Fix: Add Storybook ESLint plugin to defineConfig-wrapped configurations Oct 29, 2025
Copilot finished work on behalf of yannbf October 29, 2025 14:31
Copilot AI requested a review from yannbf October 29, 2025 14:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants