diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index 5bb2b747..1ca2cee5 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -115,6 +115,7 @@ export default defineConfig({
{ text: 'Forms', link: '/guide/forms' },
{ text: 'File uploads', link: '/guide/file-uploads' },
{ text: 'Validation', link: '/guide/validation' },
+ { text: 'View transitions', link: '/guide/view-transitions' },
],
},
{
diff --git a/docs/guide/client-side-setup.md b/docs/guide/client-side-setup.md
index 9029720d..01732666 100644
--- a/docs/guide/client-side-setup.md
+++ b/docs/guide/client-side-setup.md
@@ -114,6 +114,102 @@ createInertiaApp({
The `setup` callback receives everything necessary to initialize the client-side framework, including the root Inertia `App` component.
+## Configuring defaults
+
+@available_since core=2.2.11
+
+You may pass a `defaults` object to `createInertiaApp()` to configure default settings for various features. You don't have to pass all keys, just the ones you want to tweak.
+
+```js
+createInertiaApp({
+ // ...
+ defaults: {
+ form: {
+ recentlySuccessfulDuration: 5000,
+ },
+ prefetch: {
+ cacheFor: '1m',
+ hoverDelay: 150,
+ },
+ visitOptions: (href, options) => {
+ return {
+ headers: {
+ ...options.headers,
+ 'X-Custom-Header': 'value',
+ },
+ }
+ },
+ },
+})
+```
+
+The `visitOptions` callback receives the target URL and the current visit options, and should return an object with any options you want to override. For more details on the available configuration options, see the [forms](/guide/forms#form-errors), [prefetching](/guide/prefetching), and [manual visits](/guide/manual-visits#global-visit-options) documentation.
+
+### Updating at runtime
+
+You may also update configuration values at runtime using the exported `config` instance. This is
+particularly useful when you need to adjust settings based on user preferences or application state.
+
+:::tabs key:frameworks
+== Vue
+
+```js
+import { router } from '@inertiajs/vue3'
+
+// Set a single value using dot notation...
+config.set('form.recentlySuccessfulDuration', 1000)
+config.set('prefetch.cacheFor', '5m')
+
+// Set multiple values at once...
+config.set({
+ 'form.recentlySuccessfulDuration': 1000,
+ 'prefetch.cacheFor': '5m',
+})
+
+// Get a configuration value...
+const duration = config.get('form.recentlySuccessfulDuration')
+```
+
+== React
+
+```js
+import { router } from '@inertiajs/react'
+
+// Set a single value using dot notation...
+config.set('form.recentlySuccessfulDuration', 1000)
+config.set('prefetch.cacheFor', '5m')
+
+// Set multiple values at once...
+config.set({
+ 'form.recentlySuccessfulDuration': 1000,
+ 'prefetch.cacheFor': '5m',
+})
+
+// Get a configuration value...
+const duration = config.get('form.recentlySuccessfulDuration')
+```
+
+== Svelte 4|Svelte 5
+
+```js
+import { router } from '@inertiajs/svelte'
+
+// Set a single value using dot notation...
+config.set('form.recentlySuccessfulDuration', 1000)
+config.set('prefetch.cacheFor', '5m')
+
+// Set multiple values at once...
+config.set({
+ 'form.recentlySuccessfulDuration': 1000,
+ 'prefetch.cacheFor': '5m',
+})
+
+// Get a configuration value...
+const duration = config.get('form.recentlySuccessfulDuration')
+```
+
+:::
+
# Resolving components
The `resolve` callback tells Inertia how to load a page component. It receives a page name (string), and returns a page component module. How you implement this callback depends on which bundler (Vite or Webpack) you're using.
diff --git a/docs/guide/error-handling.md b/docs/guide/error-handling.md
index c808c214..5acca89d 100644
--- a/docs/guide/error-handling.md
+++ b/docs/guide/error-handling.md
@@ -6,6 +6,25 @@ One of the advantages to working with a robust server-side framework is the buil
Inertia solves this issue by showing all non-Inertia responses in a modal. This means you get the same beautiful error-reporting you're accustomed to, even though you've made that request over XHR.
+## Dialog element
+
+@available_since core=2.2.13
+
+By default, Inertia displays error modals using a custom `
` overlay. However, you can opt-in to using the native HTML `
` element instead, which provides built-in modal functionality including backdrop handling.
+
+To enable this, configure the `future.useDialogForErrorModal` option in your [application defaults](/guide/client-side-setup#configuring-defaults).
+
+```js
+createInertiaApp({
+ // resolve, setup, etc.
+ defaults: {
+ future: {
+ useDialogForErrorModal: true,
+ },
+ },
+})
+```
+
## Production
In production you will want to return a proper Inertia error response instead of relying on the modal-driven error reporting that is present during development. To accomplish this, you'll need to update your framework's default exception handler to return a custom error page.
diff --git a/docs/guide/forms.md b/docs/guide/forms.md
index 3378abc5..55ece8e3 100644
--- a/docs/guide/forms.md
+++ b/docs/guide/forms.md
@@ -151,7 +151,7 @@ You can pass a `transform` prop to modify the form data before submission. This
### Default values
-You can set default values for form inputs using standard HTML attributes. Use `defaultValue` `value` `value` `defaultValue` (`value` for Svelte < `5.6.0`) for text inputs and textareas, and `defaultChecked` `checked` `checked` `defaultChecked` (`checked` for Svelte < `5.6.0`) for checkboxes and radios.
+You can set default values for form inputs using standard HTML attributes. Use `defaultValue` `defaultValue` `value` `defaultValue` (`value` for Svelte < `5.6.0`) for text inputs and textareas, and `defaultChecked` `defaultChecked` `checked` `defaultChecked` (`checked` for Svelte < `5.6.0`) for checkboxes and radios.
:::tabs key:frameworks
@@ -160,7 +160,7 @@ You can set default values for form inputs using standard HTML attributes. Use <
```vue
@@ -1452,6 +1452,8 @@ $form.setError({
When a form has been successfully submitted, the `wasSuccessful` property will be `true`. In addition to this, forms have a `recentlySuccessful` property, which will be set to `true` for two seconds after a successful form submission. This property can be utilized to show temporary success messages.
+You may customize the duration of the `recentlySuccessful` state by setting the `form.recentlySuccessfulDuration` option in your [application defaults](/guide/client-side-setup#configuring-defaults). The default value is `2000` milliseconds.
+
### Resetting the Form
To reset the form's values back to their default values, you can use the `reset()` method.
diff --git a/docs/guide/links.md b/docs/guide/links.md
index f4eabe2c..48e9ddaa 100644
--- a/docs/guide/links.md
+++ b/docs/guide/links.md
@@ -416,6 +416,49 @@ export default () => (
For more information on this topic, check out the complete documentation on [partial reloads](/guide/partial-reloads.md).
+## View transitions
+
+@available_since core=2.2.13
+
+You may enable [View transitions](/guide/view-transitions) for a link by setting the `viewTransition` prop to `true`. This will use the browser's View Transitions API to animate the page transition.
+
+:::tabs key:frameworks
+== Vue
+
+```vue
+
+
+
+ Navigate
+
+```
+
+== React
+
+```jsx
+import { router } from '@inertiajs/react'
+
+export default () => (
+
+ Navigate
+
+)
+```
+
+== Svelte 4|Svelte 5
+
+```svelte
+
+
+ Navigate
+```
+
+:::
+
## Active states
It's common to set an active state for navigation links based on the current page. This can be accomplished when using Inertia by inspecting the `page` object and doing string comparisons against the `page.url` and `page.component` properties.
diff --git a/docs/guide/load-when-visible.md b/docs/guide/load-when-visible.md
index 7c973dd1..44dd6c6b 100644
--- a/docs/guide/load-when-visible.md
+++ b/docs/guide/load-when-visible.md
@@ -352,3 +352,121 @@ export default () => (
```
:::
+
+## Form submissions
+
+When submitting forms, you may want to use the `except` option to exclude the props that are being used by the `WhenVisible` component. This prevents the props from being reloaded when you get redirected back to the current page because of validation errors.
+
+:::tabs key:frameworks
+== Vue
+
+```vue
+
+
+
+
+
+
+
+
+
+```
+
+== React
+
+```jsx
+import { useForm, WhenVisible } from '@inertiajs/react'
+
+export default function CreateUser() {
+ const { data, setData, post } = useForm({
+ name: '',
+ email: '',
+ })
+
+ function submit(e) {
+ e.preventDefault()
+ post('/users', {
+ except: ['permissions'],
+ })
+ }
+
+ return (
+ <>
+
+
+ {/* ... */}
+ >
+ )
+}
+```
+
+== Svelte 4
+
+```svelte
+
+
+
+
+
+
+
+```
+
+== Svelte 5
+
+```svelte
+
+
+
+
+
+
+
+```
+
+:::
diff --git a/docs/guide/manual-visits.md b/docs/guide/manual-visits.md
index af9d8ee0..5bc9b73b 100644
--- a/docs/guide/manual-visits.md
+++ b/docs/guide/manual-visits.md
@@ -26,6 +26,7 @@ router.visit(url, {
reset: [],
preserveUrl: false,
prefetch: false,
+ viewTransition: false,
onCancelToken: (cancelToken) => {},
onCancel: () => {},
onBefore: (visit) => {},
@@ -62,6 +63,7 @@ router.visit(url, {
reset: [],
preserveUrl: false,
prefetch: false,
+ viewTransition: false,
onCancelToken: (cancelToken) => {},
onCancel: () => {},
onBefore: (visit) => {},
@@ -98,6 +100,7 @@ router.visit(url, {
reset: [],
preserveUrl: false,
prefetch: false,
+ viewTransition: false,
onCancelToken: (cancelToken) => {},
onCancel: () => {},
onBefore: (visit) => {},
@@ -326,6 +329,75 @@ router.post('/users', data, {
> [!NOTE]
> The headers Inertia uses internally to communicate its state to the server take priority and therefore cannot be overwritten.
+## Global visit options
+
+You may configure a `visitOptions` callback when [initializing your Inertia app](/guide/client-side-setup#configuring-defaults) to modify visit options globally for every request. The callback receives the target URL and the current visit options, and should return an object with any options you want to override.
+
+:::tabs key:frameworks
+== Vue
+
+```js
+import { createApp, h } from 'vue'
+import { createInertiaApp } from '@inertiajs/vue3'
+
+createInertiaApp({
+ // ...
+ defaults: {
+ visitOptions: (href, options) => {
+ return {
+ headers: {
+ ...options.headers,
+ 'X-Custom-Header': 'value',
+ },
+ }
+ },
+ },
+})
+```
+
+== React
+
+```js
+import { createInertiaApp } from '@inertiajs/react'
+import { createRoot } from 'react-dom/client'
+
+createInertiaApp({
+ // ...
+ defaults: {
+ visitOptions: (href, options) => {
+ return {
+ headers: {
+ ...options.headers,
+ 'X-Custom-Header': 'value',
+ },
+ }
+ },
+ },
+})
+```
+
+== Svelte 4|Svelte 5
+
+```js
+import { createInertiaApp } from '@inertiajs/svelte'
+
+createInertiaApp({
+ // ...
+ defaults: {
+ visitOptions: (href, options) => {
+ return {
+ headers: {
+ ...options.headers,
+ 'X-Custom-Header': 'value',
+ },
+ }
+ },
+ },
+})
+```
+
+:::
+
## File uploads
When making visits / requests that include files, Inertia will automatically convert the request data into a `FormData` object. If you would like the request to always use a `FormData` object, you may use the `forceFormData` option.
@@ -843,6 +915,39 @@ router.get('/users', { search: 'John' }, { only: ['users'] })
For more information on this feature, check out the [partial reloads](/guide/partial-reloads.md) documentation.
+## View transitions
+
+@available_since core=2.2.13
+
+You may enable [View transitions](/guide/view-transitions) for a visit by setting the `viewTransition` option to `true`. This will use the browser's View Transitions API to animate the page transition.
+
+:::tabs key:frameworks
+== Vue
+
+```js
+import { router } from '@inertiajs/vue3'
+
+router.visit('/another-page', { viewTransition: true })
+```
+
+== React
+
+```js
+import { router } from '@inertiajs/react'
+
+router.visit('/another-page', { viewTransition: true })
+```
+
+== Svelte 4|Svelte 5
+
+```js
+import { router } from '@inertiajs/svelte'
+
+router.visit('/another-page', { viewTransition: true })
+```
+
+:::
+
## Visit cancellation
You can cancel a visit using a cancel token, which Inertia automatically generates and provides via the `onCancelToken()` callback prior to making the visit.
diff --git a/docs/guide/prefetching.md b/docs/guide/prefetching.md
index d4e6b379..9c935f22 100644
--- a/docs/guide/prefetching.md
+++ b/docs/guide/prefetching.md
@@ -4,7 +4,7 @@ Inertia supports prefetching data for pages that are likely to be visited next.
## Link prefetching
-To prefetch data for a page, you can add the `prefetch` prop to the Inertia link component. By default, Inertia will prefetch the data for the page when the user hovers over the link for more than 75ms.
+To prefetch data for a page, you can add the `prefetch` prop to the Inertia link component. By default, Inertia will prefetch the data for the page when the user hovers over the link for more than 75ms. You may customize this hover delay by setting the `prefetch.hoverDelay` option in your [application defaults](/guide/client-side-setup#configuring-defaults).
:::tabs key:frameworks
== Vue
@@ -43,7 +43,7 @@ export default () => (
:::
-By default, data is cached for 30 seconds before being evicted. You can customize this behavior by passing a `cacheFor` prop to the `Link` component.
+By default, data is cached for 30 seconds before being evicted. You may customize this default value by setting the `prefetch.cacheFor` option in your [application defaults](/guide/client-side-setup#configuring-defaults). You may also customize the cache duration on a per-link basis by passing a `cacheFor` prop to the `Link` component.
:::tabs key:frameworks
== Vue
diff --git a/docs/guide/title-and-meta.md b/docs/guide/title-and-meta.md
index 28d73be9..a0a38436 100644
--- a/docs/guide/title-and-meta.md
+++ b/docs/guide/title-and-meta.md
@@ -347,3 +347,22 @@ export default () =>
```
:::
+
+## Inertia attribute on elements
+
+@available_since core=2.2.13
+
+Inertia has historically used the `inertia` attribute to track and manage elements in the document ``. However, you can now opt-in to using the more standards-compliant `data-inertia` attribute instead. According to the HTML specification, custom attributes should be prefixed with `data-` to avoid conflicts with future HTML standards.
+
+To enable this, configure the `future.useDataInertiaHeadAttribute` option in your [application defaults](/guide/client-side-setup#configuring-defaults).
+
+```js
+createInertiaApp({
+ // resolve, setup, etc.
+ defaults: {
+ future: {
+ useDataInertiaHeadAttribute: true,
+ },
+ },
+})
+```
diff --git a/docs/guide/view-transitions.md b/docs/guide/view-transitions.md
new file mode 100644
index 00000000..5de7e8a0
--- /dev/null
+++ b/docs/guide/view-transitions.md
@@ -0,0 +1,378 @@
+# View Transitions
+
+@available_since core=2.2.13
+
+Inertia supports the [View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions), allowing you to animate page transitions.
+
+> [!NOTE]
+> The View Transitions API is a [relatively new browser feature](https://caniuse.com/view-transitions). Inertia gracefully falls back to standard page transitions in browsers that don't support the API.
+
+## Enabling transitions
+
+You may enable view transitions for a visit by setting the `viewTransition` option to `true`. By default, this will apply a cross-fade transition between pages.
+
+:::tabs key:frameworks
+== Vue
+
+```js
+import { router } from '@inertiajs/vue3'
+
+router.visit('/another-page', { viewTransition: true })
+```
+
+== React
+
+```js
+import { router } from '@inertiajs/react'
+
+router.visit('/another-page', { viewTransition: true })
+```
+
+== Svelte 4|Svelte 5
+
+```js
+import { router } from '@inertiajs/svelte'
+
+router.visit('/another-page', { viewTransition: true })
+```
+
+:::
+
+## Transition callbacks
+
+You may also pass a callback to the `viewTransition` option, which will receive the standard [`ViewTransition`](https://developer.mozilla.org/en-US/docs/Web/API/ViewTransition) instance provided by the browser. This allows you to hook into the various promises provided by the API.
+
+:::tabs key:frameworks
+== Vue
+
+```js
+import { router } from '@inertiajs/vue3'
+
+router.visit('/another-page', {
+ viewTransition: (transition) => {
+ transition.ready.then(() => console.log('Transition ready'))
+ transition.updateCallbackDone.then(() => console.log('DOM updated'))
+ transition.finished.then(() => console.log('Transition finished'))
+ },
+})
+```
+
+== React
+
+```js
+import { router } from '@inertiajs/react'
+
+router.visit('/another-page', {
+ viewTransition: (transition) => {
+ transition.ready.then(() => console.log('Transition ready'))
+ transition.updateCallbackDone.then(() => console.log('DOM updated'))
+ transition.finished.then(() => console.log('Transition finished'))
+ },
+})
+```
+
+== Svelte 4|Svelte 5
+
+```js
+import { router } from '@inertiajs/svelte'
+
+router.visit('/another-page', {
+ viewTransition: (transition) => {
+ transition.ready.then(() => console.log('Transition ready'))
+ transition.updateCallbackDone.then(() => console.log('DOM updated'))
+ transition.finished.then(() => console.log('Transition finished'))
+ },
+})
+```
+
+:::
+
+## Links
+
+The `viewTransition` option is also available on the `Link` component.
+
+:::tabs key:frameworks
+== Vue
+
+```vue
+
+
+
+ Navigate
+
+```
+
+== React
+
+```jsx
+import { router } from '@inertiajs/react'
+
+export default () => (
+
+ Navigate
+
+)
+```
+
+== Svelte 4|Svelte 5
+
+```svelte
+
+
+ Navigate
+```
+
+:::
+
+You may also pass a callback to access the `ViewTransition` instance.
+
+:::tabs key:frameworks
+== Vue
+
+```vue
+
+
+
+
+ Navigate
+
+
+```
+
+== React
+
+```jsx
+import { router } from '@inertiajs/react'
+
+export default () => (
+
+ transition.finished.then(() => console.log('Done'))
+ }
+ >
+ Navigate
+
+)
+```
+
+== Svelte 4|Svelte 5
+
+```svelte
+
+
+
+ transition.finished.then(() => console.log('Done'))}
+>
+ Navigate
+
+```
+
+:::
+
+## Global configuration
+
+You may enable view transitions globally for all visits by configuring the `visitOptions` callback
+when [initializing your Inertia app](/guide/client-side-setup#configuring-defaults).
+
+:::tabs key:frameworks
+== Vue
+
+```js
+import { router } from '@inertiajs/vue3'
+
+createInertiaApp({
+ // ...
+ defaults: {
+ visitOptions: (href, options) => {
+ return { viewTransition: true }
+ },
+ },
+})
+```
+
+== React
+
+```js
+import { router } from '@inertiajs/react'
+
+createInertiaApp({
+ // ...
+ defaults: {
+ visitOptions: (href, options) => {
+ return { viewTransition: true }
+ },
+ },
+})
+```
+
+== Svelte 4|Svelte 5
+
+```js
+import { router } from '@inertiajs/svelte'
+
+createInertiaApp({
+ // ...
+ defaults: {
+ visitOptions: (href, options) => {
+ return { viewTransition: true }
+ },
+ },
+})
+```
+
+:::
+
+## Customizing transitions
+
+You may customize the transition animations using CSS. The View Transitions API uses several pseudo-elements that you can target with CSS to create custom animations. The following examples are taken from the [Chrome documentation](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#customize_the_transition).
+
+```css
+@keyframes fade-in {
+ from {
+ opacity: 0;
+ }
+}
+
+@keyframes fade-out {
+ to {
+ opacity: 0;
+ }
+}
+
+@keyframes slide-from-right {
+ from {
+ transform: translateX(30px);
+ }
+}
+
+@keyframes slide-to-left {
+ to {
+ transform: translateX(-30px);
+ }
+}
+
+::view-transition-old(root) {
+ animation:
+ 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
+ 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
+}
+
+::view-transition-new(root) {
+ animation:
+ 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
+ 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
+}
+```
+
+You may also animate individual elements between pages by assigning them a unique `view-transition-name`. For example, you may animate an avatar from a large size on a profile page to a small size on a dashboard.
+
+:::tabs key:frameworks
+== Vue
+
+```vue
+
+
+
+
+
+
+```
+
+```vue
+
+
+
+
+
+
+```
+
+== React
+
+```jsx
+// Profile.jsx
+export default function Profile() {
+ return
+}
+```
+
+```jsx
+// Dashboard.jsx
+export default function Dashboard() {
+ return
+}
+```
+
+```css
+.avatar-large {
+ view-transition-name: user-avatar;
+ width: auto;
+ height: 200px;
+}
+
+.avatar-small {
+ view-transition-name: user-avatar;
+ width: auto;
+ height: 40px;
+}
+```
+
+== Svelte 4|Svelte 5
+
+```svelte
+
+
+
+
+```
+
+```svelte
+
+
+
+
+```
+
+:::
+
+You may customize view transitions to your liking using any CSS animations you wish. For more information, please consult the [View Transitions API documentation](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#customize_the_transition).