Skip to content

Commit 96b02bd

Browse files
committed
Cookbook: Inertia Modal
1 parent 291d0d2 commit 96b02bd

File tree

2 files changed

+324
-0
lines changed

2 files changed

+324
-0
lines changed

docs/.vitepress/config.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ export default defineConfig({
152152
text: 'Integrations',
153153
items: [
154154
{ text: 'shadcn/ui', link: '/cookbook/integrating-shadcn-ui' },
155+
{ text: 'Inertia Modal', link: '/cookbook/inertia-modal' },
155156
],
156157
},
157158
{

docs/cookbook/inertia-modal.md

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
# Inertia Modal
2+
3+
[Inertia Modal](https://github.com/inertiaui/modal) is a powerful library that enables you to render any Inertia page
4+
as a modal dialog. It seamlessly integrates with your existing Inertia.js application, allowing you to create modal
5+
workflows without the complexity of managing modal state manually.
6+
7+
Here's a summary of the features:
8+
9+
- Supports React and Vue
10+
- Zero backend configuration
11+
- Super simple frontend API
12+
- Support for Base Route / URL
13+
- Modal and slideover support
14+
- Headless support
15+
- Nested/stacked modals support
16+
- Reusable modals
17+
- Multiple sizes and positions
18+
- Reload props in modals
19+
- Easy communication between nested/stacked modals
20+
- Highly configurable
21+
22+
While you can use Inertia Modal without changes on the backend, we recommend using the Rails gem
23+
[`inertia_rails-contrib`](https://github.com/skryukov/inertia_rails-contrib) to enhance your modals with base URL support. This ensures that your modals are accessible,
24+
SEO-friendly, and provide a better user experience.
25+
26+
> [!NOTE]
27+
> Svelte 5 is not yet supported by Inertia Modal.
28+
29+
## Installation
30+
31+
### 1. Install the NPM Package
32+
33+
:::tabs key:frameworks
34+
== Vue
35+
36+
```bash
37+
npm install @inertiaui/modal-vue
38+
```
39+
40+
== React
41+
42+
```bash
43+
npm install @inertiaui/modal-react
44+
```
45+
46+
:::
47+
48+
### 2. Configure Inertia
49+
50+
Update your Inertia app setup to include the modal plugin:
51+
52+
:::tabs key:frameworks
53+
== Vue
54+
55+
```js
56+
// frontend/entrypoints/inertia.js
57+
import { createApp, h } from 'vue'
58+
import { createInertiaApp } from '@inertiajs/vue3'
59+
import { renderApp } from '@inertiaui/modal-vue' // [!code ++]
60+
61+
createInertiaApp({
62+
resolve: (name) => {
63+
const pages = import.meta.glob('../pages/**/*.vue', { eager: true })
64+
return pages[`../pages/${name}.vue`]
65+
},
66+
setup({ el, App, props, plugin }) {
67+
createApp({ render: () => h(App, props) }) // [!code --]
68+
createApp({ render: renderApp(App, props) }) // [!code ++]
69+
.use(plugin)
70+
.mount(el)
71+
},
72+
})
73+
```
74+
75+
== React
76+
77+
```js
78+
// frontend/entrypoints/inertia.js
79+
import { createInertiaApp } from '@inertiajs/react'
80+
import { createElement } from 'react' // [!code --]
81+
import { renderApp } from '@inertiaui/modal-react' // [!code ++]
82+
import { createRoot } from 'react-dom/client'
83+
84+
createInertiaApp({
85+
resolve: (name) => {
86+
const pages = import.meta.glob('../pages/**/*.jsx', { eager: true })
87+
return pages[`../pages/${name}.jsx`]
88+
},
89+
setup({ el, App, props }) {
90+
const root = createRoot(el)
91+
root.render(createElement(App, props)) // [!code --]
92+
root.render(renderApp(App, props)) // [!code ++]
93+
},
94+
})
95+
```
96+
97+
:::
98+
99+
### 3. Tailwind CSS Configuration
100+
101+
:::tabs key:frameworks
102+
== Vue
103+
104+
For Tailwind CSS v4, add the modal styles to your CSS:
105+
106+
```css
107+
/* app/entrypoints/frontend/application.css */
108+
@source "../../../node_modules/@inertiaui/modal-vue";
109+
```
110+
111+
For Tailwind CSS v3, update your `tailwind.config.js`:
112+
113+
```js
114+
export default {
115+
content: [
116+
'./node_modules/@inertiaui/modal-vue/src/**/*.{js,vue}',
117+
// other paths...
118+
],
119+
}
120+
```
121+
122+
== React
123+
124+
For Tailwind CSS v4, add the modal styles to your CSS:
125+
126+
```css
127+
/* app/entrypoints/frontend/application.css */
128+
@source "../../../node_modules/@inertiaui/modal-react";
129+
```
130+
131+
For Tailwind CSS v3, update your `tailwind.config.js`:
132+
133+
```js
134+
export default {
135+
content: [
136+
'./node_modules/@inertiaui/modal-react/src/**/*.{js,jsx}',
137+
// other paths...
138+
],
139+
}
140+
```
141+
142+
:::
143+
144+
### 4. Add the Ruby Gem (optional but recommended)
145+
146+
Install the [`inertia_rails-contrib`](https://github.com/skryukov/inertia_rails-contrib) gem to your Rails application to enable base URL support for modals:
147+
148+
```bash
149+
bundle add inertia_rails-contrib
150+
```
151+
152+
## Basic example
153+
154+
The package comes with two components: `Modal` and `ModalLink`. `ModalLink` is very similar to Inertia's [built-in
155+
`Link` component](/guide/links), but it opens the linked route in a modal instead of a full page load. So, if you have a
156+
link that you want to open in a modal, you can simply replace `Link` with `ModalLink`.
157+
158+
:::tabs key:frameworks
159+
== Vue
160+
161+
```vue
162+
<script setup>
163+
import { Link } from '@inertiajs/vue3' // [!code --]
164+
import { ModalLink } from '@inertiaui/modal-vue' // [!code ++]
165+
</script>
166+
167+
<template>
168+
<!-- [!code --] -->
169+
<Link href="/users/create">Create User</Link>
170+
<!-- [!code ++] -->
171+
<ModalLink href="/users/create">Create User</ModalLink>
172+
</template>
173+
```
174+
175+
== React
176+
177+
```jsx
178+
import {Link} from '@inertiajs/react' // [!code --]
179+
import {ModalLink} from '@inertiaui/modal-react' // [!code ++]
180+
181+
export const CreateUserButton = () => {
182+
return (
183+
<Link href="/users/create">Create User</Link> // [!code --]
184+
<ModalLink href="/users/create">Create User</ModalLink> // [!code ++]
185+
)
186+
}
187+
```
188+
189+
:::
190+
191+
The page you linked can then use the `Modal` component to wrap its content in a modal.
192+
193+
:::tabs key:frameworks
194+
== Vue
195+
196+
```vue
197+
<script setup>
198+
import { Modal } from '@inertiaui/modal-vue'
199+
</script>
200+
201+
<template>
202+
<!-- [!code ++] -->
203+
<Modal>
204+
<h1>Create User</h1>
205+
<form>
206+
<!-- Form fields -->
207+
</form>
208+
<!-- [!code ++] -->
209+
</Modal>
210+
</template>
211+
```
212+
213+
== React
214+
215+
```jsx
216+
import {Modal} from '@inertiaui/modal-react'
217+
218+
export const CreateUser = () => {
219+
return (
220+
{/* [!code --] */}
221+
<>
222+
{/* [!code ++] */}
223+
<Modal>
224+
<h1>Create User</h1>
225+
<form>
226+
{/* Form fields */}
227+
</form>
228+
{/* [!code --] */}
229+
</Modal>
230+
{/* [!code ++] */}
231+
</>
232+
)
233+
}
234+
```
235+
236+
:::
237+
238+
That's it! There is no need to change anything about your routes or controllers!
239+
240+
## Enhanced Usage With Base URL Support
241+
242+
By default, Inertia Modal doesn't change the URL when opening a modal. It just stays on the same page and displays the
243+
modal content. However, you may want to change this behavior and update the URL when opening a modal. This has a few
244+
benefits:
245+
246+
- It allows users to bookmark the modal and share the URL with others.
247+
- The modal becomes part of the browser history, so users can use the back and forward buttons.
248+
- It makes the modal content accessible to search engines (when using [SSR](/guide/server-side-rendering)).
249+
- It allows you to open the modal in a new tab.
250+
251+
> [!NOTE]
252+
> To enable this feature, you need to use the [`inertia_rails-contrib`](https://github.com/skryukov/inertia_rails-contrib) gem, which provides base URL support for modals.
253+
254+
## Define a Base Route
255+
256+
To define the base route for your modal, you need to use the `inertia_modal` renderer in your controller instead of the
257+
`inertia` one. It accepts the same arguments as the `inertia` renderer:
258+
259+
```ruby
260+
261+
class UsersController < ApplicationController
262+
def edit
263+
render inertia: 'Users/Edit', props: { # [!code --]
264+
render inertia_modal: 'Users/Edit', props: { # [!code ++]
265+
user:,
266+
roles: -> { Role.all },
267+
}
268+
end
269+
end
270+
```
271+
272+
Then, you can pass the `base_url` parameter to the `inertia_modal` renderer to define the base route for your modal:
273+
274+
```ruby
275+
276+
class UsersController < ApplicationController
277+
def edit
278+
render inertia_modal: 'Users/Edit', props: {
279+
user:,
280+
roles: -> { Role.all },
281+
} # [!code --]
282+
}, base_url : users_path # [!code ++]
283+
end
284+
end
285+
```
286+
287+
> [!WARNING] Reusing the Modal URL with different Base Routes
288+
> The `base_url` parameter acts merely as a fallback when the modal is directly opened using a URL. If you open the
289+
> modal from a different route, the URL will be generated based on the current route.
290+
291+
## Open a Modal with a Base Route
292+
293+
Finally, the frontend needs to know that we're using the browser history to navigate between modals. To do this, you need
294+
to add the `navigate` attribute to the `ModalLink` component:
295+
296+
:::tabs key:frameworks
297+
== Vue
298+
299+
```vue
300+
<template>
301+
<ModalLink navigate href="/users/create"> Create User </ModalLink>
302+
</template>
303+
```
304+
305+
== React
306+
307+
```jsx
308+
export default function UserIndex() {
309+
return (
310+
<ModalLink navigate href="/users/create">
311+
Create User
312+
</ModalLink>
313+
)
314+
}
315+
```
316+
317+
:::
318+
319+
Now, when you click the "Create User" link, it will open the modal and update the URL to `/users/create`.
320+
321+
## Further Reading
322+
323+
For advanced usage, configuration options, and additional features, check out [the official Inertia Modal documentation](https://inertiaui.com/inertia-modal/docs).

0 commit comments

Comments
 (0)