Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
154 commits
Select commit Hold shift + click to select a range
054c0cc
Feature: Add @storybook/tanstack-react framework
valentinpalkovic Feb 3, 2026
433af94
Enhancement: Implement custom Vite plugin filtering for TanStack Star…
valentinpalkovic Feb 4, 2026
a920a3c
Enhancement: Add routing capabilities to @storybook/tanstack-react fr…
valentinpalkovic Feb 4, 2026
c7c5e37
Refactor: Simplify FrameworkOptions and TanStackRouterOptions types b…
valentinpalkovic Feb 4, 2026
1e1b71a
Fix types
valentinpalkovic Feb 4, 2026
13bbb6d
Refactor: Remove server configuration from viteFinal in preset.ts to …
valentinpalkovic Feb 4, 2026
096b0db
Fix types
valentinpalkovic Feb 4, 2026
4945a18
T1: Framework Core (preview.tsx, types.ts)
valentinpalkovic Feb 19, 2026
48c7203
T2: Helpers & Exports (4 files)
valentinpalkovic Feb 19, 2026
91f1243
T3: Template Stories (6 files)
valentinpalkovic Feb 19, 2026
4ea368e
Linting
valentinpalkovic Feb 19, 2026
b33f415
Fix TypeScript formatter to use ESLint instead of Prettier
valentinpalkovic Feb 19, 2026
24f5a02
Add basic stories
valentinpalkovic Feb 25, 2026
d1b1d7b
feat: implement server function stubs and integration tests
valentinpalkovic Feb 27, 2026
faf8abb
Remove router experiments
valentinpalkovic Mar 6, 2026
640d43f
Remove tanstack template stories
valentinpalkovic Mar 6, 2026
f7a79aa
Cleanup Readme
valentinpalkovic Mar 6, 2026
2f4955f
Merge remote-tracking branch 'origin/next' into julien/tanstack
huang-julien Mar 9, 2026
0570f3e
Merge branch 'next' into julien/tanstack
huang-julien Mar 19, 2026
0f9d59a
Merge branch 'next' into julien/tanstack
huang-julien Mar 23, 2026
4bc05e8
Merge branch 'next' into julien/tanstack
huang-julien Mar 25, 2026
57c6c53
feat: initial tanstack router mock
huang-julien Mar 26, 2026
4f31ee9
fix: block navigation in memoryHistory
huang-julien Mar 27, 2026
b8b9b69
feat: expose router via decorator file
huang-julien Mar 27, 2026
a70afac
build: export getRouter from index and add missing decorator
huang-julien Mar 27, 2026
cdd0672
feat: mock tanstack query
huang-julien Mar 27, 2026
0d58ae8
refactor: partial router cleanup
huang-julien Mar 30, 2026
8fdc056
feat: add additionnal mocks and fix router implementation
huang-julien Mar 30, 2026
6eb8692
Build: update build config
huang-julien Mar 30, 2026
c491732
fix: types
huang-julien Mar 30, 2026
9669b76
chore: lockfile and exports json
huang-julien Mar 30, 2026
25cc51e
chore: update template
huang-julien Mar 31, 2026
1a06c5c
Merge remote-tracking branch 'origin/next' into julien/tanstack
huang-julien Mar 31, 2026
d97607b
feat: provide better types
huang-julien Mar 31, 2026
ef7ab22
feat: provide helper
huang-julien Apr 1, 2026
d5347df
feat: improve createStoryRoute API
huang-julien Apr 1, 2026
abf31b4
fix(tanstack-react): update the correct component in decorator
huang-julien Apr 1, 2026
cce1fe3
feat(tanstack-react): update templates
huang-julien Apr 1, 2026
e1ccd75
refactor: improve type
huang-julien Apr 1, 2026
96e43b6
fix: make route available at TanstackTypes level for future library i…
huang-julien Apr 1, 2026
58d9eb5
cleanup: remove loaders
huang-julien Apr 1, 2026
5b4bb92
feat: improve type inference from CSF factory
huang-julien Apr 2, 2026
bc4cb86
feat: add params and query parameters to route
huang-julien Apr 3, 2026
b9fb69a
fix: mocks
huang-julien Apr 3, 2026
cdba65a
fix: use history replace instead of push
huang-julien Apr 3, 2026
5a398e1
refactor: remove the whole query integration (implement later)
huang-julien Apr 3, 2026
af06aaf
fix(export-mocks): fix Navigate mock
huang-julien Apr 3, 2026
cf5770f
feat: use loader to allow Route as component
huang-julien Apr 3, 2026
4b04eaa
chore: cleanup
huang-julien Apr 3, 2026
732419f
feat: update CLI templates
huang-julien Apr 7, 2026
bcee564
feat: allow to use args to customize route behavior
huang-julien Apr 7, 2026
259b8f8
fix: correctly infger story parameters from MEta type
huang-julien Apr 8, 2026
191c419
fix: correctly infer types
huang-julien Apr 8, 2026
cfdcd53
feat(tanstack): update template stories
huang-julien Apr 9, 2026
a16ebc5
docs: draft ocumentation
huang-julien Apr 9, 2026
071acda
fix types
huang-julien Apr 10, 2026
f204b4d
chore: cleanup sandbox-templates
huang-julien Apr 10, 2026
8bf4a1b
chore : cleanups
huang-julien Apr 10, 2026
d52fbab
chore: fix lockfile
huang-julien Apr 10, 2026
358607e
chore: add todo verification
huang-julien Apr 10, 2026
09459ea
Merge branch 'next' into julien/tanstack
huang-julien Apr 10, 2026
3672a44
chore: cleanup unused args
huang-julien Apr 10, 2026
d55d757
Merge branch 'julien/tanstack' of https://github.com/storybookjs/stor…
huang-julien Apr 10, 2026
f5a2924
Merge branch 'next' into julien/tanstack
huang-julien Apr 13, 2026
53a142e
Merge branch 'next' into julien/tanstack
huang-julien Apr 13, 2026
effaf69
fix: remove rsc from plugin list
huang-julien Apr 14, 2026
854b0ab
fix(tanstack-react): extract component from route from context in loader
huang-julien Apr 14, 2026
bf1e9a7
fix(tanstack-react): mock additionnal tanstack react server lib
huang-julien Apr 14, 2026
d523dcb
fix(tanstack-react): clone route and improve override
huang-julien Apr 15, 2026
6693517
fix(tanstack-react): clone route and improve override
huang-julien Apr 15, 2026
ff2ee1d
chore update lock
huang-julien Apr 15, 2026
65d03c1
fix update types and docs
huang-julien Apr 15, 2026
da30715
feat(tanstack-react): remove and mock out server side code
huang-julien Apr 16, 2026
a66779c
chore: cleanup
huang-julien Apr 16, 2026
4e0bdce
fix(tanstack-react): context provider
huang-julien Apr 16, 2026
6a715b5
fix(tanstack-react): route overrides
huang-julien Apr 17, 2026
d0b5917
fix: type extraction
huang-julien Apr 17, 2026
75c370a
ci: add tanstack-react to sandbox template
huang-julien Apr 17, 2026
ff757e2
chore: update template story template
huang-julien Apr 17, 2026
60dc912
update documentation
huang-julien Apr 17, 2026
a2f6b39
docs(tanstack-react): remove nodejs deps optimization
huang-julien Apr 17, 2026
83289dd
fix: improve types for route overrides
huang-julien Apr 17, 2026
ff12e04
fix: type
huang-julien Apr 17, 2026
b9b5f83
docs: update docs and move code into codesnippets
huang-julien Apr 17, 2026
9da4095
Merge branch 'next' into julien/tanstack
huang-julien Apr 17, 2026
516c044
docs: split FAQ
huang-julien Apr 17, 2026
ad3bcf9
build: fix import
huang-julien Apr 17, 2026
119d0de
Merge branch 'julien/tanstack' of https://github.com/storybookjs/stor…
huang-julien Apr 17, 2026
3ab9dc6
chore: remove docs
huang-julien Apr 23, 2026
2055b42
ci: uncomment sandbox generation
huang-julien Apr 23, 2026
86937ea
Revert "ci: uncomment sandbox generation"
huang-julien Apr 23, 2026
3d85527
fix: feedback
huang-julien Apr 24, 2026
c6ada2b
fix(create-sb): fix tanstack deps detection
huang-julien Apr 27, 2026
005e60c
Update code/frameworks/tanstack-react/src/export-mocks/react-router.ts
huang-julien Apr 27, 2026
4f5324f
Update code/frameworks/tanstack-react/src/export-mocks/react-router.ts
huang-julien Apr 27, 2026
977d10b
Update code/frameworks/tanstack-react/src/export-mocks/react-router.ts
huang-julien Apr 27, 2026
9a3b958
Merge branch 'next' into julien/tanstack
huang-julien Apr 27, 2026
8611d0b
fix: improve plugin ignore list
huang-julien Apr 27, 2026
dcf02d1
revert: revert sandbox-part changes
huang-julien Apr 27, 2026
0286697
Merge branch 'next' into julien/tanstack
huang-julien Apr 27, 2026
e7426ce
build: update tanstack sandboxes to start / routerSPA
huang-julien Apr 27, 2026
7b239a4
Merge branch 'next' into julien/tanstack
huang-julien Apr 27, 2026
bc3639c
fix: sandbox names
huang-julien Apr 27, 2026
8f26078
Merge branch 'julien/tanstack' of https://github.com/storybookjs/stor…
huang-julien Apr 27, 2026
35fefa3
Merge branch 'next' into julien/tanstack
huang-julien Apr 27, 2026
0faaf9a
ci: add missing extra deps for tanstack
huang-julien Apr 27, 2026
2ea9d5c
Merge branch 'julien/tanstack' of https://github.com/storybookjs/stor…
huang-julien Apr 27, 2026
e110fa8
fix(tanstack§react): add default error component to show error
huang-julien Apr 28, 2026
58d3dba
ci(tanstack-react): fix sandbox generation
huang-julien Apr 28, 2026
f544bfc
refactor(tanstack-react): rename ProjectType.TANSTACK
huang-julien Apr 28, 2026
b5387e9
Merge branch 'next' into julien/tanstack
huang-julien Apr 28, 2026
d2f4ded
fix: strip out server options in routes
huang-julien Apr 29, 2026
9d778f4
fix: stub server only files
huang-julien Apr 29, 2026
5bd3eaf
feat(tanstack-react): allow routeTree
huang-julien Apr 29, 2026
71bff3c
fix(tanstack-react): fix Route only stories
huang-julien Apr 29, 2026
2c8718d
chore: remove unnecessary mocks
huang-julien Apr 29, 2026
d0e6818
Merge branch 'julien/tanstack' of https://github.com/storybookjs/stor…
huang-julien Apr 29, 2026
b08cb0b
fix: improve server side code removal
huang-julien Apr 29, 2026
9823870
fix: type constraint, tree duplication and memoize render
huang-julien Apr 30, 2026
26e27f3
fix: unmemoize router creation and fix types
huang-julien Apr 30, 2026
14e0eb8
fix: corectly duplicate tree for Route instances
huang-julien Apr 30, 2026
da49192
fix: don't duplicate route when users provides routeOptions
huang-julien Apr 30, 2026
754eb7b
Merge remote-tracking branch 'origin/next' into julien/tanstack
huang-julien Apr 30, 2026
4e037f3
chore: update package json
huang-julien Apr 30, 2026
353385c
fix: fix react context issues in tests
huang-julien Apr 30, 2026
9392ab0
chore: format
huang-julien Apr 30, 2026
b1c367d
fix: remove story memoization
huang-julien Apr 30, 2026
97906de
fix: memoize router
huang-julien Apr 30, 2026
9c9a141
fix: use react provider to provide story in react contextr
huang-julien Apr 30, 2026
4ff02bf
fix: decorator
huang-julien Apr 30, 2026
41577f8
fix: decorator order
huang-julien Apr 30, 2026
c4854a1
fix: exclude @storybook/react from optimizeDeps
huang-julien Apr 30, 2026
1416920
Merge remote-tracking branch 'origin/next' into julien/tanstack
huang-julien Apr 30, 2026
b3023c4
chore: code cleaning and add comments
huang-julien May 4, 2026
c381a10
fix: add devtools deps to optimize deps
huang-julien May 4, 2026
caf2e9d
chore: clean types
huang-julien May 4, 2026
03a176c
Merge remote-tracking branch 'origin/next' into julien/tanstack
huang-julien May 4, 2026
d268a96
chore: rename plugin
huang-julien May 4, 2026
8c9eb9f
refactor: simplify mocks
huang-julien May 4, 2026
5cbc922
chore: move stub plugin into dedicated file
huang-julien May 4, 2026
8b7c863
Update code/frameworks/tanstack-react/src/plugins/server-code-elimina…
huang-julien May 4, 2026
2d58254
Apply suggestions from code review
huang-julien May 4, 2026
40f8bbd
fix: babel changes
huang-julien May 4, 2026
b0b5af5
fix: type
huang-julien May 4, 2026
fa6e73f
chore: cleanup package.json
huang-julien May 4, 2026
5b44054
chore: use type augmentation
huang-julien May 4, 2026
989a95f
fix: coderabbitai fedddback
huang-julien May 4, 2026
c92bd95
refactor: use template string
huang-julien May 4, 2026
ec79572
chore: regen lockfile
huang-julien May 4, 2026
8edbea5
docs: update comment to guide users on documentation
huang-julien May 4, 2026
ed7615b
fix: make tanstack template similar to nextjs ones
huang-julien May 4, 2026
cea37cc
Merge branch 'next' into julien/tanstack
huang-julien May 4, 2026
976b1a7
refactor: remove start-server mock
huang-julien May 4, 2026
5909e3e
Merge remote-tracking branch 'origin/next' into julien/tanstack
huang-julien May 5, 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
1 change: 1 addition & 0 deletions code/core/src/cli/AddonVitestService.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export const SUPPORTED_FRAMEWORKS: readonly SupportedFramework[] = [
SupportedFramework.SVELTEKIT,
SupportedFramework.VUE3_VITE,
SupportedFramework.WEB_COMPONENTS_VITE,
SupportedFramework.TANSTACK_REACT,
];
1 change: 1 addition & 0 deletions code/core/src/cli/projectTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export enum ProjectType {
PREACT = 'preact',
QWIK = 'qwik',
REACT = 'react',
TANSTACK_REACT = 'tanstack_react',
REACT_NATIVE = 'react_native',
REACT_NATIVE_AND_RNW = 'react_native_and_rnw',
REACT_NATIVE_WEB = 'react_native_web',
Expand Down
2 changes: 2 additions & 0 deletions code/core/src/common/utils/framework.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const frameworkToRenderer: Record<
[SupportedFramework.SOLID]: SupportedRenderer.SOLID,
[SupportedFramework.SVELTE_VITE]: SupportedRenderer.SVELTE,
[SupportedFramework.SVELTEKIT]: SupportedRenderer.SVELTE,
[SupportedFramework.TANSTACK_REACT]: SupportedRenderer.REACT,
[SupportedFramework.VUE3_VITE]: SupportedRenderer.VUE3,
[SupportedFramework.WEB_COMPONENTS_VITE]: SupportedRenderer.WEB_COMPONENTS,
[SupportedFramework.REACT_RSBUILD]: SupportedRenderer.REACT,
Expand Down Expand Up @@ -52,6 +53,7 @@ export const frameworkToBuilder: Record<SupportedFramework, SupportedBuilder> =
[SupportedFramework.SERVER_WEBPACK5]: SupportedBuilder.WEBPACK5,
[SupportedFramework.SVELTE_VITE]: SupportedBuilder.VITE,
[SupportedFramework.SVELTEKIT]: SupportedBuilder.VITE,
[SupportedFramework.TANSTACK_REACT]: SupportedBuilder.VITE,
[SupportedFramework.VUE3_VITE]: SupportedBuilder.VITE,
[SupportedFramework.WEB_COMPONENTS_VITE]: SupportedBuilder.VITE,
[SupportedFramework.QWIK]: SupportedBuilder.VITE,
Expand Down
1 change: 1 addition & 0 deletions code/core/src/common/utils/get-storybook-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const frameworkPackages: Record<string, SupportedFramework> = {
'@storybook/nextjs-vite': SupportedFramework.NEXTJS_VITE,
'@storybook/react-native-web-vite': SupportedFramework.REACT_NATIVE_WEB_VITE,
'@storybook/web-components-vite': SupportedFramework.WEB_COMPONENTS_VITE,
'@storybook/tanstack-react': SupportedFramework.TANSTACK_REACT,
// community (outside of monorepo)
'storybook-framework-qwik': SupportedFramework.QWIK,
'storybook-solidjs-vite': SupportedFramework.SOLID,
Expand Down
1 change: 1 addition & 0 deletions code/core/src/common/versions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default {
'@storybook/preset-server-webpack': '10.4.0-alpha.16',
'@storybook/html': '10.4.0-alpha.16',
'@storybook/preact': '10.4.0-alpha.16',
'@storybook/tanstack-react': '10.4.0-alpha.16',
'@storybook/react': '10.4.0-alpha.16',
'@storybook/server': '10.4.0-alpha.16',
'@storybook/svelte': '10.4.0-alpha.16',
Expand Down
1 change: 1 addition & 0 deletions code/core/src/types/modules/frameworks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export enum SupportedFramework {
SERVER_WEBPACK5 = 'server-webpack5',
SVELTE_VITE = 'svelte-vite',
SVELTEKIT = 'sveltekit',
TANSTACK_REACT = 'tanstack-react',
VUE3_VITE = 'vue3-vite',
WEB_COMPONENTS_VITE = 'web-components-vite',
// COMMUNITY
Expand Down
7 changes: 7 additions & 0 deletions code/frameworks/tanstack-react/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Storybook for TanStack (React + Vite)

Develop, document, and test UI components in isolation with built-in TanStack Router and TanStack Query support.

See [documentation](https://storybook.js.org/docs/get-started?ref=readme) for installation instructions, usage examples, APIs, and more.

Learn more about Storybook at [storybook.js.org](https://storybook.js.org/?ref=readme).
41 changes: 41 additions & 0 deletions code/frameworks/tanstack-react/build-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { BuildEntries } from '../../../scripts/build/utils/entry-utils.ts';

const config: BuildEntries = {
entries: {
browser: [
{
exportEntries: ['.'],
entryPoint: './src/index.ts',
},
{
exportEntries: ['./preview'],
entryPoint: './src/preview.tsx',
},
{
exportEntries: ['./react-router'],
entryPoint: './src/export-mocks/react-router.ts',
external: ['@tanstack/react-router'],
},
{
exportEntries: ['./start-storage-context'],
entryPoint: './src/export-mocks/start-storage-context.ts',
},
{
exportEntries: ['./start'],
entryPoint: './src/export-mocks/start.ts',
},
],
node: [
{
exportEntries: ['./preset'],
entryPoint: './src/preset.ts',
},
{
exportEntries: ['./node'],
entryPoint: './src/node/index.ts',
},
],
},
};

export default config;
112 changes: 112 additions & 0 deletions code/frameworks/tanstack-react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"name": "@storybook/tanstack-react",
"version": "10.4.0-alpha.16",
"description": "Storybook for TanStack (React, Vite): Router and Start ready Storybook framework",
"keywords": [
"storybook",
"storybook-framework",
"tanstack",
"tanstack-router",
"tanstack-start",
"react",
"vite",
"component",
"components"
],
"homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/tanstack-react",
"bugs": {
"url": "https://github.com/storybookjs/storybook/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/storybookjs/storybook.git",
"directory": "code/frameworks/tanstack-react"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/storybook"
},
"license": "MIT",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"code": "./src/index.ts",
"default": "./dist/index.js"
},
"./node": {
"types": "./dist/node/index.d.ts",
"code": "./src/node/index.ts",
"default": "./dist/node/index.js"
},
"./package.json": "./package.json",
"./preset": {
"types": "./dist/preset.d.ts",
"code": "./src/preset.ts",
"default": "./dist/preset.js"
},
"./preview": {
"types": "./dist/preview.d.ts",
"code": "./src/preview.tsx",
"default": "./dist/preview.js"
},
"./react-router": {
"types": "./dist/export-mocks/react-router.d.ts",
"code": "./src/export-mocks/react-router.ts",
"default": "./dist/export-mocks/react-router.js"
},
"./start": {
"types": "./dist/export-mocks/start.d.ts",
"code": "./src/export-mocks/start.ts",
"default": "./dist/export-mocks/start.js"
},
"./start-storage-context": {
"types": "./dist/export-mocks/start-storage-context.d.ts",
"code": "./src/export-mocks/start-storage-context.ts",
"default": "./dist/export-mocks/start-storage-context.js"
}
},
"files": [
"dist/**/*",
"template/**/*",
"README.md",
"*.js",
"*.d.ts",
"!src/**/*"
],
"dependencies": {
"@storybook/builder-vite": "workspace:*",
"@storybook/react": "workspace:*",
"@storybook/react-vite": "workspace:*"
},
"devDependencies": {
"@tanstack/react-router": "^1.168.10",
"@tanstack/react-start": "^1.167.16",
"@tanstack/router-core": "^1.168.9",
"@tanstack/start-client-core": "^1.167.9",
"@types/node": "^22.19.1",
"typescript": "^5.9.3",
"vite": "^7.0.4"
},
"peerDependencies": {
"@tanstack/react-router": "^1.168.10",
"@tanstack/react-start": "^1.167.16",
"@tanstack/router-core": "^1.168.9",
"@tanstack/start-client-core": "^1.167.9",
"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",
"storybook": "workspace:^",
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"@tanstack/react-start": {
"optional": true
},
"@tanstack/start-client-core": {
"optional": true
}
},
"publishConfig": {
"access": "public"
}
}
10 changes: 10 additions & 0 deletions code/frameworks/tanstack-react/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "tanstack-react",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"targets": {
"compile": {},
"check": {}
},
"tags": ["library"]
}
99 changes: 99 additions & 0 deletions code/frameworks/tanstack-react/src/export-mocks/react-router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { createRoute } from '@tanstack/react-router';
export * from '@tanstack/react-router';

import { fn } from 'storybook/test';
import React from 'react';
import { useEffect } from 'storybook/internal/preview-api';

import {
useNavigate as _useNavigate,
useRouter as _useRouter,
useBlocker as _useBlocker,
useMatch as _useMatch,
useSearch as _useSearch,
useParams as _useParams,
useLocation as _useLocation,
useRouterState as _useRouterState,
useMatchRoute as _useMatchRoute,
useLoaderData as _useLoaderData,
useLoaderDeps as _useLoaderDeps,
useRouteContext as _useRouteContext,
useMatches as _useMatches,
useParentMatches as _useParentMatches,
useChildMatches as _useChildMatches,
useCanGoBack as _useCanGoBack,
useLinkProps as _useLinkProps,
} from '@tanstack/react-router';
import type { Navigate as _Navigate } from '@tanstack/react-router';
import { onNavigate } from './spies.ts';

// Mock navigation hooks — backed by real implementations so they work in stories
export const useNavigate = fn(_useNavigate).mockName('@tanstack/react-router::useNavigate');
export const useRouter = fn(_useRouter).mockName('@tanstack/react-router::useRouter');
export const useBlocker = fn(_useBlocker).mockName('@tanstack/react-router::useBlocker');
export const useSearch = fn(_useSearch).mockName('@tanstack/react-router::useSearch');
export const useParams = fn(_useParams).mockName('@tanstack/react-router::useParams');
export const useLocation = fn(_useLocation).mockName('@tanstack/react-router::useLocation');
export const useRouterState = fn(_useRouterState).mockName(
'@tanstack/react-router::useRouterState'
);
export const useLoaderData = fn(_useLoaderData).mockName('@tanstack/react-router::useLoaderData');
export const useLoaderDeps = fn(_useLoaderDeps).mockName('@tanstack/react-router::useLoaderDeps');
export const useRouteContext = fn(_useRouteContext).mockName(
'@tanstack/react-router::useRouteContext'
);
export const useCanGoBack = fn(_useCanGoBack).mockName('@tanstack/react-router::useCanGoBack');
export const useLinkProps = fn(_useLinkProps).mockName('@tanstack/react-router::useLinkProps');

export const Outlet = () => null;

export const Navigate: typeof _Navigate = ({ to, href }) => {
useEffect(() => {
onNavigate({ to: (to as string) || href });
}, [to, href]);

return null;
};
Comment thread
huang-julien marked this conversation as resolved.

export const Link = ({
to,
children,
...props
}: {
to: string;
children?: React.ReactNode;
[key: string]: unknown;
}) => {
const location = useLocation();
return React.createElement(
'a',
{
href: to,
onClick: (e: React.MouseEvent) => {
e.preventDefault();
onNavigate({ to, from: location.href });
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
...props,
},
children
);
};

/**
* Override createFileRoute from tanstack react router
* because the org `createFileRoute` doesn't set the path in the Route
*/
Comment thread
huang-julien marked this conversation as resolved.
export function createFileRoute(path: string) {
return (options: any) => {
return createRoute({
path,
...options,
isRoot: false,
}).update({
id: path,
path: path,
fullPath: path,
// any because tanstack router does that
} as any);
};
}
10 changes: 10 additions & 0 deletions code/frameworks/tanstack-react/src/export-mocks/spies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { fn } from 'storybook/test';

export type NavigationEvent = { to?: string; from?: string };

/**
* Spy called whenever navigation is attempted (Link click, useNavigate, etc.).
* Navigation is blocked — the story stays on screen — but the spy records
* `{ to, from }` so play functions can assert on it.
*/
export const onNavigate = fn<(event: NavigationEvent) => void>().mockName('navigate');
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { StartStorageContext } from '@tanstack/start-storage-context';

const START_CONTEXT_SYMBOL = Symbol.for('storybook.tanstack-react.start-storage-context');

type BrowserStartGlobals = typeof globalThis & {
__TSR_ROUTER__?: unknown;
__TSS_START_OPTIONS__?: unknown;
[START_CONTEXT_SYMBOL]?: StartStorageContext;
};

const browserGlobals = globalThis as BrowserStartGlobals;

function createFallbackStartContext(): StartStorageContext | undefined {
if (
browserGlobals.__TSR_ROUTER__ === undefined &&
browserGlobals.__TSS_START_OPTIONS__ === undefined
) {
return undefined;
}

return {
getRouter: () => browserGlobals.__TSR_ROUTER__ as never,
request: new Request('http://localhost/'),
startOptions: browserGlobals.__TSS_START_OPTIONS__,
contextAfterGlobalMiddlewares: undefined,
executedRequestMiddlewares: new Set(),
};
}

export async function runWithStartContext<T>(
context: StartStorageContext,
fn: () => T | Promise<T>
): Promise<T> {
const previousContext = browserGlobals[START_CONTEXT_SYMBOL];
browserGlobals[START_CONTEXT_SYMBOL] = context;

try {
return await fn();
} finally {
if (previousContext) {
browserGlobals[START_CONTEXT_SYMBOL] = previousContext;
} else {
delete browserGlobals[START_CONTEXT_SYMBOL];
}
}
}
Comment thread
huang-julien marked this conversation as resolved.

export function getStartContext<TThrow extends boolean = true>(opts?: {
throwIfNotFound?: TThrow;
}): TThrow extends false ? StartStorageContext | undefined : StartStorageContext {
const context = browserGlobals[START_CONTEXT_SYMBOL] ?? createFallbackStartContext();

if (!context && opts?.throwIfNotFound !== false) {
throw new Error('No Start context found in Storybook mock.');
}

return context as TThrow extends false ? StartStorageContext | undefined : StartStorageContext;
}

export type { StartStorageContext };
Loading
Loading