Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 0 additions & 6 deletions crates/next-core/src/next_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,6 @@ pub struct ExperimentalConfig {
trust_host_header: Option<bool>,

url_imports: Option<serde_json::Value>,
view_transition: Option<bool>,
/// This option is to enable running the Webpack build in a worker thread
/// (doesn't apply to Turbopack).
webpack_build_worker: Option<bool>,
Expand Down Expand Up @@ -1722,11 +1721,6 @@ impl NextConfig {
Vc::cell(self.experimental.taint.unwrap_or(false))
}

#[turbo_tasks::function]
pub fn enable_view_transition(&self) -> Vc<bool> {
Vc::cell(self.experimental.view_transition.unwrap_or(false))
}

#[turbo_tasks::function]
pub fn enable_cache_components(&self) -> Vc<bool> {
Vc::cell(self.experimental.cache_components.unwrap_or(false))
Expand Down
22 changes: 8 additions & 14 deletions crates/next-core/src/next_import_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,13 @@ pub async fn get_next_client_import_map(
match &ty {
ClientContextType::Pages { .. } => {}
ClientContextType::App { app_dir } => {
let react_flavor = if *next_config.enable_ppr().await?
|| *next_config.enable_taint().await?
|| *next_config.enable_view_transition().await?
{
"-experimental"
} else {
""
};
// Keep in sync with file:///./../../../packages/next/src/lib/needs-experimental-react.ts
let react_flavor =
if *next_config.enable_ppr().await? || *next_config.enable_taint().await? {
"-experimental"
} else {
""
};

import_map.insert_exact_alias(
rcstr!("react"),
Expand Down Expand Up @@ -833,12 +832,7 @@ async fn apply_vendored_react_aliases_server(
) -> Result<()> {
let ppr = *next_config.enable_ppr().await?;
let taint = *next_config.enable_taint().await?;
let view_transition = *next_config.enable_view_transition().await?;
let react_channel = if ppr || taint || view_transition {
"-experimental"
} else {
""
};
let react_channel = if ppr || taint { "-experimental" } else { "" };
let react_condition = if ty.should_use_react_server_condition() {
"server"
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Enable ViewTransition API from React in App Router
version: experimental
---

`viewTransition` is an experimental flag that enables the new experimental [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) in React. This API allows you to leverage the native View Transitions browser API to create seamless transitions between UI states.
`viewTransition` is an experimental flag that enables the new [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) in React. This API allows you to leverage the native View Transitions browser API to create seamless transitions between UI states.

To enable this feature, you need to set the `viewTransition` property to `true` in your `next.config.js` file.

Expand All @@ -19,19 +19,18 @@ const nextConfig = {
module.exports = nextConfig
```

> Important Notice: This feature is not developed or maintained by the Next.js team — it is an experimental API from the React team. It is still in **early stages** and **not recommended for production use**. The implementation is still being iterated on, and its behavior may change in future React releases.
> Enabling this feature requires understanding the experimental nature of the API. To fully grasp its behavior, refer to the [React pull request](https://github.com/facebook/react/pull/31975) and related discussions.
> Important Notice: The `<ViewTransition>` Component is already available in React's Canary release channel.
> `experimental.viewTransition` is only required to enable deeper integration with Next.js features e.g. automatically
> [adding Transition types](https://react.dev/reference/react/addTransitionType) for navigations. Next.js specific transition types are not implemented yet.

## Usage

Once enabled, you can import the `ViewTransition` component from React in your application:
You can import the [`<ViewTransition>` Component](https://react.dev/reference/react/ViewTransition) from React in your application:

```jsx
import { unstable_ViewTransition as ViewTransition } from 'react'
import { ViewTransition } from 'react'
```

However, documentation and examples are currently limited, and you will need to refer directly to React’s source code and discussions to understand how this works.

### Live Demo

Check out our [Next.js View Transition Demo](https://view-transition-example.vercel.app) to see this feature in action.
Expand Down
40 changes: 20 additions & 20 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@
"@types/jest": "29.5.5",
"@types/node": "20.17.6",
"@types/node-fetch": "2.6.1",
"@types/react": "19.1.16",
"@types/react-dom": "19.1.10",
"@types/react": "19.2.2",
"@types/react-dom": "19.2.1",
"@types/relay-runtime": "14.1.13",
"@types/string-hash": "1.1.1",
"@types/trusted-types": "2.0.3",
Expand Down Expand Up @@ -199,7 +199,7 @@
"eslint-plugin-jsdoc": "48.0.4",
"eslint-plugin-mdx": "3.1.5",
"eslint-plugin-react": "7.35.0",
"eslint-plugin-react-hooks": "0.0.0-experimental-c7862584-20251006",
"eslint-plugin-react-hooks": "0.0.0-experimental-a4eb2dfa-20251006",
"eslint-v8": "npm:eslint@^8.57.0",
"event-stream": "4.0.1",
"execa": "2.0.3",
Expand Down Expand Up @@ -259,16 +259,16 @@
"pretty-ms": "7.0.0",
"random-seed": "0.3.0",
"react": "19.0.0",
"react-builtin": "npm:[email protected]c7862584-20251006",
"react-builtin": "npm:[email protected]a4eb2dfa-20251006",
"react-dom": "19.0.0",
"react-dom-builtin": "npm:[email protected]c7862584-20251006",
"react-dom-experimental-builtin": "npm:[email protected]c7862584-20251006",
"react-experimental-builtin": "npm:[email protected]c7862584-20251006",
"react-is-builtin": "npm:[email protected]c7862584-20251006",
"react-server-dom-turbopack": "19.3.0-canary-c7862584-20251006",
"react-server-dom-turbopack-experimental": "npm:[email protected]c7862584-20251006",
"react-server-dom-webpack": "19.3.0-canary-c7862584-20251006",
"react-server-dom-webpack-experimental": "npm:[email protected]c7862584-20251006",
"react-dom-builtin": "npm:[email protected]a4eb2dfa-20251006",
"react-dom-experimental-builtin": "npm:[email protected]a4eb2dfa-20251006",
"react-experimental-builtin": "npm:[email protected]a4eb2dfa-20251006",
"react-is-builtin": "npm:[email protected]a4eb2dfa-20251006",
"react-server-dom-turbopack": "19.3.0-canary-a4eb2dfa-20251006",
"react-server-dom-turbopack-experimental": "npm:[email protected]a4eb2dfa-20251006",
"react-server-dom-webpack": "19.3.0-canary-a4eb2dfa-20251006",
"react-server-dom-webpack-experimental": "npm:[email protected]a4eb2dfa-20251006",
"react-ssr-prepass": "1.0.8",
"react-virtualized": "9.22.3",
"relay-compiler": "13.0.2",
Expand All @@ -278,8 +278,8 @@
"resolve-from": "5.0.0",
"sass": "1.54.0",
"satori": "0.15.2",
"scheduler-builtin": "npm:[email protected]c7862584-20251006",
"scheduler-experimental-builtin": "npm:[email protected]c7862584-20251006",
"scheduler-builtin": "npm:[email protected]a4eb2dfa-20251006",
"scheduler-experimental-builtin": "npm:[email protected]a4eb2dfa-20251006",
"seedrandom": "3.0.5",
"semver": "7.3.7",
"serve-handler": "6.1.6",
Expand Down Expand Up @@ -319,14 +319,14 @@
"@babel/parser": "7.27.0",
"@babel/types": "7.27.0",
"@babel/traverse": "7.27.0",
"@types/react": "19.1.16",
"@types/react-dom": "19.1.10",
"@types/react": "19.2.2",
"@types/react-dom": "19.2.1",
"@types/retry": "0.12.0",
"jest-snapshot": "30.0.0-alpha.6",
"react": "19.3.0-canary-c7862584-20251006",
"react-dom": "19.3.0-canary-c7862584-20251006",
"react-is": "19.3.0-canary-c7862584-20251006",
"scheduler": "0.28.0-canary-c7862584-20251006"
"react": "19.3.0-canary-a4eb2dfa-20251006",
"react-dom": "19.3.0-canary-a4eb2dfa-20251006",
"react-is": "19.3.0-canary-a4eb2dfa-20251006",
"scheduler": "0.28.0-canary-a4eb2dfa-20251006"
},
"packageExtensions": {
"[email protected]": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31872,12 +31872,10 @@
? parentHostFiber
: Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
};
FragmentInstance.prototype.experimental_scrollIntoView = function (
alignToTop
) {
FragmentInstance.prototype.scrollIntoView = function (alignToTop) {
if ("object" === typeof alignToTop)
throw Error(
"FragmentInstance.experimental_scrollIntoView() does not support scrollIntoViewOptions. Use the alignToTop boolean instead."
"FragmentInstance.scrollIntoView() does not support scrollIntoViewOptions. Use the alignToTop boolean instead."
);
var children = [];
traverseVisibleHostChildren(
Expand Down Expand Up @@ -32342,11 +32340,11 @@
};
(function () {
var isomorphicReactPackageVersion = React.version;
if ("19.3.0-experimental-c7862584-20251006" !== isomorphicReactPackageVersion)
if ("19.3.0-experimental-a4eb2dfa-20251006" !== isomorphicReactPackageVersion)
throw Error(
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
(isomorphicReactPackageVersion +
"\n - react-dom: 19.3.0-experimental-c7862584-20251006\nLearn more: https://react.dev/warnings/version-mismatch")
"\n - react-dom: 19.3.0-experimental-a4eb2dfa-20251006\nLearn more: https://react.dev/warnings/version-mismatch")
);
})();
("function" === typeof Map &&
Expand Down Expand Up @@ -32383,10 +32381,10 @@
!(function () {
var internals = {
bundleType: 1,
version: "19.3.0-experimental-c7862584-20251006",
version: "19.3.0-experimental-a4eb2dfa-20251006",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.3.0-experimental-c7862584-20251006"
reconcilerVersion: "19.3.0-experimental-a4eb2dfa-20251006"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -32534,7 +32532,7 @@
listenToAllSupportedEvents(container);
return new ReactDOMHydrationRoot(initialChildren);
};
exports.version = "19.3.0-experimental-c7862584-20251006";
exports.version = "19.3.0-experimental-a4eb2dfa-20251006";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17674,7 +17674,7 @@ function validateDocumentPositionWithFiberTree(
fragmentFiber)
: !1;
}
FragmentInstance.prototype.experimental_scrollIntoView = function (alignToTop) {
FragmentInstance.prototype.scrollIntoView = function (alignToTop) {
if ("object" === typeof alignToTop) throw Error(formatProdErrorMessage(566));
var children = [];
traverseVisibleHostChildren(
Expand Down Expand Up @@ -19570,14 +19570,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
};
var isomorphicReactPackageVersion$jscomp$inline_2217 = React.version;
if (
"19.3.0-experimental-c7862584-20251006" !==
"19.3.0-experimental-a4eb2dfa-20251006" !==
isomorphicReactPackageVersion$jscomp$inline_2217
)
throw Error(
formatProdErrorMessage(
527,
isomorphicReactPackageVersion$jscomp$inline_2217,
"19.3.0-experimental-c7862584-20251006"
"19.3.0-experimental-a4eb2dfa-20251006"
)
);
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
Expand All @@ -19599,10 +19599,10 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
};
var internals$jscomp$inline_2914 = {
bundleType: 0,
version: "19.3.0-experimental-c7862584-20251006",
version: "19.3.0-experimental-a4eb2dfa-20251006",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.3.0-experimental-c7862584-20251006"
reconcilerVersion: "19.3.0-experimental-a4eb2dfa-20251006"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_2915 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -19709,4 +19709,4 @@ exports.hydrateRoot = function (container, initialChildren, options) {
listenToAllSupportedEvents(container);
return new ReactDOMHydrationRoot(initialChildren);
};
exports.version = "19.3.0-experimental-c7862584-20251006";
exports.version = "19.3.0-experimental-a4eb2dfa-20251006";
Original file line number Diff line number Diff line change
Expand Up @@ -31924,12 +31924,10 @@
? parentHostFiber
: Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
};
FragmentInstance.prototype.experimental_scrollIntoView = function (
alignToTop
) {
FragmentInstance.prototype.scrollIntoView = function (alignToTop) {
if ("object" === typeof alignToTop)
throw Error(
"FragmentInstance.experimental_scrollIntoView() does not support scrollIntoViewOptions. Use the alignToTop boolean instead."
"FragmentInstance.scrollIntoView() does not support scrollIntoViewOptions. Use the alignToTop boolean instead."
);
var children = [];
traverseVisibleHostChildren(
Expand Down Expand Up @@ -32394,11 +32392,11 @@
};
(function () {
var isomorphicReactPackageVersion = React.version;
if ("19.3.0-experimental-c7862584-20251006" !== isomorphicReactPackageVersion)
if ("19.3.0-experimental-a4eb2dfa-20251006" !== isomorphicReactPackageVersion)
throw Error(
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
(isomorphicReactPackageVersion +
"\n - react-dom: 19.3.0-experimental-c7862584-20251006\nLearn more: https://react.dev/warnings/version-mismatch")
"\n - react-dom: 19.3.0-experimental-a4eb2dfa-20251006\nLearn more: https://react.dev/warnings/version-mismatch")
);
})();
("function" === typeof Map &&
Expand Down Expand Up @@ -32435,10 +32433,10 @@
!(function () {
var internals = {
bundleType: 1,
version: "19.3.0-experimental-c7862584-20251006",
version: "19.3.0-experimental-a4eb2dfa-20251006",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.3.0-experimental-c7862584-20251006"
reconcilerVersion: "19.3.0-experimental-a4eb2dfa-20251006"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -32916,7 +32914,7 @@
exports.useFormStatus = function () {
return resolveDispatcher().useHostTransitionStatus();
};
exports.version = "19.3.0-experimental-c7862584-20251006";
exports.version = "19.3.0-experimental-a4eb2dfa-20251006";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19711,7 +19711,7 @@ function validateDocumentPositionWithFiberTree(
fragmentFiber)
: !1;
}
FragmentInstance.prototype.experimental_scrollIntoView = function (alignToTop) {
FragmentInstance.prototype.scrollIntoView = function (alignToTop) {
if ("object" === typeof alignToTop) throw Error(formatProdErrorMessage(566));
var children = [];
traverseVisibleHostChildren(
Expand Down Expand Up @@ -21624,14 +21624,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
};
var isomorphicReactPackageVersion$jscomp$inline_2513 = React.version;
if (
"19.3.0-experimental-c7862584-20251006" !==
"19.3.0-experimental-a4eb2dfa-20251006" !==
isomorphicReactPackageVersion$jscomp$inline_2513
)
throw Error(
formatProdErrorMessage(
527,
isomorphicReactPackageVersion$jscomp$inline_2513,
"19.3.0-experimental-c7862584-20251006"
"19.3.0-experimental-a4eb2dfa-20251006"
)
);
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
Expand All @@ -21653,10 +21653,10 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
};
var internals$jscomp$inline_3223 = {
bundleType: 0,
version: "19.3.0-experimental-c7862584-20251006",
version: "19.3.0-experimental-a4eb2dfa-20251006",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.3.0-experimental-c7862584-20251006"
reconcilerVersion: "19.3.0-experimental-a4eb2dfa-20251006"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_3224 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -21924,7 +21924,7 @@ exports.useFormState = function (action, initialState, permalink) {
exports.useFormStatus = function () {
return ReactSharedInternals.H.useHostTransitionStatus();
};
exports.version = "19.3.0-experimental-c7862584-20251006";
exports.version = "19.3.0-experimental-a4eb2dfa-20251006";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10544,5 +10544,5 @@
'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server'
);
};
exports.version = "19.3.0-experimental-c7862584-20251006";
exports.version = "19.3.0-experimental-a4eb2dfa-20251006";
})();
Original file line number Diff line number Diff line change
Expand Up @@ -7157,4 +7157,4 @@ exports.renderToString = function (children, options) {
'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server'
);
};
exports.version = "19.3.0-experimental-c7862584-20251006";
exports.version = "19.3.0-experimental-a4eb2dfa-20251006";
Original file line number Diff line number Diff line change
Expand Up @@ -10544,5 +10544,5 @@
'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server'
);
};
exports.version = "19.3.0-experimental-c7862584-20251006";
exports.version = "19.3.0-experimental-a4eb2dfa-20251006";
})();
Original file line number Diff line number Diff line change
Expand Up @@ -7260,4 +7260,4 @@ exports.renderToString = function (children, options) {
'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server'
);
};
exports.version = "19.3.0-experimental-c7862584-20251006";
exports.version = "19.3.0-experimental-a4eb2dfa-20251006";
Loading
Loading