docs: cleans up live preview overview (#7068)

This commit is contained in:
Jacob Fletcher
2024-07-08 14:52:15 -04:00
committed by GitHub
parent 441d00a4fd
commit 40a8a3f715
2 changed files with 120 additions and 104 deletions

View File

@@ -10,7 +10,7 @@ keywords: live preview, frontend, react, next.js, vue, nuxt.js, svelte, hook, us
If your front-end application supports Server Components like the [Next.js App Router](https://nextjs.org/docs/app), etc., we suggest setting up [server-side Live Preview](./server) instead. If your front-end application supports Server Components like the [Next.js App Router](https://nextjs.org/docs/app), etc., we suggest setting up [server-side Live Preview](./server) instead.
</Banner> </Banner>
While using Live Preview, the Admin panel emits a new `window.postMessage` event every time your document has changed. Your front-end application can listen for these events and re-render accordingly. While using Live Preview, the [Admin Panel](../admin/overview) emits a new `window.postMessage` event every time your document has changed. Your front-end application can listen for these events and re-render accordingly.
If your front-end application is built with [React](#react) or [Vue](#vue), use the `useLivePreview` hooks that Payload provides. In the future, all other major frameworks like Svelte will be officially supported. If you are using any of these frameworks today, you can still integrate with Live Preview yourself using the underlying tooling that Payload provides. See [building your own hook](#building-your-own-hook) for more information. If your front-end application is built with [React](#react) or [Vue](#vue), use the `useLivePreview` hooks that Payload provides. In the future, all other major frameworks like Svelte will be officially supported. If you are using any of these frameworks today, you can still integrate with Live Preview yourself using the underlying tooling that Payload provides. See [building your own hook](#building-your-own-hook) for more information.
@@ -44,7 +44,16 @@ And return the following values:
It is important that the `depth` argument matches exactly with the depth of your initial page request. The depth property is used to populated relationships and uploads beyond their IDs. See [Depth](../getting-started/concepts#depth) for more information. It is important that the `depth` argument matches exactly with the depth of your initial page request. The depth property is used to populated relationships and uploads beyond their IDs. See [Depth](../getting-started/concepts#depth) for more information.
</Banner> </Banner>
## React ## Frameworks
Live Preview will work with any front-end framework that supports the native [`window.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) API. By default, Payload officially supports the most popular frameworks, including:
- [React](#react)
- [Vue](#vue)
If your framework is not listed, you can still integrate with Live Preview using the underlying tooling that Payload provides. [More details](#building-your-own-hook).
### React
If your front-end application is built with client-side [React](https://react.dev) like [Next.js Pages Router](https://nextjs.org/docs/pages), you can use the `useLivePreview` hook that Payload provides. If your front-end application is built with client-side [React](https://react.dev) like [Next.js Pages Router](https://nextjs.org/docs/pages), you can use the `useLivePreview` hook that Payload provides.
@@ -79,7 +88,12 @@ export const PageClient: React.FC<{
} }
``` ```
## Vue <Banner type="warning">
<strong>Reminder:</strong>
If you are using [React Server Components](https://react.dev/reference/rsc/server-components), we strongly suggest setting up [server-side Live Preview](./server) instead.
</Banner>
### Vue
If your front-end application is built with [Vue 3](https://vuejs.org) or [Nuxt 3](https://nuxt.js), you can use the `useLivePreview` composable that Payload provides. If your front-end application is built with [Vue 3](https://vuejs.org) or [Nuxt 3](https://nuxt.js), you can use the `useLivePreview` composable that Payload provides.
@@ -91,7 +105,7 @@ npm install @payloadcms/live-preview-vue
Then, use the `useLivePreview` hook in your Vue component: Then, use the `useLivePreview` hook in your Vue component:
```vue ```ts
<script setup lang="ts"> <script setup lang="ts">
import type { PageData } from '~/types'; import type { PageData } from '~/types';
import { defineProps } from 'vue'; import { defineProps } from 'vue';
@@ -128,10 +142,10 @@ This package provides the following functions:
| Path | Description | | Path | Description |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | | ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| **`subscribe`** | Subscribes to the Admin panel's `window.postMessage` events and calls the provided callback function. | | **`subscribe`** | Subscribes to the Admin Panel's `window.postMessage` events and calls the provided callback function. |
| **`unsubscribe`** | Unsubscribes from the Admin panel's `window.postMessage` events. | | **`unsubscribe`** | Unsubscribes from the Admin Panel's `window.postMessage` events. |
| **`ready`** | Sends a `window.postMessage` event to the Admin panel to indicate that the front-end is ready to receive messages. | | **`ready`** | Sends a `window.postMessage` event to the Admin Panel to indicate that the front-end is ready to receive messages. |
| **`isLivePreviewEvent`** | Checks if a `MessageEvent` originates from the Admin panel and is a Live Preview event, i.e. debounced form state. | | **`isLivePreviewEvent`** | Checks if a `MessageEvent` originates from the Admin Panel and is a Live Preview event, i.e. debounced form state. |
The `subscribe` function takes the following args: The `subscribe` function takes the following args:
@@ -154,7 +168,7 @@ import { subscribe, unsubscribe } from '@payloadcms/live-preview'
// 3. Populating relationships and uploads // 3. Populating relationships and uploads
// 4. Calling the `onChange` callback with the result // 4. Calling the `onChange` callback with the result
// Your hook should also: // Your hook should also:
// 1. Tell the Admin panel when it is ready to receive messages // 1. Tell the Admin Panel when it is ready to receive messages
// 2. Handle the results of the `onChange` callback to update the UI // 2. Handle the results of the `onChange` callback to update the UI
// 3. Unsubscribe from the `window.postMessage` events when it unmounts // 3. Unsubscribe from the `window.postMessage` events when it unmounts
``` ```
@@ -186,7 +200,7 @@ export const useLivePreview = <T extends any>(props: {
}, []) }, [])
useEffect(() => { useEffect(() => {
// Listen for `window.postMessage` events from the Admin panel // Listen for `window.postMessage` events from the Admin Panel
// When a change is made, the `onChange` callback will be called with the merged data // When a change is made, the `onChange` callback will be called with the merged data
const subscription = subscribe({ const subscription = subscribe({
callback: onChange, callback: onChange,
@@ -195,7 +209,7 @@ export const useLivePreview = <T extends any>(props: {
serverURL, serverURL,
}) })
// Once subscribed, send a `ready` message back up to the Admin panel // Once subscribed, send a `ready` message back up to the Admin Panel
// This will indicate that the front-end is ready to receive messages // This will indicate that the front-end is ready to receive messages
if (!hasSentReadyMessage.current) { if (!hasSentReadyMessage.current) {
hasSentReadyMessage.current = true hasSentReadyMessage.current = true

View File

@@ -2,27 +2,40 @@
title: Live Preview title: Live Preview
label: Overview label: Overview
order: 10 order: 10
desc: With Live Preview you can render your front-end application directly within the Admin panel. Your changes take effect as you type. No save needed. desc: With Live Preview you can render your front-end application directly within the Admin Panel. Your changes take effect as you type. No save needed.
keywords: live preview, preview, live, iframe, iframe preview, visual editing, design keywords: live preview, preview, live, iframe, iframe preview, visual editing, design
--- ---
**With Live Preview you can render your front-end application directly within the Admin panel. As you type, your changes take effect in real-time. No need to save a draft or publish your changes.** With Live Preview you can render your front-end application directly within the [Admin Panel](../admin/overview). As you type, your changes take effect in real-time. No need to save a draft or publish your changes. This works in both [Server-side](./server) as well as [Client-side](./client) environments.
Live Preview works by rendering an iframe on the page that loads your front-end application. The Admin panel communicates with your app through [`window.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) events. These events are emitted every time a change is made to the document. Your app then listens for these events and re-renders itself with the data it receives. Live Preview works in both server-side as well as client-side environments. See [Front-End](./frontend) for more details. Live Preview works by rendering an iframe on the page that loads your front-end application. The Admin Panel communicates with your app through [`window.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) events. These events are emitted every time a change is made to the document. Your app then listens for these events and re-renders itself with the data it receives.
{/* IMAGE OF LIVE PREVIEW HERE */} {/* IMAGE OF LIVE PREVIEW HERE */}
<Banner type="warning">
Live Preview is currently in beta. You may use this feature in production, but please be aware
that it is subject to change and may not be fully stable for all use cases. If you encounter any
issues, please [report
them](https://github.com/payloadcms/payload/issues/new?assignees=jacobsfletch&labels=possible-bug&projects=&title=Live%20Preview&template=1.bug_report.yml)
with as much detail as possible.
</Banner>
## Setup ## Setup
Setting up Live Preview is easy. You first need to enable it through the `admin.livePreview` property of your Payload config. It takes the following options: Setting up Live Preview is easy. This can be done either globally through the [Root Config](../configuration/overview), or on individual [Collection](../configuration/collections) and [Global](../configuration/globals) configs. Once configured, a new "Live Preview" tab will appear at the top of enabled documents. Navigating to this tab opens the preview window and loads your front-end application.
To add Live Preview, use the `admin.livePreview` property in your [Payload Config](../configuration/overview):
```ts
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
// ...
// highlight-start
livePreview: {
url: 'http://localhost:3000', // The URL to your front-end, this can also be a function (see below)
collections: ['pages'], // The Collection(s) to enable Live Preview on (Globals are also possible)
},
// highlight-end
}
})
```
The following options are available:
| Path | Description | | Path | Description |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -33,60 +46,47 @@ Setting up Live Preview is easy. You first need to enable it through the `admin.
_\* An asterisk denotes that a property is required._ _\* An asterisk denotes that a property is required._
Here is a basic example of enabling Live Preview on a `pages` collection: <Banner type="warning">
<strong>Reminder:</strong>
```ts Alternatively, you can define the <code>admin.livePreview</code> property on individual [Collection](../configuration/collections) and [Global](../configuration/globals) configs. Settings defined here will be merged into the top-level as overrides.
// payload.config.ts </Banner>
{
// ...
admin: {
// ...
livePreview: {
url: 'http://localhost:3000', // The URL to your front-end, this can also be a function (see below)
collections: ['pages'], // The collections to enable Live Preview on (globals are also possible)
},
}
}
```
Alternatively, you can define the <code>admin.livePreview</code> property on individual collection and global configs. Settings defined here will be merged into the top-level as overrides (if applicable).
```ts
// Collection.ts
{
// ...
admin: {
// ...
livePreview: {
url: 'http://localhost:3000',
},
}
}
```
Once configured, a new "Live Preview" tab will appear at the top of enabled documents. Navigating to this tab opens the preview window and loads your front-end application.
### URL ### URL
The `url` property is a string that points to your front-end application. This value is used as the `src` attribute of the iframe rendering your front-end. The `url` property is a string that points to your front-end application. This value is used as the `src` attribute of the iframe rendering your front-end. Once loaded, the Admin Panel will communicate directly with your app through `window.postMessage` events.
You can also pass a function in order to dynamically format URLs. This function is called with the following arguments: To set the URL, use the `admin.livePreview.url` property in your [Payload Config](../configuration/overview):
| Path | Description |
| ------------------ | ----------------------------------------------------------------------------------------------------------------- |
| **`data`** | The data of the document being edited. This includes changes that have not yet been saved. |
| **`documentInfo`** | Information about the document being edited like collection slug. [More details](../admin/hooks#usedocumentinfo). |
| **`locale`** | The locale currently being edited (if applicable). [More details](../configuration/localization). |
Here is an example of using a function that returns a dynamic URL:
```ts ```ts
// payload.config.ts import { buildConfig } from 'payload'
{
const config = buildConfig({
// ... // ...
admin: { admin: {
// ... // ...
livePreview: { livePreview: {
url: 'http://localhost:3000', // highlight-line
collections: ['pages'],
},
}
})
```
#### Dynamic URLs
You can also pass a function in order to dynamically format URLs. This is useful for multi-tenant applications, localization, or any other scenario where the URL needs to be generated based on the document being edited.
To set dynamic URLs, set the `admin.livePreview.url` property in your [Payload Config](../configuration/overview) to a function:
```ts
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
// ...
livePreview: {
// highlight-start
url: ({ url: ({
data, data,
documentInfo, documentInfo,
@@ -96,13 +96,50 @@ Here is an example of using a function that returns a dynamic URL:
}${locale ? `?locale=${locale?.code}` : ''}`, // Localization query param }${locale ? `?locale=${locale?.code}` : ''}`, // Localization query param
collections: ['pages'], collections: ['pages'],
}, },
// highlight-end
} }
} })
``` ```
The following arguments are provided to the `url` function:
| Path | Description |
| ------------------ | ----------------------------------------------------------------------------------------------------------------- |
| **`data`** | The data of the document being edited. This includes changes that have not yet been saved. |
| **`documentInfo`** | Information about the document being edited like collection slug. [More details](../admin/hooks#usedocumentinfo). |
| **`locale`** | The locale currently being edited (if applicable). [More details](../configuration/localization). |
### Breakpoints ### Breakpoints
The breakpoints property is an array of objects which are used as “device sizes” in the preview window. Each item will render as an option in the toolbar. When selected, the preview window will resize to the exact dimensions specified in that breakpoint. Each breakpoint takes the following properties: The breakpoints property is an array of objects which are used as “device sizes” in the preview window. Each item will render as an option in the toolbar. When selected, the preview window will resize to the exact dimensions specified in that breakpoint.
To set breakpoints, use the `admin.livePreview.breakpoints` property in your [Payload Config](../configuration/overview):
```ts
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
// ...
livePreview: {
url: 'http://localhost:3000',
// highlight-start
breakpoints: [
{
label: 'Mobile',
name: 'mobile',
width: 375,
height: 667,
},
],
// highlight-end
},
}
})
```
The following options are available for each breakpoint:
| Path | Description | | Path | Description |
| --------------- | --------------------------------------------------------------------------- | | --------------- | --------------------------------------------------------------------------- |
@@ -113,41 +150,6 @@ The breakpoints property is an array of objects which are used as “device size
_\* An asterisk denotes that a property is required._ _\* An asterisk denotes that a property is required._
Here is an example of defining breakpoints:
```ts
// payload.config.ts
{
// ...
admin: {
// ...
livePreview: {
url: 'http://localhost:3000',
breakpoints: [
{
label: 'Mobile',
name: 'mobile',
width: 375,
height: 667,
},
{
label: 'Tablet',
name: 'tablet',
width: 768,
height: 1024,
},
{
label: 'Desktop',
name: 'desktop',
width: 1440,
height: 900,
},
],
},
}
}
```
{/* IMAGE OF TOOLBAR HERE */} {/* IMAGE OF TOOLBAR HERE */}
The "Responsive" option is always available in the drop-down and requires no additional configuration. This is the default breakpoint that will be used on initial load. This option styles the iframe with a width and height of `100%` so that it fills the screen at its maximum size and automatically resizes as the window changes size. The "Responsive" option is always available in the drop-down and requires no additional configuration. This is the default breakpoint that will be used on initial load. This option styles the iframe with a width and height of `100%` so that it fills the screen at its maximum size and automatically resizes as the window changes size.