Skip to content

[Bug]: Storybooks do not properly satisfy peer dependency. #34610

@XionWCFM

Description

@XionWCFM

Describe the bug

This issue is particularly evident in the Yarn PnP environment, but

since it relies on the package manager implicitly resolving package misconfigurations, I believe this is a problem that needs to be improved within Storybook itself, rather than being solved by simply not using Yarn PnP.

From what I have observed, most addons have peer dependency issues, and the root cause of the problem is often the failure to properly propagate the peer dependency of @storybook/icons.

However, this is closer to a problem with the packages using @storybook/icons rather than with @storybook/icons itself.

I think it would be good to fix this issue. What do you think?

If you do not have the resources to fix this, I can do the work myself.

For example, if you look at @storybook/addon-vitest, it relies on @storybook/icons as an internal dependency.

@storybook/icons requires "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",

"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"

but @storybook/addon-vitest neither provides react and react-dom as dependencies nor specifies react and react-dom as peer-dependencies.

These kinds of issues are widespread across Storybook packages.

{
  "name": "@storybook/addon-vitest",
  "version": "10.4.0-alpha.10",
  "description": "Storybook Vitest addon: Blazing fast component testing using stories",
  "keywords": [
    "storybook",
    "storybook-addon",
    "vitest",
    "testing",
    "test",
    "component",
    "components",
    "component-testing",
    "react",
    "vue",
    "svelte",
    "web-components"
  ],
  "homepage": "https://github.com/storybookjs/storybook/tree/next/code/addons/vitest",
  "bugs": {
    "url": "https://github.com/storybookjs/storybook/issues"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/storybookjs/storybook.git",
    "directory": "code/addons/vitest"
  },
  "funding": {
    "type": "opencollective",
    "url": "https://opencollective.com/storybook"
  },
  "license": "MIT",
  "type": "module",
  "imports": {
    "#manager-store": {
      "storybook": "./src/manager-store.mock.ts",
      "default": "./src/manager-store.ts"
    }
  },
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "code": "./src/index.ts",
      "default": "./dist/index.js"
    },
    "./constants": {
      "types": "./dist/constants.d.ts",
      "code": "./src/constants.ts",
      "default": "./dist/constants.js"
    },
    "./internal/coverage-reporter": "./dist/node/coverage-reporter.js",
    "./internal/global-setup": "./dist/vitest-plugin/global-setup.js",
    "./internal/setup-file": "./dist/vitest-plugin/setup-file.js",
    "./internal/setup-file-with-project-annotations": "./dist/vitest-plugin/setup-file-with-project-annotations.js",
    "./internal/test-utils": "./dist/vitest-plugin/test-utils.js",
    "./manager": "./dist/manager.js",
    "./package.json": "./package.json",
    "./postinstall": "./dist/postinstall.js",
    "./preset": "./dist/preset.js",
    "./vitest": "./dist/node/vitest.js",
    "./vitest-plugin": {
      "types": "./dist/vitest-plugin/index.d.ts",
      "code": "./src/vitest-plugin/index.ts",
      "default": "./dist/vitest-plugin/index.js"
    }
  },
  "files": [
    "dist/**/*",
    "templates/**/*",
    "!dist/dummy.*",
    "README.md",
    "*.mjs",
    "*.js",
    "*.cjs",
    "*.d.ts",
    "!src/**/*"
  ],
  "dependencies": {
    "@storybook/global": "^5.0.0",
    "@storybook/icons": "^2.0.1"
  },
  "devDependencies": {
    "@storybook/addon-a11y": "workspace:*",
    "@types/istanbul-lib-report": "^3.0.3",
    "@types/micromatch": "^4.0.0",
    "@types/node": "^22.19.1",
    "@types/semver": "^7.7.1",
    "@vitest/browser-playwright": "^4.1.0",
    "@vitest/runner": "^4.1.0",
    "empathic": "^2.0.0",
    "es-toolkit": "^1.43.0",
    "istanbul-lib-report": "^3.0.1",
    "micromatch": "^4.0.8",
    "pathe": "^1.1.2",
    "picocolors": "^1.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "semver": "^7.7.3",
    "sirv": "^2.0.4",
    "slash": "^5.0.0",
    "tinyglobby": "^0.2.10",
    "tree-kill": "^1.2.2",
    "ts-dedent": "^2.2.0",
    "typescript": "^5.9.3",
    "vitest": "^4.1.0"
  },
  "peerDependencies": {
    "@vitest/browser": "^3.0.0 || ^4.0.0",
    "@vitest/browser-playwright": "^4.0.0",
    "@vitest/runner": "^3.0.0 || ^4.0.0",
    "storybook": "workspace:^",
    "vitest": "^3.0.0 || ^4.0.0"
  },
  "peerDependenciesMeta": {
    "@vitest/browser": {
      "optional": true
    },
    "@vitest/browser-playwright": {
      "optional": true
    },
    "@vitest/runner": {
      "optional": true
    },
    "vitest": {
      "optional": true
    }
  },
  "publishConfig": {
    "access": "public"
  },
  "storybook": {
    "displayName": "Test",
    "unsupportedFrameworks": [
      "react-native"
    ],
    "icon": "https://user-images.githubusercontent.com/263385/101991666-479cc600-3c7c-11eb-837b-be4e5ffa1bb8.png"
  }
}
{
  "name": "@storybook/icons",
  "version": "2.0.1",
  "description": "Icon library from the Storybook team",
  "homepage": "https://github.com/storybookjs/icons#readme",
  "bugs": {
    "url": "https://github.com/storybookjs/icons/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/storybookjs/icons.git"
  },
  "license": "MIT",
  "author": {
    "name": "cdedreuille",
    "email": "charles@chromatic.com"
  },
  "sideEffects": false,
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "files": [
    "dist"
  ],
  "scripts": {
    "build": "tsup --onSuccess \"cp -a public/. dist/public\"",
    "build-storybook": "storybook build",
    "changeset": "changeset",
    "chromatic": "npx chromatic --project-token=chpt_d0c5927e55681dd",
    "dev": "concurrently  -n \"Build,SB\" \"pnpm build --watch\" \"pnpm storybook\" ",
    "format": "prettier --write .",
    "generate-icons": "jiti ./src/generate.ts",
    "lint": "oxlint",
    "release": "pnpm build && pnpm changeset publish",
    "storybook": "storybook dev -p 6006",
    "type-check": "tsc"
  },
  "lint-staged": {
    "*": "prettier --write"
  },
  "devDependencies": {
    "@changesets/changelog-github": "^0.5.1",
    "@changesets/cli": "^2.29.6",
    "@chromatic-com/storybook": "^4.1.1",
    "@storybook/addon-a11y": "10.2.0-beta.4",
    "@storybook/addon-docs": "10.2.0-beta.4",
    "@storybook/react-vite": "10.2.0-beta.4",
    "@svgr/core": "5.5.0",
    "@svgr/plugin-prettier": "5.5.0",
    "@svgr/plugin-svgo": "5.5.0",
    "@types/node": "^22.12.0",
    "@types/react": "^18.2.14",
    "@types/react-dom": "^18.0.11",
    "@vitejs/plugin-react": "^5.1.0",
    "axios": "^1.13.2",
    "chromatic": "^13.3.3",
    "concurrently": "^9.2.1",
    "dotenv": "^17.2.3",
    "figma-api-exporter": "0.0.2",
    "figma-js": "1.16.0",
    "figma-transformer": "2.1.0",
    "jiti": "^2.6.1",
    "lint-staged": "^16.2.6",
    "oxlint": "^1.28.0",
    "picocolors": "^1.1.1",
    "pkg-pr-new": "^0.0.57",
    "prettier": "^3.6.2",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "storybook": "10.2.0-beta.4",
    "tsup": "^8.5.0",
    "typescript": "^5.9.3",
    "vite": "^7.2.2"
  },
  "peerDependencies": {
    "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
    "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
  },
  "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0",
  "publishConfig": {
    "access": "public",
    "registry": "https://registry.npmjs.org"
  }
}

Solution

The packages that depend on the library's dependencies must satisfy peer dependencies.

There are two main methods. The first is to explicitly specify it as dependencies, and the second is to inherit peer dependencies.

For example, the problem with @storybook/icons can be solved like this.

  "dependencies": {
    "@storybook/global": "^5.0.0",
    "@storybook/icons": "^2.0.1",
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },

This resolves the peer dependency issue. Of course, since it is natural for React to be maintained as a singleton, doing it this way would be a better approach, at least for libraries like React.

  "dependencies": {
    "@storybook/global": "^5.0.0",
    "@storybook/icons": "^2.0.1",
  },
  "peerDependencies": {
    "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
    "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
  },

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions