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"
},
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/iconsrather than with@storybook/iconsitself.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.
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.