Skip to content

Next.js: Fix Link component override in appDirectory configuration#31251

Merged
valentinpalkovic merged 12 commits into
storybookjs:nextfrom
yatishgoel:fix/nextjs15-link-component-override
Feb 11, 2026
Merged

Next.js: Fix Link component override in appDirectory configuration#31251
valentinpalkovic merged 12 commits into
storybookjs:nextfrom
yatishgoel:fix/nextjs15-link-component-override

Conversation

@yatishgoel
Copy link
Copy Markdown
Contributor

@yatishgoel yatishgoel commented Apr 26, 2025

Closes #30390

What I did

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=<PR_NUMBER>

Greptile Summary

Added mock implementation and webpack alias mappings for Next.js Link component to fix navigation issues in Next.js 15 with appDirectory configuration.

  • Added code/frameworks/nextjs/src/export-mocks/link/index.tsx with mock Link component implementation
  • Added Link component mappings in code/frameworks/nextjs/src/export-mocks/webpack.ts for proper aliasing
  • Updated code/frameworks/nextjs/package.json exports to include new Link mock component
  • Added support for Next.js 15.0.0 as peer dependency

The changes ensure proper Link component behavior in stories by preventing navigation to non-existent pages when using Next.js 15 in appDirectory mode.

Summary by CodeRabbit

  • New Features
    • Added a mock for the Next.js Link component, enabling improved Storybook testing support for Next.js projects.
    • Introduced new compatibility utilities for segment and redirect status code handling.
    • Extended public API exports for easier access to mocking and compatibility modules.

✏️ Tip: You can customize this high-level summary in your review settings.

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

LGTM

3 file(s) reviewed, no comment(s)
Edit PR Review Bot Settings | Greptile

@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Apr 26, 2025

View your CI Pipeline Execution ↗ for commit f9534d8.

Command Status Duration Result
nx run-many -t build --parallel=3 ✅ Succeeded 1m 15s View ↗

☁️ Nx Cloud last updated this comment at 2025-07-02 08:26:31 UTC

@valentinpalkovic valentinpalkovic added the patch:yes Bugfix & documentation PR that need to be picked to main branch label Jun 23, 2025
@valentinpalkovic
Copy link
Copy Markdown
Contributor

Hi @yatishgoel,

Thank you for opening the PR!

Could you take a look at the build pipeline? Unfortunately, it is failing.

@github-actions github-actions Bot added the Stale label Jul 18, 2025
@valentinpalkovic
Copy link
Copy Markdown
Contributor

Superseded by #32131

@ryami333
Copy link
Copy Markdown

ryami333 commented Dec 3, 2025

@valentinpalkovic – seeing as #32131 did not actually address the issue, should this PR be re-evaluated?

@valentinpalkovic valentinpalkovic changed the title fix: Next.js 15 Link component override in appDirectory configuration Next.js: Fix Link component override in appDirectory configuration Dec 3, 2025
@valentinpalkovic
Copy link
Copy Markdown
Contributor

@yatishgoel Could you merge next into your PR and resolve the merge conflicts?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 4, 2025

📝 Walkthrough

Walkthrough

This change expands the Next.js Storybook integration's public API by adding a new mock export for next/link and two compatibility modules. The package.json is updated with corresponding export paths and bundler entries, and webpack aliases are configured to resolve the new mock mappings.

Changes

Cohort / File(s) Summary
Package Configuration
code/frameworks/nextjs/package.json
Adds three new public exports: ./export-mocks/link/index.tsx, ./compatibility/segment.compat.ts, and ./compatibility/redirect-status-code.compat.ts. Includes bundler entry for the link mock.
Link Mock Export
code/frameworks/nextjs/src/export-mocks/link/index.tsx
New file introducing a mocked Link component via Storybook's fn() utility, named 'next/link::Link', exported both as default and named export.
Webpack Configuration
code/frameworks/nextjs/src/export-mocks/webpack.ts
Adds two new alias mappings: 'next/link' and '@storybook/nextjs/link.mock' both resolving to the new link mock export.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

  • Review package.json exports for correct paths and consistency with implementation
  • Verify mock function naming and export structure in the new link module
  • Confirm webpack alias mappings correctly resolve to the new mock location
✨ Finishing touches
  • 📝 Generate docstrings

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
code/frameworks/nextjs/package.json (1)

199-222: Bundler entries for link mock and compat modules look correct; clarify export surface

The three new bundler entries

  • ./src/export-mocks/link/index.tsx
  • ./src/compatibility/segment.compat.ts
  • ./src/compatibility/redirect-status-code.compat.ts

line up with the new webpack aliases and compatibility helpers and ensure those files are built into dist. That’s what you need so /dist/export-mocks/link/index actually exists for the alias in export-mocks/webpack.ts.

One thing to double-check:

  • If segment.compat / redirect-status-code.compat and the link mock are meant to be publicly importable (beyond internal use), they should also have matching exports (and ideally typesVersions) entries, following the existing pattern used for draft-mode.compat and the other *.mock modules.
  • If they’re purely internal helpers, the current bundler-only entries are fine; just keep their usage via internal relative imports to avoid surprising consumers.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a60c55c and f9534d8.

📒 Files selected for processing (3)
  • code/frameworks/nextjs/package.json (1 hunks)
  • code/frameworks/nextjs/src/export-mocks/link/index.tsx (1 hunks)
  • code/frameworks/nextjs/src/export-mocks/webpack.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use ESLint and Prettier configurations that are enforced in the codebase

Files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/src/export-mocks/webpack.ts
  • code/frameworks/nextjs/package.json
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Enable TypeScript strict mode

Files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/src/export-mocks/webpack.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{ts,tsx,js,jsx,mjs}: Use server-side logger from 'storybook/internal/node-logger' for Node.js code
Use client-side logger from 'storybook/internal/client-logger' for browser code
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/src/export-mocks/webpack.ts
code/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions that need to be tested from their modules

Files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/src/export-mocks/webpack.ts
code/**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier with --write flag to format code before committing
Run ESLint with yarn lint:js:cmd to check for linting issues and fix errors before committing

Files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/src/export-mocks/webpack.ts
  • code/frameworks/nextjs/package.json
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Applies to code/**/*.{test,spec}.{ts,tsx,js,jsx} : Mock external dependencies using vi.mock() for file system, loggers, and other external dependencies in tests
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required dependencies that the test subject uses
Learnt from: mrginglymus
Repo: storybookjs/storybook PR: 32556
File: code/core/package.json:309-313
Timestamp: 2025-09-29T13:20:23.346Z
Learning: The `fast-printf` dependency in Storybook's core package is bundled into the final distribution during the build process, so it should remain in devDependencies rather than being moved to dependencies, following the same pattern as other bundled dependencies like `open`.
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Follow existing patterns and conventions in the Storybook codebase
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/tooltip/WithTooltip.tsx:54-96
Timestamp: 2025-11-05T09:37:25.920Z
Learning: Repo: storybookjs/storybook — In code/core/src/components/components/tooltip/WithTooltip.tsx, the legacy WithTooltip implementation is intentionally reintroduced for backward compatibility and is deprecated; maintainers (per Sidnioulz) do not want maintenance or improvements on it. Prefer WithTooltipNew/Popover; avoid suggesting changes to WithTooltip.* going forward.
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32507
File: code/core/src/manager/globals/globals-module-info.ts:25-33
Timestamp: 2025-09-24T09:39:39.233Z
Learning: In Storybook, storybook/actions/decorator is a preview-only entrypoint and should not be included in manager globals configuration. The duplicatedKeys array in code/core/src/manager/globals/globals-module-info.ts is specifically for manager-side externalization, not preview entrypoints.
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors in Vitest tests
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies in Vitest tests
📚 Learning: 2025-11-28T14:50:24.889Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Applies to code/**/*.{test,spec}.{ts,tsx,js,jsx} : Mock external dependencies using vi.mock() for file system, loggers, and other external dependencies in tests

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/src/export-mocks/webpack.ts
  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Group related mocks together in Vitest tests

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-28T14:50:24.889Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Applies to code/**/*.{ts,tsx,js,jsx} : Export functions that need to be tested from their modules

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should match the expected return type of the original function

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required dependencies that the test subject uses

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/src/export-mocks/webpack.ts
  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors in Vitest tests

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases in Vitest tests

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-05T09:38:47.712Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/link/index.tsx
  • code/frameworks/nextjs/package.json
📚 Learning: 2025-10-01T15:24:01.060Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/webpack.ts
  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies in Vitest tests

Applied to files:

  • code/frameworks/nextjs/src/export-mocks/webpack.ts
  • code/frameworks/nextjs/package.json
📚 Learning: 2025-09-24T09:39:39.233Z
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32507
File: code/core/src/manager/globals/globals-module-info.ts:25-33
Timestamp: 2025-09-24T09:39:39.233Z
Learning: In Storybook, storybook/actions/decorator is a preview-only entrypoint and should not be included in manager globals configuration. The duplicatedKeys array in code/core/src/manager/globals/globals-module-info.ts is specifically for manager-side externalization, not preview entrypoints.

Applied to files:

  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid direct function mocking without `vi.mocked()` in Vitest tests

Applied to files:

  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required properties and methods that the test subject uses in Vitest tests

Applied to files:

  • code/frameworks/nextjs/package.json
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Keep mock implementations simple and focused in Vitest tests

Applied to files:

  • code/frameworks/nextjs/package.json
🧬 Code graph analysis (1)
code/frameworks/nextjs/src/export-mocks/link/index.tsx (1)
code/core/src/test/spy.ts (1)
  • fn (36-39)
🔇 Additional comments (1)
code/frameworks/nextjs/src/export-mocks/webpack.ts (1)

7-19: Link aliases match existing mock pattern

The new aliases for 'next/link' and '@storybook/nextjs/link.mock' are consistent with the existing cache/headers/navigation/router mappings and correctly point at the new dist module. Just make sure the built artifact continues to live at /dist/export-mocks/link/index.{mjs,js} so these stay in sync with the bundler output.

Comment on lines +1 to +13
import React from 'react';

import { fn } from 'storybook/test';

// Mock implementation for next/link
const mockLink = fn().mockName('next/link::Link');

const linkExports = {
default: mockLink,
};

export default linkExports.default;
export { mockLink as Link };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Let me verify the React import concern and linkExports object pattern one more time
cat << 'EOF' > /tmp/verify.ts
// From the snippet in review comment:
import React from 'react';
import { fn } from 'storybook/test';

const mockLink = fn().mockName('next/link::Link');
const linkExports = { default: mockLink };

export default linkExports.default;
export { mockLink as Link };

// Analysis:
// 1. React import: used? No - verified
// 2. linkExports: necessary? No - it just wraps mockLink, verified
// 3. fn() behavior: is it a function that returns undefined?
//    - fn() is Vitest spy, when called returns undefined by default
//    - When used as React component like <Link />, React would not render it properly
EOF
cat /tmp/verify.ts

Repository: storybookjs/storybook

Length of output: 186


Remove unused React import and simplify mock export structure

The React import is unused (no JSX or React APIs called), and the linkExports object unnecessarily wraps mockLink. Both can be removed by exporting mockLink directly:

-import React from 'react';
-
-import { fn } from 'storybook/test';
+import { fn } from 'storybook/test';

 // Mock implementation for next/link
 const mockLink = fn().mockName('next/link::Link');
-
-const linkExports = {
-  default: mockLink,
-};
-
-export default linkExports.default;
+export default mockLink;
 export { mockLink as Link };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import React from 'react';
import { fn } from 'storybook/test';
// Mock implementation for next/link
const mockLink = fn().mockName('next/link::Link');
const linkExports = {
default: mockLink,
};
export default linkExports.default;
export { mockLink as Link };
import { fn } from 'storybook/test';
// Mock implementation for next/link
const mockLink = fn().mockName('next/link::Link');
export default mockLink;
export { mockLink as Link };
🤖 Prompt for AI Agents
In code/frameworks/nextjs/src/export-mocks/link/index.tsx around lines 1 to 13,
remove the unused "import React from 'react';" and eliminate the unnecessary
linkExports object by exporting mockLink directly as the default and named
export; specifically delete the React import and replace the linkExports-based
default export with a direct default export of mockLink while keeping the named
export "Link" mapped to mockLink.

@github-actions github-actions Bot added the Stale label Dec 16, 2025
@ndelangen ndelangen added patch:yes Bugfix & documentation PR that need to be picked to main branch and removed patch:yes Bugfix & documentation PR that need to be picked to main branch labels Jan 26, 2026
@github-actions github-actions Bot removed the Stale label Jan 30, 2026
@yatishgoel yatishgoel force-pushed the fix/nextjs15-link-component-override branch from f9534d8 to b3e8ea8 Compare January 30, 2026 13:28
@valentinpalkovic valentinpalkovic moved this to Empathy Queue (prioritized) in Core Team Projects Jan 30, 2026
@yatishgoel
Copy link
Copy Markdown
Contributor Author

Thanks for prioritizing this! Let me know if anything else is needed.

@valentinpalkovic
Copy link
Copy Markdown
Contributor

Hi @yatishgoel

Thank you for resolving the merge conflicts. Could you please take a look into the build errors for next-js-latest--webpack---typescript---build?

@storybook-app-bot
Copy link
Copy Markdown

storybook-app-bot Bot commented Feb 5, 2026

Package Benchmarks

Commit: 27628cd, ran on 9 February 2026 at 14:48:34 UTC

No significant changes detected, all good. 👏

yatishgoel and others added 2 commits February 7, 2026 12:45
@valentinpalkovic
Copy link
Copy Markdown
Contributor

Hi @yatishgoel

the nextjs Link story is broken. Empty links are rendered.


IMG_1205

@yatishgoel
Copy link
Copy Markdown
Contributor Author

yatishgoel commented Feb 7, 2026

Hi @valentinpalkovic,

The empty links are happening because the mock uses fn() as the default export. fn() without an implementation returns undefined when React calls it as a component, so nothing renders.

I'm planning to replace it with a React.forwardRef component that renders a plain <a> tag, stripping Next.js-specific props like replace, scroll, prefetch. This is similar to how the image mock works, real DOM rendering without the Next.js navigation layer.

One tradeoff is that the mock would no longer use fn(), so users won't be able to track or assert Link interactions in their tests. Would this approach work, or would you prefer a different direction?

@valentinpalkovic
Copy link
Copy Markdown
Contributor

valentinpalkovic commented Feb 9, 2026

Can't we just create an a element with an onClick handler, which suppresses the navigation (e.preventDefault) and also calls `fn() inside the ' onClick ' handler so that link clicks are logged to the action panel?

@valentinpalkovic valentinpalkovic moved this from Empathy Queue (prioritized) to On Hold in Core Team Projects Feb 9, 2026
yatishgoel and others added 3 commits February 9, 2026 18:52
…d improve click handling. The MockLink component now constructs href strings from object types and prevents default link behavior while invoking the mock action.
… to ensure proper functionality of the mock action.
@valentinpalkovic valentinpalkovic merged commit 40e556a into storybookjs:next Feb 11, 2026
114 checks passed
@github-project-automation github-project-automation Bot moved this from On Hold to Done in Core Team Projects Feb 11, 2026
valentinpalkovic added a commit that referenced this pull request Feb 17, 2026
…-override

Next.js: Fix Link component override in appDirectory configuration

(cherry picked from commit 40e556a)
@github-actions github-actions Bot added the patch:done Patch/release PRs already cherry-picked to main/release branch label Feb 17, 2026
@lencioni
Copy link
Copy Markdown

I believe this may not work correctly for Next.js links with legacyBehavior. I opened an issue #33861

Comment on lines +35 to +39
return (
<a ref={ref} href={hrefString} onClick={handleClick} {...rest}>
{children}
</a>
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think if legacyBehavior is true, this should pass the props onto the child instead of rendering an <a> itself. #33861

See here: https://github.com/vercel/next.js/blob/b0595b17ae331a2e1cccff35da8d093f0636c8e1/packages/next/src/client/link.tsx#L680-L690

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug ci:normal needs triage nextjs patch:done Patch/release PRs already cherry-picked to main/release branch patch:yes Bugfix & documentation PR that need to be picked to main branch

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Bug]: Next.js Link component causes navigation to a non-existent page in stories

5 participants