Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b3e8ea8
feat: Update Storybook Header component and related configurations
yatishgoel Apr 26, 2025
8c50b52
Merge branch 'next' into fix/nextjs15-link-component-override
yatishgoel Jan 30, 2026
01e498a
Merge branch 'next' into fix/nextjs15-link-component-override
valentinpalkovic Jan 30, 2026
1330387
Merge branch 'next' into fix/nextjs15-link-component-override
valentinpalkovic Feb 2, 2026
5a45292
Merge branch 'next' into fix/nextjs15-link-component-override
yatishgoel Feb 3, 2026
ca1693a
Merge branch 'next' into fix/nextjs15-link-component-override
valentinpalkovic Feb 3, 2026
e9b5ab1
Update Next.js package.json to include code path for link mock
yatishgoel Feb 5, 2026
372b103
Merge branch 'storybookjs:next' into fix/nextjs15-link-component-over…
yatishgoel Feb 7, 2026
41d8856
Enhance Next.js build configuration by adding link mock entry and upd…
yatishgoel Feb 7, 2026
5c1eb43
Builder-Vite: Update dependencies react-vite framework
valentinpalkovic Feb 9, 2026
7bc1553
Refactor Next.js link mock implementation to enhance functionality an…
yatishgoel Feb 9, 2026
25e35bc
Merge branch 'next' into fix/nextjs15-link-component-override
yatishgoel Feb 9, 2026
ada93bc
Addon-Vitest: Improve config file detection in monorepos
valentinpalkovic Feb 9, 2026
27628cd
Fix: Add missing import statement in Next.js link mock implementation…
yatishgoel Feb 9, 2026
a755ba6
Dedupe
valentinpalkovic Feb 11, 2026
dd088b3
Merge pull request #33810 from storybookjs/valentin/fix-sec-issue
valentinpalkovic Feb 11, 2026
2696bdb
Merge branch 'next-release' into next
storybook-bot Feb 11, 2026
40e556a
Merge pull request #31251 from yatishgoel/fix/nextjs15-link-component…
valentinpalkovic Feb 11, 2026
b09081a
Harden lookup of Vitest config
valentinpalkovic Feb 12, 2026
b6d6bf1
Addon-Vitest: Support Vitest canaries
valentinpalkovic Feb 12, 2026
d7c87fa
Merge pull request #33814 from storybookjs/valentin/improve-config-fi…
valentinpalkovic Feb 12, 2026
992d908
Merge pull request #33833 from storybookjs/valentin/support-canary-re…
valentinpalkovic Feb 12, 2026
99e6b34
Write changelog for 10.3.0-alpha.6 [skip ci]
storybook-bot Feb 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 10.3.0-alpha.6

- Addon-Vitest: Improve config file detection in monorepos - [#33814](https://github.com/storybookjs/storybook/pull/33814), thanks @valentinpalkovic!
- Addon-Vitest: Support Vitest canaries - [#33833](https://github.com/storybookjs/storybook/pull/33833), thanks @valentinpalkovic!
- Builder-Vite: Update dependencies react-vite framework - [#33810](https://github.com/storybookjs/storybook/pull/33810), thanks @valentinpalkovic!
- Next.js: Fix Link component override in appDirectory configuration - [#31251](https://github.com/storybookjs/storybook/pull/31251), thanks @yatishgoel!

## 10.3.0-alpha.5

- Builder-Vite: Use relative path for mocker entry in production builds - [#33792](https://github.com/storybookjs/storybook/pull/33792), thanks @DukeDeSouth!
Expand Down
55 changes: 45 additions & 10 deletions code/addons/vitest/src/node/vitest-manager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { existsSync } from 'node:fs';
import { existsSync, readFileSync } from 'node:fs';

import type {
CoverageOptions,
Expand All @@ -13,7 +13,8 @@ import { Tag } from 'storybook/internal/core-server';
import type { StoryId, StoryIndex, StoryIndexEntry } from 'storybook/internal/types';

import * as find from 'empathic/find';
import path, { dirname, join, normalize } from 'pathe';
import * as walk from 'empathic/walk';
import path, { dirname, join, normalize, resolve } from 'pathe';
// eslint-disable-next-line depend/ban-dependencies
import slash from 'slash';

Expand Down Expand Up @@ -75,19 +76,53 @@ export class VitestManager {
: { enabled: false }
) as CoverageOptions;

const vitestWorkspaceConfig = find.any(
[
...VITEST_WORKSPACE_FILE_EXTENSION.map((ext) => `vitest.workspace.${ext}`),
...VITEST_CONFIG_FILE_EXTENSIONS.map((ext) => `vitest.config.${ext}`),
],
{ last: getProjectRoot() }
);
// In monorepos, the Storybook configDir (e.g. packages/web-app/.storybook) identifies
// the sub-package. We start the Vitest config search from its parent (the package root)
// and traverse upward to the project root, so configs in both sub-packages and the
// monorepo root are found. Without this, find.any defaults to process.cwd() which may
// be the monorepo root and would miss sub-package configs entirely.
const configDir = this.testManager.storybookOptions.configDir;
const packageRoot = configDir ? dirname(resolve(configDir)) : undefined;

const configFiles = [
...VITEST_WORKSPACE_FILE_EXTENSION.map((ext) => `vitest.workspace.${ext}`),
...VITEST_CONFIG_FILE_EXTENSIONS.flatMap((ext) => [
`vitest.config.${ext}`,
`vite.config.${ext}`,
]),
];

const potentialConfigFileLocations = walk.up(packageRoot || process.cwd(), {
last: getProjectRoot(),
});

let vitestWorkspaceConfig: string | undefined;
let firstVitestConfig: string | undefined;

for (const location of potentialConfigFileLocations) {
for (const file of configFiles) {
const maybe = find.any([file], { cwd: location, last: getProjectRoot() });
if (maybe && existsSync(maybe)) {
firstVitestConfig ??= maybe;
const content = readFileSync(maybe, 'utf8');
if (content.includes('storybookTest') || content.includes('@storybook/addon-vitest')) {
vitestWorkspaceConfig = dirname(maybe);
break;
}
}
}
if (vitestWorkspaceConfig) {
break;
}
}

const projectName = 'storybook:' + process.env.STORYBOOK_CONFIG_DIR;

const vitestConfigFallbackLocation = firstVitestConfig || packageRoot || process.cwd();

try {
this.vitest = await createVitest('test', {
root: vitestWorkspaceConfig ? dirname(vitestWorkspaceConfig) : process.cwd(),
root: vitestWorkspaceConfig ?? vitestConfigFallbackLocation,
watch: true,
passWithNoTests: false,
project: [projectName],
Expand Down
22 changes: 22 additions & 0 deletions code/core/src/cli/AddonVitestService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,28 @@ describe('AddonVitestService', () => {
expect(result.reasons).toBeUndefined();
});

it('should return compatible when vitest prerelease >= 3.0.0', async () => {
vi.mocked(mockPackageManager.getInstalledVersion)
.mockResolvedValueOnce('3.0.0-beta.1') // vitest
.mockResolvedValueOnce(null); // msw

const result = await service.validatePackageVersions();

expect(result.compatible).toBe(true);
expect(result.reasons).toBeUndefined();
});

it('should return compatible when vitest canary is used', async () => {
vi.mocked(mockPackageManager.getInstalledVersion)
.mockResolvedValueOnce('0.0.0-833c515fa25cef20905a7f9affb156dfa6f151ab') // vitest
.mockResolvedValueOnce(null); // msw

const result = await service.validatePackageVersions();

expect(result.compatible).toBe(true);
expect(result.reasons).toBeUndefined();
});

it('should return compatible when vitest >=4.0.0', async () => {
vi.mocked(mockPackageManager.getInstalledVersion)
.mockResolvedValueOnce('4.0.0') // vitest
Expand Down
3 changes: 2 additions & 1 deletion code/core/src/cli/AddonVitestService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,9 @@ export class AddonVitestService {
// Check Vitest version (>=3.0.0 - stricter requirement from postinstall)
const vitestVersionSpecifier = await this.packageManager.getInstalledVersion('vitest');
const coercedVitestVersion = vitestVersionSpecifier ? coerce(vitestVersionSpecifier) : null;
const isCanary = coercedVitestVersion?.version.startsWith('0.0.0') ?? false;

if (coercedVitestVersion && !satisfies(coercedVitestVersion, '>=3.0.0')) {
if (coercedVitestVersion && !satisfies(coercedVitestVersion, '>=3.0.0') && !isCanary) {
reasons.push(
`The addon requires Vitest 3.0.0 or higher. You are currently using ${vitestVersionSpecifier}.`
);
Expand Down
4 changes: 4 additions & 0 deletions code/frameworks/nextjs/build-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ const config: BuildEntries = {
exportEntries: ['./navigation.mock'],
entryPoint: './src/export-mocks/navigation/index.ts',
},
{
exportEntries: ['./link.mock'],
entryPoint: './src/export-mocks/link/index.tsx',
},
{
exportEntries: ['./router.mock'],
entryPoint: './src/export-mocks/router/index.ts',
Expand Down
5 changes: 5 additions & 0 deletions code/frameworks/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
"./image-context": "./dist/image-context.js",
"./images/next-image": "./dist/images/next-image.js",
"./images/next-legacy-image": "./dist/images/next-legacy-image.js",
"./link.mock": {
"types": "./dist/export-mocks/link/index.d.ts",
"code": "./src/export-mocks/link/index.tsx",
"default": "./dist/export-mocks/link/index.js"
},
"./navigation.mock": {
"types": "./dist/export-mocks/navigation/index.d.ts",
"code": "./src/export-mocks/navigation/index.ts",
Expand Down
45 changes: 45 additions & 0 deletions code/frameworks/nextjs/src/export-mocks/link/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';

import { fn } from 'storybook/test';

const linkAction = fn().mockName('next/link::Link');

const MockLink = React.forwardRef<HTMLAnchorElement, any>(function MockLink(
{
href,
as: _as,
replace,
scroll,
shallow,
prefetch,
passHref,
legacyBehavior,
locale,
onClick,
children,
...rest
},
ref
) {
const hrefString =
typeof href === 'object'
? `${href.pathname || ''}${href.query ? '?' + new URLSearchParams(href.query).toString() : ''}${href.hash || ''}`
: href;

const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault();
onClick?.(e);
linkAction(hrefString, { replace, scroll, shallow, prefetch, locale });
};

return (
<a ref={ref} href={hrefString} onClick={handleClick} {...rest}>
{children}
</a>
);
});

MockLink.displayName = 'NextLink';

export default MockLink;
export { MockLink as Link };
1 change: 1 addition & 0 deletions code/frameworks/nextjs/src/export-mocks/webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const mapping = {
'next/navigation': '@storybook/nextjs/navigation.mock',
'next/router': '@storybook/nextjs/router.mock',
'next/cache': '@storybook/nextjs/cache.mock',
'next/link': '@storybook/nextjs/link.mock',
...getCompatibilityAliases(),
};

Expand Down
2 changes: 1 addition & 1 deletion code/frameworks/react-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"!src/**/*"
],
"dependencies": {
"@joshwooding/vite-plugin-react-docgen-typescript": "^0.6.3",
"@joshwooding/vite-plugin-react-docgen-typescript": "^0.6.4",
"@rollup/pluginutils": "^5.0.2",
"@storybook/builder-vite": "workspace:*",
"@storybook/react": "workspace:*",
Expand Down
3 changes: 2 additions & 1 deletion code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,5 +220,6 @@
"Dependency Upgrades"
]
]
}
},
"deferredNextVersion": "10.3.0-alpha.6"
}
2 changes: 1 addition & 1 deletion docs/versions/next.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":"10.3.0-alpha.5","info":{"plain":"- Builder-Vite: Use relative path for mocker entry in production builds - [#33792](https://github.com/storybookjs/storybook/pull/33792), thanks @DukeDeSouth!\n- CLI: Support addon-vitest setup when --skip-install is passed - [#33718](https://github.com/storybookjs/storybook/pull/33718), thanks @valentinpalkovic!\n- CSF: Fix cross-file story imports in csf-factories codemod - [#33723](https://github.com/storybookjs/storybook/pull/33723), thanks @yatishgoel!\n- Compile: reduce VCPUs for CI check task from 4 to 3 - [#33822](https://github.com/storybookjs/storybook/pull/33822), thanks @valentinpalkovic!\n- Core: Ignore empty files when indexing - [#33782](https://github.com/storybookjs/storybook/pull/33782), thanks @JReinhold!\n- Globals: Repair dynamicTitle: false for user-defined tools - [#33284](https://github.com/storybookjs/storybook/pull/33284), thanks @ia319!\n- Logger: Honor --loglevel for npmlog output - [#33776](https://github.com/storybookjs/storybook/pull/33776), thanks @LouisLau-art!\n- Telemetry: Add Expo metaframework - [#33783](https://github.com/storybookjs/storybook/pull/33783), thanks @copilot-swe-agent!\n- Telemetry: Add init exit event - [#33773](https://github.com/storybookjs/storybook/pull/33773), thanks @valentinpalkovic!\n- Telemetry: Add share events - [#33766](https://github.com/storybookjs/storybook/pull/33766), thanks @ndelangen!\n- Test: Update event creation logic in user-event package - [#33787](https://github.com/storybookjs/storybook/pull/33787), thanks @valentinpalkovic!\n- Viewport: Skip viewport validation before parameters load - [#33794](https://github.com/storybookjs/storybook/pull/33794), thanks @ia319!"}}
{"version":"10.3.0-alpha.6","info":{"plain":"- Addon-Vitest: Improve config file detection in monorepos - [#33814](https://github.com/storybookjs/storybook/pull/33814), thanks @valentinpalkovic!\n- Addon-Vitest: Support Vitest canaries - [#33833](https://github.com/storybookjs/storybook/pull/33833), thanks @valentinpalkovic!\n- Builder-Vite: Update dependencies react-vite framework - [#33810](https://github.com/storybookjs/storybook/pull/33810), thanks @valentinpalkovic!\n- Next.js: Fix Link component override in appDirectory configuration - [#31251](https://github.com/storybookjs/storybook/pull/31251), thanks @yatishgoel!"}}
67 changes: 21 additions & 46 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3301,12 +3301,12 @@ __metadata:
languageName: node
linkType: hard

"@isaacs/brace-expansion@npm:^5.0.0":
version: 5.0.0
resolution: "@isaacs/brace-expansion@npm:5.0.0"
"@isaacs/brace-expansion@npm:^5.0.1":
version: 5.0.1
resolution: "@isaacs/brace-expansion@npm:5.0.1"
dependencies:
"@isaacs/balanced-match": "npm:^4.0.1"
checksum: 10c0/b4d4812f4be53afc2c5b6c545001ff7a4659af68d4484804e9d514e183d20269bb81def8682c01a22b17c4d6aed14292c8494f7d2ac664e547101c1a905aa977
checksum: 10c0/e5d67c7bbf1f17b88132a35bc638af306d48acbb72810d48fa6e6edd8ab375854773108e8bf70f021f7ef6a8273455a6d1f0c3b5aa2aff06ce7894049ab77fb8
languageName: node
linkType: hard

Expand Down Expand Up @@ -3395,19 +3395,19 @@ __metadata:
languageName: node
linkType: hard

"@joshwooding/vite-plugin-react-docgen-typescript@npm:^0.6.3":
version: 0.6.3
resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.6.3"
"@joshwooding/vite-plugin-react-docgen-typescript@npm:^0.6.4":
version: 0.6.4
resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.6.4"
dependencies:
glob: "npm:^11.1.0"
glob: "npm:^13.0.1"
react-docgen-typescript: "npm:^2.2.2"
peerDependencies:
typescript: ">= 4.3.x"
vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 10c0/e68d2884235b8290673c17a13bc303a088feba6ce0a275ab0778b50e90b967f5dffdcf71ed3197e9cdf07607594a9cb2a86e3ea6e4eb8962b50d61078107bac3
checksum: 10c0/73149b2d41d5b8eff7dfe4d037a6903fe4123ae46f3928d88535020539f44159c4ea1b342e6a77d4c14219f2f743fea0ef96e81279cce8b6d247dc4d582e27ed
languageName: node
linkType: hard

Expand Down Expand Up @@ -8371,7 +8371,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@storybook/react-vite@workspace:code/frameworks/react-vite"
dependencies:
"@joshwooding/vite-plugin-react-docgen-typescript": "npm:^0.6.3"
"@joshwooding/vite-plugin-react-docgen-typescript": "npm:^0.6.4"
"@rollup/pluginutils": "npm:^5.0.2"
"@storybook/builder-vite": "workspace:*"
"@storybook/react": "workspace:*"
Expand Down Expand Up @@ -17605,7 +17605,7 @@ __metadata:
languageName: node
linkType: hard

"foreground-child@npm:^3.1.0, foreground-child@npm:^3.3.1":
"foreground-child@npm:^3.1.0":
version: 3.3.1
resolution: "foreground-child@npm:3.3.1"
dependencies:
Expand Down Expand Up @@ -18215,30 +18215,14 @@ __metadata:
languageName: node
linkType: hard

"glob@npm:^11.1.0":
version: 11.1.0
resolution: "glob@npm:11.1.0"
"glob@npm:^13.0.0, glob@npm:^13.0.1":
version: 13.0.1
resolution: "glob@npm:13.0.1"
dependencies:
foreground-child: "npm:^3.3.1"
jackspeak: "npm:^4.1.1"
minimatch: "npm:^10.1.1"
minimatch: "npm:^10.1.2"
minipass: "npm:^7.1.2"
package-json-from-dist: "npm:^1.0.0"
path-scurry: "npm:^2.0.0"
bin:
glob: dist/esm/bin.mjs
checksum: 10c0/1ceae07f23e316a6fa74581d9a74be6e8c2e590d2f7205034dd5c0435c53f5f7b712c2be00c3b65bf0a49294a1c6f4b98cd84c7637e29453b5aa13b79f1763a2
languageName: node
linkType: hard

"glob@npm:^13.0.0":
version: 13.0.0
resolution: "glob@npm:13.0.0"
dependencies:
minimatch: "npm:^10.1.1"
minipass: "npm:^7.1.2"
path-scurry: "npm:^2.0.0"
checksum: 10c0/8e2f5821f3f7c312dd102e23a15b80c79e0837a9872784293ba2e15ec73b3f3749a49a42a31bfcb4e52c84820a474e92331c2eebf18819d20308f5c33876630a
checksum: 10c0/af7b863dec8dff74f61d7d6e53104e1f6bbdd482157a196cade8ed857481e876ec35181b38a059b2a7b93ea3b08248f4ff0792fef6dc91814fd5097a716f48e4
languageName: node
linkType: hard

Expand Down Expand Up @@ -20249,15 +20233,6 @@ __metadata:
languageName: node
linkType: hard

"jackspeak@npm:^4.1.1":
version: 4.1.1
resolution: "jackspeak@npm:4.1.1"
dependencies:
"@isaacs/cliui": "npm:^8.0.2"
checksum: 10c0/84ec4f8e21d6514db24737d9caf65361511f75e5e424980eebca4199f400874f45e562ac20fa8aeb1dd20ca2f3f81f0788b6e9c3e64d216a5794fd6f30e0e042
languageName: node
linkType: hard

"jake@npm:^10.8.5":
version: 10.8.7
resolution: "jake@npm:10.8.7"
Expand Down Expand Up @@ -22457,12 +22432,12 @@ __metadata:
languageName: node
linkType: hard

"minimatch@npm:^10.0.1, minimatch@npm:^10.1.1, minimatch@npm:^9.0.3 || ^10.0.1":
version: 10.1.1
resolution: "minimatch@npm:10.1.1"
"minimatch@npm:^10.0.1, minimatch@npm:^10.1.2, minimatch@npm:^9.0.3 || ^10.0.1":
version: 10.1.2
resolution: "minimatch@npm:10.1.2"
dependencies:
"@isaacs/brace-expansion": "npm:^5.0.0"
checksum: 10c0/c85d44821c71973d636091fddbfbffe62370f5ee3caf0241c5b60c18cd289e916200acb2361b7e987558cd06896d153e25d505db9fc1e43e6b4b6752e2702902
"@isaacs/brace-expansion": "npm:^5.0.1"
checksum: 10c0/0cccef3622201703de6ecf9d772c0be1d5513dcc038ed9feb866c20cf798243e678ac35605dac3f1a054650c28037486713fe9e9a34b184b9097959114daf086
languageName: node
linkType: hard

Expand Down