docs: rewrites admin docs to 3.0 (#6891)
This commit is contained in:
@@ -6,80 +6,137 @@ desc: Fully customize your Admin Panel by swapping in your own React components.
|
|||||||
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||||
---
|
---
|
||||||
|
|
||||||
The [Payload Admin](./overview) panel is designed to be as minimal and straightforward as possible to allow easy customization and control. In order for Payload to support this level of customization without introducing versioning or future-proofing issues, Payload provides a pattern for you to supply your own React components via your Payload config.
|
The [Payload Admin Panel](./overview) is designed to be as minimal and straightforward as possible to allow for both easy customization and full control over the UI. In order for Payload to support this level of customization, Payload provides a pattern for you to supply your own React components through your [Payload Config](../configuration/overview).
|
||||||
|
|
||||||
<Banner type="warning">
|
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default, with the exception of [Custom Providers](#custom-providers). This enables the use of the [Local API](../local-api) directly in the front-end. Custom Components are available for nearly every part of the Admin Panel for extreme granularity and control.
|
||||||
All Custom Components in the Admin Panel are [React Server Components](https://react.dev/reference/rsc/server-components). This means they are rendered on the server
|
|
||||||
</Banner>
|
|
||||||
|
|
||||||
To swap in your own React component, first, consult the list of available components below. Determine the scope that corresponds to what you are trying to accomplish, and then author your React component accordingly.
|
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
<strong>Tip:</strong>
|
<strong>Note:</strong>
|
||||||
<br />
|
Client Components continue to be fully supported. To use Client Components in your app, simply import them into a Server Component and render them. Ensure your Client Component includes the `use client` directive and that any [non-serializable props](https://react.dev/reference/rsc/use-client#serializable-types) are sanitized. [More details](#client-components).
|
||||||
Custom components will automatically be provided with all props that the default component
|
|
||||||
normally accepts.
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
## Base Component Overrides
|
To swap in your own Custom Component, consult the list of available components below. Determine the scope that corresponds to what you are trying to accomplish, then [author your React component(s)](#building-custom-components) accordingly.
|
||||||
|
|
||||||
You can override a set of admin panel-wide components by providing a component to your base Payload config's `admin.components` property. The following options are available:
|
There are four main types of Custom Components in Payload:
|
||||||
|
|
||||||
| Path | Description |
|
- [Root Components](#custom-root-components)
|
||||||
|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
- [Collection Components](#custom-collection-components)
|
||||||
| **`Nav`** | Contains the sidebar / mobile menu in its entirety. |
|
- [Global Components](#custom-global-components)
|
||||||
| **`BeforeNavLinks`** | Array of components to inject into the built-in Nav, _before_ the links themselves. |
|
- [Field Components](./fields)
|
||||||
| **`AfterNavLinks`** | Array of components to inject into the built-in Nav, _after_ the links. |
|
|
||||||
| **`BeforeDashboard`** | Array of components to inject into the built-in Dashboard, _before_ the default dashboard contents. |
|
|
||||||
| **`AfterDashboard`** | Array of components to inject into the built-in Dashboard, _after_ the default dashboard contents. [Demo](https://github.com/payloadcms/payload/tree/main/test/admin/components/AfterDashboard/index.tsx) |
|
|
||||||
| **`BeforeLogin`** | Array of components to inject into the built-in Login, _before_ the default login form. |
|
|
||||||
| **`AfterLogin`** | Array of components to inject into the built-in Login, _after_ the default login form. |
|
|
||||||
| **`logout.Button`** | A custom React component. |
|
|
||||||
| **`graphics.Icon`** | Used as a graphic within the `Nav` component. Often represents a condensed version of a full logo. |
|
|
||||||
| **`graphics.Logo`** | The full logo to be used in contexts like the `Login` view. |
|
|
||||||
| **`providers`** | Define your own provider components that will wrap the [Admin Panel](./overview). [More](#custom-providers) |
|
|
||||||
| **`actions`** | Array of custom components to be rendered in the [Admin Panel](./overview) header, providing additional interactivity and functionality. |
|
|
||||||
| **`views`** | Override or create new [Views](./views) within the [Admin Panel](./overview). |
|
|
||||||
|
|
||||||
Here is a full example showing how to swap some of these components for your own.
|
## Custom Root Components
|
||||||
|
|
||||||
`payload.config.js`
|
Root Components are those that effect the [Admin Panel](./overview) generally. You can override Root Components through the `admin.components` property of the [Payload Config](../getting-started/overview).
|
||||||
|
|
||||||
|
Here is an example showing what it might look like to swap out Root Components for your own Custom Components. See [Building Custom Components](#building-custom-components) for exact details on how to build them:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { buildConfig } from 'payload/config'
|
import { buildConfig } from 'payload'
|
||||||
|
|
||||||
import {
|
import { MyCustomLogo } from './MyCustomLogo'
|
||||||
MyCustomNav,
|
|
||||||
MyCustomLogo,
|
|
||||||
MyCustomIcon,
|
|
||||||
MyCustomAccount,
|
|
||||||
MyCustomDashboard,
|
|
||||||
MyProvider,
|
|
||||||
MyCustomAdminAction,
|
|
||||||
} from './customComponents'
|
|
||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
Nav: MyCustomNav,
|
|
||||||
graphics: {
|
graphics: {
|
||||||
Icon: MyCustomIcon,
|
Logo: MyCustomLogo, // highlight-line
|
||||||
Logo: MyCustomLogo,
|
|
||||||
},
|
},
|
||||||
actions: [MyCustomAdminAction],
|
|
||||||
views: {
|
|
||||||
Account: MyCustomAccount,
|
|
||||||
Dashboard: MyCustomDashboard,
|
|
||||||
},
|
|
||||||
providers: [MyProvider],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## Collections
|
The following options are available:
|
||||||
|
|
||||||
You can override components on a collection-by-collection basis via the `admin.components` property.
|
| Path | Description |
|
||||||
|
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| **`Nav`** | Contains the sidebar / mobile menu in its entirety. |
|
||||||
|
| **`BeforeNavLinks`** | An array of Custom Components to inject into the built-in Nav, _before_ the links themselves. |
|
||||||
|
| **`AfterNavLinks`** | An array of Custom Components to inject into the built-in Nav, _after_ the links. |
|
||||||
|
| **`BeforeDashboard`** | An array of Custom Components to inject into the built-in Dashboard, _before_ the default dashboard contents. |
|
||||||
|
| **`AfterDashboard`** | An array of Custom Components to inject into the built-in Dashboard, _after_ the default dashboard contents. |
|
||||||
|
| **`BeforeLogin`** | An array of Custom Components to inject into the built-in Login, _before_ the default login form. |
|
||||||
|
| **`AfterLogin`** | An array of Custom Components to inject into the built-in Login, _after_ the default login form. |
|
||||||
|
| **`logout.Button`** | The button displayed in the sidebar that logs the user out. |
|
||||||
|
| **`graphics.Icon`** | The simplified logo used in contexts like the the `Nav` component. |
|
||||||
|
| **`graphics.Logo`** | The full logo used in contexts like the `Login` view. |
|
||||||
|
| **`providers`** | Custom [React Context](https://react.dev/learn/scaling-up-with-reducer-and-context) providers that will wrap the entire [Admin Panel](./overview). [More details](#custom-providers). |
|
||||||
|
| **`actions`** | An array of Custom Components to be rendered in the header of the [Admin Panel](./overview), providing additional interactivity and functionality. |
|
||||||
|
| **`views`** | Override or create new views within the [Admin Panel](./overview). [More details](./views). |
|
||||||
|
|
||||||
|
<Banner type="success">
|
||||||
|
<strong>Note:</strong> You can also use the `admin.components` property on any Collection Config or Global Config to set [Custom Collection Components](#custom-collection-components) or [Custom Global Components](#custom-global-components).
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
### Custom Providers
|
||||||
|
|
||||||
|
You can add additional [React Context](https://react.dev/learn/scaling-up-with-reducer-and-context) to any Payload app through Custom Providers. As you add more and more Custom Components to your [Admin Panel](./overview), this is a great may to share state across all of them.
|
||||||
|
|
||||||
|
To do this, add `admin.components.providers` to your config:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { buildConfig } from 'payload'
|
||||||
|
|
||||||
|
import { MyProvider } from './MyProvider'
|
||||||
|
|
||||||
|
export default buildConfig({
|
||||||
|
// ...
|
||||||
|
admin: {
|
||||||
|
components: {
|
||||||
|
providers: [MyProvider], // highlight-line
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Then build your Custom Provider as follows:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client'
|
||||||
|
import React, { createContext, useContext } from 'react'
|
||||||
|
|
||||||
|
const MyCustomContext = React.createContext(myCustomValue)
|
||||||
|
|
||||||
|
export const MyProvider: React.FC = ({ children }) => {
|
||||||
|
return (
|
||||||
|
<MyCustomContext.Provider value={myCustomValue}>
|
||||||
|
{children}
|
||||||
|
</MyCustomContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useMyCustomContext = () => useContext(MyCustomContext)
|
||||||
|
```
|
||||||
|
|
||||||
|
<Banner type="warning">
|
||||||
|
<strong>Reminder:</strong> Custom Providers are by definition Client Components. This means they must include the `use client` directive at the top of their files and cannot use server-only code.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
## Custom Collection Components
|
||||||
|
|
||||||
|
Collection Components are those that effect [Collection](../configuration/collections)-specific UI within the [Admin Panel](./overview). You can override Collection Components through the `admin.components` property on any [Collection Config](../configuration/collections).
|
||||||
|
|
||||||
|
Here is an example showing what it might look like to swap out Collection Components for your own Custom Components. See [Building Custom Components](#building-custom-components) for exact details on how to build them:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { SanitizedCollectionConfig } from 'payload/types'
|
||||||
|
import { CustomSaveButton } from './CustomSaveButton'
|
||||||
|
|
||||||
|
export const MyCollection: SanitizedCollectionConfig = {
|
||||||
|
slug: 'my-collection',
|
||||||
|
admin: {
|
||||||
|
components: {
|
||||||
|
edit: {
|
||||||
|
SaveButton: CustomSaveButton, // highlight-line
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The following options are available:
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||||||
@@ -87,165 +144,171 @@ You can override components on a collection-by-collection basis via the `admin.c
|
|||||||
| **`BeforeListTable`** | Array of components to inject _before_ the built-in List view's table |
|
| **`BeforeListTable`** | Array of components to inject _before_ the built-in List view's table |
|
||||||
| **`AfterList`** | Array of components to inject _after_ the built-in List view |
|
| **`AfterList`** | Array of components to inject _after_ the built-in List view |
|
||||||
| **`AfterListTable`** | Array of components to inject _after_ the built-in List view's table |
|
| **`AfterListTable`** | Array of components to inject _after_ the built-in List view's table |
|
||||||
| **`edit.SaveButton`** | Replace the default `Save` button with a custom component. Drafts must be disabled |
|
| **`edit.SaveButton`** | Replace the default `Save` button with a Custom Component. Drafts must be disabled |
|
||||||
| **`edit.SaveDraftButton`** | Replace the default `Save Draft` button with a custom component. Drafts must be enabled and autosave must be disabled. |
|
| **`edit.SaveDraftButton`** | Replace the default `Save Draft` button with a Custom Component. Drafts must be enabled and autosave must be disabled. |
|
||||||
| **`edit.PublishButton`** | Replace the default `Publish` button with a custom component. Drafts must be enabled. |
|
| **`edit.PublishButton`** | Replace the default `Publish` button with a Custom Component. Drafts must be enabled. |
|
||||||
| **`edit.PreviewButton`** | Replace the default `Preview` button with a custom component. |
|
| **`edit.PreviewButton`** | Replace the default `Preview` button with a Custom Component. |
|
||||||
| **`views`** | Override or create new [Views](./views) within the [Admin Panel](./overview). |
|
| **`views`** | Override or create new views within the [Admin Panel](./overview). [More details](./views). |
|
||||||
|
|
||||||
Here is a full example showing how to swap some of these components for your own:
|
## Custom Global Components
|
||||||
|
|
||||||
`CustomSaveButton.tsx`
|
Global Components are those that effect [Global](../configuration/globals)-specific UI within the [Admin Panel](./overview). You can override Global Components through the `admin.components` property on any [Global Config](../configuration/globals).
|
||||||
|
|
||||||
```tsx
|
Here is an example showing what it might look like to swap out Global Components for your own Custom Components. See [Building Custom Components](#building-custom-components) for exact details on how to build them:
|
||||||
import { CustomSaveButtonProps } from 'payload/types'
|
|
||||||
|
|
||||||
const CustomSaveButton: CustomSaveButtonProps = ({
|
|
||||||
DefaultButton,
|
|
||||||
label,
|
|
||||||
save
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<DefaultButton
|
|
||||||
label={label}
|
|
||||||
save={save}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`CustomSaveDraftButton.tsx`
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { CustomSaveDraftButtonProps } from 'payload/types'
|
|
||||||
|
|
||||||
export const CustomSaveDraftButton: CustomSaveDraftButtonProps = ({
|
|
||||||
DefaultButton,
|
|
||||||
disabled,
|
|
||||||
label,
|
|
||||||
saveDraft,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<DefaultButton
|
|
||||||
label={label}
|
|
||||||
disabled={disabled}
|
|
||||||
saveDraft={saveDraft}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`CustomPublishButton.tsx`
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { CustomPreviewButtonProps } from 'payload/types'
|
|
||||||
|
|
||||||
export const CustomPublishButton: CustomPublishButtonProps = ({
|
|
||||||
DefaultButton,
|
|
||||||
disabled,
|
|
||||||
label,
|
|
||||||
publish,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<DefaultButton
|
|
||||||
label={label}
|
|
||||||
disabled={disabled}
|
|
||||||
publish={publish}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`CustomPreviewButton`
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { CustomPreviewButtonProps } from 'payload/types'
|
|
||||||
|
|
||||||
export const CustomPreviewButton: CustomPreviewButtonProps = ({
|
|
||||||
DefaultButton,
|
|
||||||
disabled,
|
|
||||||
label,
|
|
||||||
preview,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<DefaultButton
|
|
||||||
label={label}
|
|
||||||
disabled={disabled}
|
|
||||||
preview={preview}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`collection.ts`
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import * as React from 'react'
|
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { SanitizedGlobalConfig } from 'payload/types'
|
||||||
import { CustomSaveButton } from './CustomSaveButton'
|
import { CustomSaveButton } from './CustomSaveButton'
|
||||||
import { CustomSaveDraftButton } from './CustomSaveDraftButton'
|
|
||||||
import { CustomPublishButton } from './CustomPublishButton'
|
|
||||||
import { CustomPreviewButton } from './CustomPreviewButton'
|
|
||||||
|
|
||||||
export const MyCollection: SanitizedCollectionConfig = {
|
export const MyGlobal: SanitizedGlobalConfig = {
|
||||||
slug: 'my-collection',
|
slug: 'my-global',
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
edit: {
|
elements: {
|
||||||
SaveButton: CustomSaveButton,
|
SaveButton: CustomSaveButton, // highlight-line
|
||||||
SaveDraftButton: CustomSaveDraftButton,
|
|
||||||
PublishButton: CustomPublishButton,
|
|
||||||
PreviewButton: CustomPreviewButton,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// ...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Globals
|
The following options are available:
|
||||||
|
|
||||||
As with Collections, you can override components on a global-by-global basis via the `admin.components` property.
|
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`elements.SaveButton`** | Replace the default `Save` button with a custom component. Drafts must be disabled |
|
| **`elements.SaveButton`** | Replace the default `Save` button with a Custom Component. Drafts must be disabled. |
|
||||||
| **`elements.SaveDraftButton`** | Replace the default `Save Draft` button with a custom component. Drafts must be enabled and autosave must be disabled. |
|
| **`elements.SaveDraftButton`** | Replace the default `Save Draft` button with a Custom Component. Drafts must be enabled and autosave must be disabled. |
|
||||||
| **`elements.PublishButton`** | Replace the default `Publish` button with a custom component. Drafts must be enabled. |
|
| **`elements.PublishButton`** | Replace the default `Publish` button with a Custom Component. Drafts must be enabled. |
|
||||||
| **`elements.PreviewButton`** | Replace the default `Preview` button with a custom component. |
|
| **`elements.PreviewButton`** | Replace the default `Preview` button with a Custom Component. |
|
||||||
| **`views`** | Override or create new [Views](./views) within the [Admin Panel](./overview). |
|
| **`views`** | Override or create new views within the [Admin Panel](./overview). [More details](./views). |
|
||||||
|
|
||||||
## Custom providers
|
## Building Custom Components
|
||||||
|
|
||||||
As your admin customizations gets more complex you may want to share state between fields or other components. You can add custom providers to do add your own context to any Payload app for use in other custom components within the [Admin Panel](./overview). Within your config add `admin.components.providers`, these can be used to share context or provide other custom functionality. See the [React Context](https://reactjs.org/docs/context.html) docs to learn more.
|
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default, with the exception of [Custom Providers](#custom-providers). This enables the use of the [Local API](../local-api) directly in the front-end.
|
||||||
|
|
||||||
<Banner type="warning">
|
To make building Custom Components as easy as possible, Payload automatically provides common props, such as the [`payload`](../local-api/overview) class, the [`i18n`](../configuration/i18n) object, etc. This means that when building Custom Components within the Admin Panel, you do not have to get these yourself like you would from an external application.
|
||||||
<strong>Reminder:</strong> Don't forget to pass the **children** prop through the provider
|
|
||||||
component for the admin UI to show
|
|
||||||
</Banner>
|
|
||||||
|
|
||||||
## Styling Custom Components
|
Here is an example:
|
||||||
|
|
||||||
Payload exports its SCSS variables and mixins for reuse in your own custom components. This is helpful in cases where you might want to style a custom input similarly to Payload's built-ini styling, so it blends more thoroughly into the existing admin UI.
|
|
||||||
|
|
||||||
To make use of Payload SCSS variables / mixins to use directly in your own components, you can import them as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
@import '~payload/scss';
|
|
||||||
```
|
|
||||||
|
|
||||||
## Getting the current language
|
|
||||||
|
|
||||||
When developing custom components you can support multiple languages to be consistent with Payload's i18n support. The best way to do this is to add your translation resources to the [i18n configuration](https://payloadcms.com/docs/configuration/i18n) and import `useTranslation` from `@payloadcms/ui/providers/Translation` in your components.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useTranslation } from '@payloadcms/ui/providers/Translation'
|
import React from 'react'
|
||||||
|
|
||||||
const CustomComponent: React.FC = () => {
|
const MyServerComponent = async ({
|
||||||
// highlight-start
|
payload // highlight-line
|
||||||
const { t, i18n } = useTranslation()
|
}) => {
|
||||||
// highlight-end
|
const page = await payload.findByID({
|
||||||
|
collection: 'pages',
|
||||||
|
id: '123',
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<p>{page.title}</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Each Custom Component receives the following props by default:
|
||||||
|
|
||||||
|
| Prop | Description |
|
||||||
|
| ------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||||
|
| `payload` | The [Payload](../local-api/overview) class. |
|
||||||
|
| `i18n` | The [i18n](../i18n) object. |
|
||||||
|
|
||||||
|
Custom Components also receive various other props that are specific to the context in which the Custom Component is being rendered. For example, [Custom Views](./views) receive the `user` prop. For a full list of available props, consult the documentation related to the specific component you are working with.
|
||||||
|
|
||||||
|
<Banner type="success">
|
||||||
|
See [Root Components](#custom-root-components), [Collection Components](#custom-collection-components), [Global Components](#custom-global-components), or [Field Components](#custom-field-components) for a complete list of all available components.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
#### Client Components
|
||||||
|
|
||||||
|
When [Building Custom Components](#building-custom-components), it's still possible to use client-side code such as `useState` or the `window` object. To do this, simply define your component in a new file with the `use client` directive at the top:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client' // highlight-line
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
|
||||||
|
export const MyClientComponent: React.FC = () => {
|
||||||
|
const [count, setCount] = useState(0)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button onClick={() => setCount(count + 1)}>
|
||||||
|
Clicked {count} times
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then simply import and render your Client Component within your Server Component:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React from 'react'
|
||||||
|
import { MyClientComponent } from './MyClientComponent'
|
||||||
|
|
||||||
|
export default function MyServerComponent() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<MyClientComponent />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<Banner type="warning">
|
||||||
|
<strong>Reminder:</strong>
|
||||||
|
Client Components cannot be passed [non-serializable props](https://react.dev/reference/rsc/use-client#serializable-types). Before rendering your Client Component from a Server Component, ensure that any props passed to it are appropriately sanitized.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
#### Using Hooks
|
||||||
|
|
||||||
|
To make it easier to [build your Custom Components](#building-custom-components), you can use [Payload's built-in React Hooks](./hooks) on the client. For example, you might want to interact with one of Payload's many React Contexts:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client'
|
||||||
|
import React from 'react'
|
||||||
|
import { useDocumentInfo } from '@payloadcms/ui'
|
||||||
|
|
||||||
|
export const MyClientComponent: React.FC = () => {
|
||||||
|
const { slug } = useDocumentInfo()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<p>{`Entity slug: ${slug}`}</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<Banner type="success">
|
||||||
|
See the [Hooks](./hooks) documentation for a full list of available hooks.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
#### Getting the Current Language
|
||||||
|
|
||||||
|
All Custom Components can support multiple languages to be consistent with Payload's [Internationalization](../configuration/i18n). To do this, first add your translation resources to the [I18n Config](../configuration/i18n).
|
||||||
|
|
||||||
|
From any Server Component, you can translate resources using the `getTranslation` function from `@payloadcms/translations`. All Server Components automatically receive the `i18n` object as a prop by default.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React from 'react'
|
||||||
|
import { getTranslation } from '@payloadcms/translations'
|
||||||
|
|
||||||
|
export default async function MyServerComponent({ i18n }) {
|
||||||
|
const translatedTitle = getTranslation(myTranslation, i18n) // highlight-line
|
||||||
|
|
||||||
|
return (
|
||||||
|
<p>{translatedTitle}</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The best way to do this within a Client Component is to import the `useTranslation` hook from `@payloadcms/ui`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React from 'react'
|
||||||
|
import { useTranslation } from '@payloadcms/ui'
|
||||||
|
|
||||||
|
export const MyClientComponent: React.FC = () => {
|
||||||
|
const { t, i18n } = useTranslation() // highlight-line
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul>
|
<ul>
|
||||||
@@ -257,23 +320,94 @@ const CustomComponent: React.FC = () => {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Getting the current locale
|
<Banner type="success">
|
||||||
|
See the [Hooks](./hooks) documentation for a full list of available hooks.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
In any custom component you can get the selected locale with `useLocale` hook. `useLocale` returns the full locale object, consisting of a `label`, `rtl`(right-to-left) property, and then `code`. Here is a simple example:
|
#### Getting the Current Locale
|
||||||
|
|
||||||
|
All [Custom Views](./views) can support multiple locales to be consistent with Payload's [Localization](../configuration/localization). All Custom Views automatically receive the `locale` object as a prop by default. This can be used to scope API requests, etc.:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useLocale } from 'payload/components/utilities'
|
import React from 'react'
|
||||||
|
|
||||||
|
export default async function MyServerComponent({ payload, locale }) {
|
||||||
|
const localizedPage = await payload.findByID({
|
||||||
|
collection: 'pages',
|
||||||
|
id: '123',
|
||||||
|
locale,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<p>{localizedPage.title}</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The best way to do this within a Client Component is to import the `useLocale` hook from `@payloadcms/ui`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React from 'react'
|
||||||
|
import { useLocale } from '@payloadcms/ui'
|
||||||
|
|
||||||
const Greeting: React.FC = () => {
|
const Greeting: React.FC = () => {
|
||||||
// highlight-start
|
const locale = useLocale() // highlight-line
|
||||||
const locale = useLocale()
|
|
||||||
// highlight-end
|
|
||||||
|
|
||||||
const trans = {
|
const trans = {
|
||||||
en: 'Hello',
|
en: 'Hello',
|
||||||
es: 'Hola',
|
es: 'Hola',
|
||||||
}
|
}
|
||||||
|
|
||||||
return <span> {trans[locale.code]} </span>
|
return (
|
||||||
|
<span>{trans[locale.code]}</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<Banner type="success">
|
||||||
|
See the [Hooks](./hooks) documentation for a full list of available hooks.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
#### Styling Custom Components
|
||||||
|
|
||||||
|
Payload has a robust [CSS Library](./customizing-css) that you can style your Custom Components similarly to Payload's built-in styling. This will ensure that your Custom Component matches the existing design system, and so that it automatically adapts to any theme changes.
|
||||||
|
|
||||||
|
To apply custom styles, simply import your own `.css` or `.scss` file into your Custom Component:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import './index.scss'
|
||||||
|
|
||||||
|
export const MyComponent: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className="my-component">
|
||||||
|
My Custom Component
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then to colorize your Custom Component's background, for example, you can use the following CSS:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
.my-component {
|
||||||
|
background-color: var(--theme-elevation-500);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Payload also exports its [SCSS](https://sass-lang.com) library for reuse which includes mixins, etc. To use this, simply import it as follows into your `.scss` file:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
@import '~payload/scss';
|
||||||
|
|
||||||
|
.my-component {
|
||||||
|
@include mid-break {
|
||||||
|
background-color: var(--theme-elevation-900);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
<Banner type="success">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
You can also drill into Payload's own component styles, or easily apply global, app-wide CSS. More on that [here](./customizing-css).
|
||||||
|
</Banner>
|
||||||
|
|||||||
@@ -2,50 +2,64 @@
|
|||||||
title: Customizing CSS & SCSS
|
title: Customizing CSS & SCSS
|
||||||
label: Customizing CSS
|
label: Customizing CSS
|
||||||
order: 60
|
order: 60
|
||||||
desc: Customize your Payload admin panel further by adding your own CSS or SCSS style sheet to the configuration, powerful theme and design options are waiting for you.
|
desc: Customize the Payload Admin Panel further by adding your own CSS or SCSS style sheet to the configuration, powerful theme and design options are waiting for you.
|
||||||
keywords: admin, css, scss, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
keywords: admin, css, scss, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||||
---
|
---
|
||||||
|
|
||||||
## Adding your own CSS / SCSS
|
Customizing the Payload [Admin Panel](./overview) through CSS alone is one of the easiest and most powerful ways to customize the look and feel of the dashboard. To allow for this level of customization, Payload:
|
||||||
|
|
||||||
You can add your own CSS by providing your base Payload config with a path to your own CSS or SCSS. Customize the styling of any part of the Payload dashboard as necessary.
|
1. Exposes a [root-level stylesheet](#global-css) for you to easily to inject custom selectors
|
||||||
|
1. Provides a [CSS library](#css-library) that can be easily overridden or extended
|
||||||
|
1. Uses [BEM naming conventions](http://getbem.com) so that class names are globally accessible
|
||||||
|
|
||||||
To do so, provide your base Payload config with a path to your own stylesheet. It can be either a CSS or SCSS file.
|
To customize the CSS within the Admin UI, determine scope and change you'd like to make, and then add your own CSS or SCSS to the configuration as needed.
|
||||||
|
|
||||||
**Example in payload.config.js:**
|
## Global CSS
|
||||||
|
|
||||||
```ts
|
Global CSS refers to the CSS that is applied to the entire [Admin Panel](./overview). This is where you can have a significant impact to the look and feel of the Admin UI through just a few lines of code.
|
||||||
import { buildConfig } from 'payload/config'
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
const config = buildConfig({
|
You can add your own global CSS through the root `custom.scss` file of your app. This file is loaded into the root of the Admin Panel and can be used to inject custom selectors or styles however needed.
|
||||||
admin: {
|
|
||||||
css: path.resolve(__dirname, 'relative/path/to/stylesheet.scss'),
|
Here is an example of how you might target the Dashboard View and change the background color:
|
||||||
},
|
|
||||||
})
|
```scss
|
||||||
|
.dashboard {
|
||||||
|
background-color: red; // highlight-line
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Overriding built-in styles
|
|
||||||
|
|
||||||
To make it as easy as possible for you to override our styles, Payload uses [BEM naming conventions](http://getbem.com/) for all CSS within the Admin UI. If you provide your own CSS, you can override any built-in styles easily.
|
|
||||||
|
|
||||||
In addition to adding your own style definitions, you can also override Payload's built-in CSS variables. We use as much as possible behind the scenes, and you can override any of them that you'd like to.
|
|
||||||
|
|
||||||
You can find the built-in Payload CSS variables within [`./src/admin/scss/app.scss`](https://github.com/payloadcms/payload/blob/main/packages/payload/src/admin/scss/app.scss) and [`./src/admin/scss/colors.scss`](https://github.com/payloadcms/payload/blob/main/packages/payload/src/admin/scss/colors.scss). The following variables are defined and can be overridden:
|
|
||||||
|
|
||||||
- Breakpoints
|
|
||||||
- Base color shades (white to black by default)
|
|
||||||
- Success / warning / error color shades
|
|
||||||
- Theme-specific colors (background, input background, text color, etc.)
|
|
||||||
- Elevation colors (used to determine how "bright" something should be when compared to the background)
|
|
||||||
- Fonts
|
|
||||||
- Horizontal gutter
|
|
||||||
|
|
||||||
### Dark mode
|
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
If you're overriding colors or theme elevations, make sure to consider how your changes will
|
<strong>Note:</strong>
|
||||||
affect dark mode.
|
If you are building [Custom Components](./overview), it is best to import your own stylesheets directly into your components, rather than using the global stylesheet. You can continue to use the [CSS library](#css-library) as needed.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
By default, Payload automatically overrides all `--theme-elevation`s and inverts all success / warning / error shades to suit dark mode. We also update some base theme variables like `--theme-bg`, `--theme-text`, etc.
|
## CSS Library
|
||||||
|
|
||||||
|
To make it as easy as possible for you to override default styles, Payload uses [BEM naming conventions](http://getbem.com/) for all CSS within the Admin UI. If you provide your own CSS, you can override any built-in styles easily, including targeting nested components and their various component states.
|
||||||
|
|
||||||
|
You can also override Payload's built-in [CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties). These variables are widely consumed by the Admin Panel, so modifying them has a significant impact on the look and feel of the Admin UI.
|
||||||
|
|
||||||
|
The following variables are defined and can be overridden:
|
||||||
|
|
||||||
|
- [Breakpoints](https://github.com/payloadcms/payload/blob/beta/packages/ui/src/scss/queries.scss)
|
||||||
|
- [Colors](https://github.com/payloadcms/payload/blob/beta/packages/ui/src/scss/colors.scss)
|
||||||
|
- Base color shades (white to black by default)
|
||||||
|
- Success / warning / error color shades
|
||||||
|
- Theme-specific colors (background, input background, text color, etc.)
|
||||||
|
- Elevation colors (used to determine how "bright" something should be when compared to the background)
|
||||||
|
- [Sizing](https://github.com/payloadcms/payload/blob/beta/packages/ui/src/scss/app.scss)
|
||||||
|
- Horizontal gutter
|
||||||
|
- Transition speeds
|
||||||
|
- Font sizes
|
||||||
|
- Etc.
|
||||||
|
|
||||||
|
For an up-to-date, comprehensive list of all available variables, please refer to the [Source Code](https://github.com/payloadcms/payload/blob/main/packages/ui/src/scss).
|
||||||
|
|
||||||
|
<Banner type="warning">
|
||||||
|
<strong>Warning:</strong>
|
||||||
|
If you're overriding colors or theme elevations, make sure to consider how [your changes will affect dark mode](#dark-mode).
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
#### Dark Mode
|
||||||
|
|
||||||
|
Colors are designed to automatically adapt to theme of the [Admin Panel](./overview). By default, Payload automatically overrides all `--theme-elevation` colors and inverts all success / warning / error shades to suit dark mode. We also update some base theme variables like `--theme-bg`, `--theme-text`, etc.
|
||||||
|
|||||||
@@ -1,27 +1,78 @@
|
|||||||
---
|
---
|
||||||
title: Environment Variables in Admin UI
|
title: Environment Variables in the Admin Panel
|
||||||
label: Environment Variables
|
label: Environment Variables
|
||||||
order: 100
|
order: 100
|
||||||
desc: NEEDS TO BE WRITTEN
|
desc: NEEDS TO BE WRITTEN
|
||||||
---
|
---
|
||||||
|
|
||||||
## Admin environment vars
|
Environment variables are a way to store sensitive information that your application needs to function. This could be anything from API keys to database credentials. Payload allows you to provide environment variables to your [Admin Panel](./overview) that can be accessed by your [Custom Components](./components) and [Custom Endpoints](../rest-api/overview#custom-endpoints).
|
||||||
|
|
||||||
|
For security and safety reasons, the Admin Panel not **not** include environment variables in client-side bundle by default. But, Payload provides a mechanism to expose environment variables to the client-side bundle when needed.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
<strong>Important:</strong>
|
<strong>Important:</strong>
|
||||||
<br />
|
<br />
|
||||||
Be careful about what variables you provide to your client-side code. Analyze every single one to
|
Be careful about what variables you provide to your client-side code. Analyze every single one to
|
||||||
make sure that you're not accidentally leaking anything that an attacker could exploit. Only keys
|
make sure that you're not accidentally leaking anything that an outside attacker could exploit. Only keys
|
||||||
that are safe for anyone to read in plain text should be provided to your Admin panel.
|
that are safe for anyone to read in plain text should be provided to your [Admin Panel](./overview).
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
By default, `env` variables are **not** provided to the Admin panel for security and safety reasons.
|
## Client-side Environments
|
||||||
But, Payload provides you with a way to still provide `env` vars to your frontend code.
|
|
||||||
|
|
||||||
**Payload will automatically supply any present `env` variables that are prefixed with `PAYLOAD_PUBLIC_` directly to the Admin panel.**
|
If you are building [Custom Components](./components) that are using Client Components and need to access environment variables from the client-side, you can do so by prefixing your environment variables with `NEXT_PUBLIC_`.
|
||||||
|
|
||||||
For example, if you've got the following environment variable:
|
For example, if you've got the following environment variable:
|
||||||
|
|
||||||
`PAYLOAD_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_XXXXXXXXXXXXXXXXXX`
|
```bash
|
||||||
|
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_XXXXXXXXXXXXXXXXXX
|
||||||
|
```
|
||||||
|
|
||||||
This key will automatically be made available to the Payload bundle and can be referenced in your Admin component code as `process.env.PAYLOAD_PUBLIC_STRIPE_PUBLISHABLE_KEY`.
|
This key will automatically be made available to the client-side Payload bundle and can be referenced in your Custom Component as follows:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const stripeKey = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
|
||||||
|
|
||||||
|
const MyClientComponent = () => {
|
||||||
|
// do something with the key
|
||||||
|
|
||||||
|
return (
|
||||||
|
<p>
|
||||||
|
My Client Component
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<Banner type="info">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
For more information on how to use environment variables in the [Admin Panel](./overview), see the [Next.js documentation](https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables).
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
## Server-side Environments
|
||||||
|
|
||||||
|
All [Custom Endpoints](../rest-api/overview#custom-endpoints) and [Custom Components](./components) that are Server Components are unaffected by this restriction and can access any environment variables you provide. For example, if you've got the following environment variable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
STRIPE_SECRET=sk_test_XXXXXXXXXXXXXXXXXX
|
||||||
|
```
|
||||||
|
|
||||||
|
This key will be available to your Server Components as follows:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const stripeSecret = process.env.STRIPE_SECRET
|
||||||
|
|
||||||
|
const MyServerComponent = async () => {
|
||||||
|
// do something with the secret
|
||||||
|
|
||||||
|
return (
|
||||||
|
<p>
|
||||||
|
My Server Component
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -21,17 +21,17 @@ All Payload fields support the ability to swap in your own React components. So,
|
|||||||
| Component | Description |
|
| Component | Description |
|
||||||
| ------------ | --------------------------------------------------------------------------------------------------------------------------- |
|
| ------------ | --------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`Filter`** | Override the text input that is presented in the `List` view when a user is filtering documents by the customized field. |
|
| **`Filter`** | Override the text input that is presented in the `List` view when a user is filtering documents by the customized field. |
|
||||||
| **`Cell`** | Used in the `List` view's table to represent a table-based preview of the data stored in the field. [More](#cell-component) |
|
| **`Cell`** | Used in the `List` view's table to represent a table-based preview of the data stored in the field. [More details](#cell-component).|
|
||||||
| **`Field`** | Swap out the field itself within all `Edit` views. [More](#field-component) |
|
| **`Field`** | Swap out the field itself within all `Edit` views. [More details](#field-component). |
|
||||||
|
|
||||||
As an alternative to replacing the entire Field component, you may want to keep the majority of the default Field component and only swap components within. This allows you to replace the **`Label`** or **`Error`** within a field component or add additional components inside the field with **`beforeInput`** or **`afterInput`**. **`beforeInput`** and **`afterInput`** are allowed in any fields that don't contain other fields, except [UI](/docs/fields/ui) and [Rich Text](/docs/fields/rich-text).
|
As an alternative to replacing the entire Field component, you may want to keep the majority of the default Field component and only swap components within. This allows you to replace the **`Label`** or **`Error`** within a field component or add additional components inside the field with **`beforeInput`** or **`afterInput`**. **`beforeInput`** and **`afterInput`** are allowed in any fields that don't contain other fields, except [UI](/docs/fields/ui) and [Rich Text](/docs/fields/rich-text).
|
||||||
|
|
||||||
| Component | Description |
|
| Component | Description |
|
||||||
| ----------------- | --------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | --------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`Label`** | Override the default Label in the Field Component. [More](#label-component) |
|
| **`Label`** | Override the default Label in the Field Component. [More details](#label-component). |
|
||||||
| **`Error`** | Override the default Label in the Field Component. [More](#error-component) |
|
| **`Error`** | Override the default Label in the Field Component. [More details](#error-component). |
|
||||||
| **`beforeInput`** | An array of elements that will be added before `input`/`textarea` elements. [More](#afterinput-and-beforeinput) |
|
| **`beforeInput`** | An array of elements that will be added before `input`/`textarea` elements. [More details](#afterinput-and-beforeinput).|
|
||||||
| **`afterInput`** | An array of elements that will be added after `input`/`textarea` elements. [More](#afterinput-and-beforeinput) |
|
| **`afterInput`** | An array of elements that will be added after `input`/`textarea` elements. [More details](#afterinput-and-beforeinput). |
|
||||||
|
|
||||||
## Cell Component
|
## Cell Component
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ These are the props that will be passed to your custom Cell to use in your own c
|
|||||||
| ---------------- | ----------------------------------------------------------------- |
|
| ---------------- | ----------------------------------------------------------------- |
|
||||||
| **`field`** | An object that includes the field configuration. |
|
| **`field`** | An object that includes the field configuration. |
|
||||||
| **`colIndex`** | A unique number for the column in the list. |
|
| **`colIndex`** | A unique number for the column in the list. |
|
||||||
| **`collection`** | An object with the config of the collection that the field is in. |
|
| **`collection`** | An object with the config of the Collection that the field is in. |
|
||||||
| **`cellData`** | The data for the field that the cell represents. |
|
| **`cellData`** | The data for the field that the cell represents. |
|
||||||
| **`rowData`** | An object with all the field values for the row. |
|
| **`rowData`** | An object with all the field values for the row. |
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ These are the props that will be passed to your custom Cell to use in your own c
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import type { Props } from 'payload/components/views/Cell'
|
import type { CellProps } from 'payload'
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
const baseClass = 'custom-cell'
|
const baseClass = 'custom-cell'
|
||||||
@@ -70,11 +70,12 @@ When writing your own custom components you can make use of a number of hooks to
|
|||||||
When swapping out the `Field` component, you'll be responsible for sending and receiving the field's `value` from the form itself. To do so, import the `useField` hook as follows:
|
When swapping out the `Field` component, you'll be responsible for sending and receiving the field's `value` from the form itself. To do so, import the `useField` hook as follows:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useField } from 'payload/components/forms'
|
'use client'
|
||||||
|
import { useField } from '@payloadcms/ui'
|
||||||
|
|
||||||
const CustomTextField: React.FC<{ path: string }> = ({ path }) => {
|
const CustomTextField: React.FC<{ path: string }> = ({ path }) => {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
const { value, setValue } = useField<string>({ path })
|
const { value, setValue } = useField({ path })
|
||||||
// highlight-end
|
// highlight-end
|
||||||
|
|
||||||
return <input onChange={(e) => setValue(e.target.value)} value={value} />
|
return <input onChange={(e) => setValue(e.target.value)} value={value} />
|
||||||
@@ -99,10 +100,10 @@ These are the props that will be passed to your custom Label.
|
|||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
|
'use client'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from '@payloadcms/ui'
|
||||||
|
import { getTranslation } from '@payloadcms/translations'
|
||||||
import { getTranslation } from 'payload/utilities/getTranslation'
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
htmlFor?: string
|
htmlFor?: string
|
||||||
@@ -164,7 +165,7 @@ With these properties you can add multiple components before and after the input
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Field } from 'payload/types'
|
import type { Field } from 'payload/types'
|
||||||
|
|
||||||
import './style.scss'
|
import './style.scss'
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,12 @@ desc: Make use of all of the powerful React hooks that Payload provides.
|
|||||||
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||||
---
|
---
|
||||||
|
|
||||||
Payload provides a variety of powerful hooks that can be used within your own React components. With them, you can interface with Payload itself and build just about any type of complex customization you can think of—directly in familiar React code.
|
Payload provides a variety of powerful [React Hooks](https://react.dev/reference/react-dom/hooks) that can be used within your own [Custom Components](./components), such as [Custom Fields](./fields). With them, you can interface with Payload itself and build just about any type of complex customization you can think of.
|
||||||
|
|
||||||
|
<Banner type="warning">
|
||||||
|
<strong>Reminder:</strong>
|
||||||
|
All Custom Components are [React Server Components](https://react.dev/reference/rsc/server-components) by default. Hooks, on the other hand, are only available in client-side environments. To use hooks, [ensure your component is a client component](./components#client-components).
|
||||||
|
</Banner>
|
||||||
|
|
||||||
## useField
|
## useField
|
||||||
|
|
||||||
@@ -15,41 +20,53 @@ The `useField` hook is used internally within every applicable Payload field com
|
|||||||
Outside of internal use, its most common use-case is in custom `Field` components. When you build a custom React `Field` component, you'll be responsible for sending and receiving the field's `value` from the form itself. To do so, import the `useField` hook as follows:
|
Outside of internal use, its most common use-case is in custom `Field` components. When you build a custom React `Field` component, you'll be responsible for sending and receiving the field's `value` from the form itself. To do so, import the `useField` hook as follows:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useField } from 'payload/components/forms'
|
'use client'
|
||||||
|
import { useField } from '@payloadcms/ui'
|
||||||
|
|
||||||
type Props = { path: string }
|
const CustomTextField: React.FC = ({ name }) => {
|
||||||
|
|
||||||
const CustomTextField: React.FC<Props> = ({ path }) => {
|
|
||||||
// highlight-start
|
// highlight-start
|
||||||
const { value, setValue } = useField<string>({ path })
|
const { value, setValue, path } = useField({ path: name })
|
||||||
// highlight-end
|
// highlight-end
|
||||||
|
|
||||||
return <input onChange={(e) => setValue(e.target.value)} value={value.path} />
|
return (
|
||||||
|
<input
|
||||||
|
onChange={(e) => setValue(e.target.value)}
|
||||||
|
value={value.path}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `useField` hook accepts an `args` object and sends back information and helpers for you to make use of:
|
The `useField` hook accepts the following arguments:
|
||||||
|
|
||||||
|
| Property | Description |
|
||||||
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `disableFormData` | If `true`, the field will not be included in the form data when the form is submitted. |
|
||||||
|
| `hasRows` | |
|
||||||
|
| `path` | If you do not provide a `path` or a `name`, this hook will look for one using the `useFieldPath` hook. |
|
||||||
|
| `validate` | If you do not provide a `validate` function, the field will be validated _on the client_ before submitting to the server. |
|
||||||
|
|
||||||
|
Here is what `useField` hook returns:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const field = useField<string>({
|
type FieldResult<T> = {
|
||||||
path: 'fieldPathHere', // required
|
errorMessage?: string
|
||||||
validate: myValidateFunc, // optional
|
errorPaths?: string[]
|
||||||
disableFormData?: false, // if true, the field's data will be ignored
|
filterOptions?: FilterOptionsResult
|
||||||
condition?: myConditionHere, // optional, used to skip validation if condition fails
|
formInitializing: boolean
|
||||||
})
|
formProcessing: boolean
|
||||||
|
formSubmitted: boolean
|
||||||
// Here is what `useField` sends back
|
initialValue?: T
|
||||||
const {
|
path: string
|
||||||
showError, // whether or not the field should show as errored
|
permissions: FieldPermissions
|
||||||
errorMessage, // the error message to show, if showError
|
readOnly?: boolean
|
||||||
value, // the current value of the field from the form
|
rows?: Row[]
|
||||||
formSubmitted, // if the form has been submitted
|
schemaPath: string
|
||||||
formProcessing, // if the form is currently processing
|
setValue: (val: unknown, disableModifyingForm?: boolean) => voi
|
||||||
setValue, // method to set the field's value in form state
|
showError: boolean
|
||||||
initialValue, // the initial value that the field mounted with
|
valid?: boolean
|
||||||
} = field;
|
value: T
|
||||||
|
}
|
||||||
// The rest of your component goes here
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## useFormFields
|
## useFormFields
|
||||||
@@ -66,7 +83,8 @@ Thanks to the awesome package [`use-context-selector`](https://github.com/dai-sh
|
|||||||
You can pass a Redux-like selector into the hook, which will ensure that you retrieve only the field that you want. The selector takes an argument with type of `[fields: Fields, dispatch: React.Dispatch<Action>]]`.
|
You can pass a Redux-like selector into the hook, which will ensure that you retrieve only the field that you want. The selector takes an argument with type of `[fields: Fields, dispatch: React.Dispatch<Action>]]`.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useFormFields } from 'payload/components/forms'
|
'use client'
|
||||||
|
import type { useFormFields } from '@payloadcms/ui'
|
||||||
|
|
||||||
const MyComponent: React.FC = () => {
|
const MyComponent: React.FC = () => {
|
||||||
// Get only the `amount` field state, and only cause a rerender when that field changes
|
// Get only the `amount` field state, and only cause a rerender when that field changes
|
||||||
@@ -88,7 +106,8 @@ const MyComponent: React.FC = () => {
|
|||||||
You can do lots of powerful stuff by retrieving the full form state, like using built-in helper functions to reduce field state to values only, or to retrieve sibling data by path.
|
You can do lots of powerful stuff by retrieving the full form state, like using built-in helper functions to reduce field state to values only, or to retrieve sibling data by path.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useAllFormFields, reduceFieldsToValues, getSiblingData } from 'payload/components/forms';
|
'use client'
|
||||||
|
import { useAllFormFields, reduceFieldsToValues, getSiblingData } from '@payloadcms/ui'
|
||||||
|
|
||||||
const ExampleComponent: React.FC = () => {
|
const ExampleComponent: React.FC = () => {
|
||||||
// the `fields` const will be equal to all fields' state,
|
// the `fields` const will be equal to all fields' state,
|
||||||
@@ -111,7 +130,7 @@ const ExampleComponent: React.FC = () => {
|
|||||||
|
|
||||||
#### Updating other fields' values
|
#### Updating other fields' values
|
||||||
|
|
||||||
If you are building a custom component, then you should use `setValue` which is returned from the `useField` hook to programmatically set your field's value. But if you're looking to update _another_ field's value, you can use `dispatchFields` returned from `useFormFields`.
|
If you are building a Custom Component, then you should use `setValue` which is returned from the `useField` hook to programmatically set your field's value. But if you're looking to update _another_ field's value, you can use `dispatchFields` returned from `useFormFields`.
|
||||||
|
|
||||||
You can send the following actions to the `dispatchFields` function.
|
You can send the following actions to the `dispatchFields` function.
|
||||||
|
|
||||||
@@ -141,7 +160,7 @@ The `useForm` hook can be used to interact with the form itself, and sends back
|
|||||||
up-to-date. They will be removed from this hook's response in an upcoming version.
|
up-to-date. They will be removed from this hook's response in an upcoming version.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
The `useForm` hook returns an object with the following properties: |
|
The `useForm` hook returns an object with the following properties:
|
||||||
|
|
||||||
<TableWithDrawers
|
<TableWithDrawers
|
||||||
columns={[
|
columns={[
|
||||||
@@ -394,7 +413,7 @@ export const CustomArrayManager = () => {
|
|||||||
}`}
|
}`}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>An example config to go along with the custom component</p>
|
<p>An example config to go along with the Custom Component</p>
|
||||||
<pre>
|
<pre>
|
||||||
{`const ExampleCollection = {
|
{`const ExampleCollection = {
|
||||||
slug: "example-collection",
|
slug: "example-collection",
|
||||||
@@ -491,7 +510,7 @@ export const CustomArrayManager = () => {
|
|||||||
}`}
|
}`}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>An example config to go along with the custom component</p>
|
<p>An example config to go along with the Custom Component</p>
|
||||||
<pre>
|
<pre>
|
||||||
{`const ExampleCollection = {
|
{`const ExampleCollection = {
|
||||||
slug: "example-collection",
|
slug: "example-collection",
|
||||||
@@ -601,7 +620,7 @@ export const CustomArrayManager = () => {
|
|||||||
}`}
|
}`}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>An example config to go along with the custom component</p>
|
<p>An example config to go along with the Custom Component</p>
|
||||||
<pre>
|
<pre>
|
||||||
{`const ExampleCollection = {
|
{`const ExampleCollection = {
|
||||||
slug: "example-collection",
|
slug: "example-collection",
|
||||||
@@ -639,19 +658,20 @@ export const CustomArrayManager = () => {
|
|||||||
|
|
||||||
The `useCollapsible` hook allows you to control parent collapsibles:
|
The `useCollapsible` hook allows you to control parent collapsibles:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ------------------------- | ------------------------------------------------------------------------------------------------------------ | --- |
|
| ------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`isCollapsed`** | State of the collapsible. `true` if open, `false` if collapsed |
|
| **`isCollapsed`** | State of the collapsible. `true` if open, `false` if collapsed. |
|
||||||
| **`isVisible`** | If nested, determine if the nearest collapsible is visible. `true` if no parent is closed, `false` otherwise |
|
| **`isVisible`** | If nested, determine if the nearest collapsible is visible. `true` if no parent is closed, `false` otherwise. |
|
||||||
| **`toggle`** | Toggles the state of the nearest collapsible |
|
| **`toggle`** | Toggles the state of the nearest collapsible. |
|
||||||
| **`isWithinCollapsible`** | Determine when you are within another collaspible | |
|
| **`isWithinCollapsible`** | Determine when you are within another collapsible. |
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
|
'use client'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { useCollapsible } from 'payload/components/utilities'
|
import { useCollapsible } from '@payloadcms/ui'
|
||||||
|
|
||||||
const CustomComponent: React.FC = () => {
|
const CustomComponent: React.FC = () => {
|
||||||
const { isCollapsed, toggle } = useCollapsible()
|
const { isCollapsed, toggle } = useCollapsible()
|
||||||
@@ -673,8 +693,8 @@ The `useDocumentInfo` hook provides lots of information about the document curre
|
|||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
| ------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||||
| **`collection`** | If the doc is a collection, its collection config will be returned |
|
| **`collection`** | If the doc is a collection, its Collection Config will be returned |
|
||||||
| **`global`** | If the doc is a global, its global config will be returned |
|
| **`global`** | If the doc is a global, its Global Config will be returned |
|
||||||
| **`id`** | If the doc is a collection, its ID will be returned |
|
| **`id`** | If the doc is a collection, its ID will be returned |
|
||||||
| **`preferencesKey`** | The `preferences` key to use when interacting with document-level user preferences |
|
| **`preferencesKey`** | The `preferences` key to use when interacting with document-level user preferences |
|
||||||
| **`versions`** | Versions of the current doc |
|
| **`versions`** | Versions of the current doc |
|
||||||
@@ -687,7 +707,8 @@ The `useDocumentInfo` hook provides lots of information about the document curre
|
|||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useDocumentInfo } from 'payload/components/utilities'
|
'use client'
|
||||||
|
import { useDocumentInfo } from '@payloadcms/ui'
|
||||||
|
|
||||||
const LinkFromCategoryToPosts: React.FC = () => {
|
const LinkFromCategoryToPosts: React.FC = () => {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
@@ -709,10 +730,11 @@ const LinkFromCategoryToPosts: React.FC = () => {
|
|||||||
|
|
||||||
## useLocale
|
## useLocale
|
||||||
|
|
||||||
In any custom component you can get the selected locale object with the `useLocale` hook. `useLocale`gives you the full locale object, consisting of a `label`, `rtl`(right-to-left) property, and then `code`. Here is a simple example:
|
In any Custom Component you can get the selected locale object with the `useLocale` hook. `useLocale`gives you the full locale object, consisting of a `label`, `rtl`(right-to-left) property, and then `code`. Here is a simple example:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useLocale } from 'payload/components/utilities'
|
'use client'
|
||||||
|
import { useLocale } from '@payloadcms/ui'
|
||||||
|
|
||||||
const Greeting: React.FC = () => {
|
const Greeting: React.FC = () => {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
@@ -743,8 +765,9 @@ Useful to retrieve info about the currently logged in user as well as methods fo
|
|||||||
| **`permissions`** | The permissions of the current user |
|
| **`permissions`** | The permissions of the current user |
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useAuth } from 'payload/components/utilities'
|
'use client'
|
||||||
import { User } from '../payload-types.ts'
|
import { useAuth } from '@payloadcms/ui'
|
||||||
|
import type { User } from '../payload-types.ts'
|
||||||
|
|
||||||
const Greeting: React.FC = () => {
|
const Greeting: React.FC = () => {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
@@ -757,10 +780,11 @@ const Greeting: React.FC = () => {
|
|||||||
|
|
||||||
## useConfig
|
## useConfig
|
||||||
|
|
||||||
Used to easily fetch the full Payload config.
|
Used to easily fetch the Payload Client Config.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useConfig } from 'payload/components/utilities'
|
'use client'
|
||||||
|
import { useConfig } from '@payloadcms/ui'
|
||||||
|
|
||||||
const MyComponent: React.FC = () => {
|
const MyComponent: React.FC = () => {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
@@ -776,7 +800,8 @@ const MyComponent: React.FC = () => {
|
|||||||
Sends back how many editing levels "deep" the current component is. Edit depth is relevant while adding new documents / editing documents in modal windows and other cases.
|
Sends back how many editing levels "deep" the current component is. Edit depth is relevant while adding new documents / editing documents in modal windows and other cases.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useEditDepth } from 'payload/components/utilities'
|
'use client'
|
||||||
|
import { useEditDepth } from '@payloadcms/ui'
|
||||||
|
|
||||||
const MyComponent: React.FC = () => {
|
const MyComponent: React.FC = () => {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
@@ -796,7 +821,8 @@ Returns methods to set and get user preferences. More info can be found [here](h
|
|||||||
Returns the currently selected theme (`light`, `dark` or `auto`), a set function to update it and a boolean `autoMode`, used to determine if the theme value should be set automatically based on the user's device preferences.
|
Returns the currently selected theme (`light`, `dark` or `auto`), a set function to update it and a boolean `autoMode`, used to determine if the theme value should be set automatically based on the user's device preferences.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useTheme } from 'payload/components/utilities'
|
'use client'
|
||||||
|
import { useTheme } from '@payloadcms/ui'
|
||||||
|
|
||||||
const MyComponent: React.FC = () => {
|
const MyComponent: React.FC = () => {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
@@ -824,7 +850,8 @@ const MyComponent: React.FC = () => {
|
|||||||
Returns methods to manipulate table columns
|
Returns methods to manipulate table columns
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useTableColumns } from 'payload/components/hooks'
|
'use client'
|
||||||
|
import { useTableColumns } from '@payloadcms/ui'
|
||||||
|
|
||||||
const MyComponent: React.FC = () => {
|
const MyComponent: React.FC = () => {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
@@ -855,7 +882,8 @@ The `useDocumentEvents` hook provides a way of subscribing to cross-document eve
|
|||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useDocumentEvents } from 'payload/components/hooks'
|
'use client'
|
||||||
|
import { useDocumentEvents } from '@payloadcms/ui'
|
||||||
|
|
||||||
const ListenForUpdates: React.FC = () => {
|
const ListenForUpdates: React.FC = () => {
|
||||||
const { mostRecentUpdate } = useDocumentEvents()
|
const { mostRecentUpdate } = useDocumentEvents()
|
||||||
|
|||||||
@@ -2,18 +2,18 @@
|
|||||||
title: The Admin Panel
|
title: The Admin Panel
|
||||||
label: Overview
|
label: Overview
|
||||||
order: 10
|
order: 10
|
||||||
desc: Manage your data and customize the Admin Panel by swapping in your own React components. Create, modify or remove views, fields, styles and much more.
|
desc: Manage your data and customize the Payload Admin Panel by swapping in your own React components. Create, modify or remove views, fields, styles and much more.
|
||||||
keywords: admin, components, custom, customize, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
keywords: admin, components, custom, customize, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||||
---
|
---
|
||||||
|
|
||||||
Payload dynamically generates a beautiful, fully functional Admin Panel to manage your users and data. The Payload Admin Panel is highly performant, even with 100+ fields, and is written fully in TypeScript. It is built with [React](https://react.dev) using the [Next.js App Router](https://nextjs.org/docs/app) and fully supports [React Server Components](https://react.dev/reference/rsc/server-components) which enables the use of the [Local API](/docs/local-api/overview) on the front-end.
|
Payload dynamically generates a beautiful, [fully type-safe](../typescript/overview) admin panel to manage your users and data. It is highly performant, even with 100+ fields, and is translated in over 30 languages. Within the Admin Panel you can manage content, [render your site](../live-preview/overview), preview drafts, [diff versions](../versions/overview), and so much more.
|
||||||
|
|
||||||
You can endlessly customize and extend the Admin UI by swapping your own in [Custom Components](./components) for everything from field labels to entire views. You can also modify built-in views, build your own fields, [swap out Payload branding for your own](https://payloadcms.com/blog/white-label-admin-ui), and so much more.
|
The Admin Panel is designed to [white-label your brand](https://payloadcms.com/blog/white-label-admin-ui). You can endlessly customize and extend the Admin UI by swapping in your own [Custom Components](./components)—everything from simple field labels to entire views can be modified or replaced to meet the needs of your editors.
|
||||||
|
|
||||||
|
The Admin Panel is written in [TypeScript](https://www.typescriptlang.org) and built with [React](https://react.dev) using the [Next.js App Router](https://nextjs.org/docs/app). It supports [React Server Components](https://react.dev/reference/rsc/server-components) and the use of the [Local API](/docs/local-api/overview) on the front-end. You can install Payload into any [existing Next.js app in just one line](../getting-started/installation) and [deploy it anywhere](../production).
|
||||||
|
|
||||||
<Banner type="success">
|
<Banner type="success">
|
||||||
The Admin Panel is meant to be simple enough to give you a starting point but not bring too much
|
The Payload Admin Panel is designed to be as minimal and straightforward as possible to allow easy customization and control. [Learn more](./components).
|
||||||
complexity, so that you can easily customize it to suit the needs of your application and your
|
|
||||||
editors.
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
<LightDarkImage
|
<LightDarkImage
|
||||||
@@ -23,106 +23,209 @@ You can endlessly customize and extend the Admin UI by swapping your own in [Cus
|
|||||||
caption="Redesigned Admin Panel with a collapsible sidebar that's open by default, providing greater extensibility and enhanced horizontal real estate."
|
caption="Redesigned Admin Panel with a collapsible sidebar that's open by default, providing greater extensibility and enhanced horizontal real estate."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
The Admin Panel serves as the entire HTTP layer for Payload, providing a full CRUD interface for your app. This means that both the [REST](../rest-api/overview) and [GraphQL](../graphql/overview) APIs are Next.js routes that exist directly alongside your front-end application.
|
||||||
|
|
||||||
|
Once you [install Payload](../getting-started/installation), the following files and directories will be created in your app:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
app/
|
||||||
|
├─ (payload)/
|
||||||
|
├── admin/
|
||||||
|
├─── [[...segments]]/
|
||||||
|
├──── page.tsx
|
||||||
|
├──── not-found.tsx
|
||||||
|
├── api/
|
||||||
|
├─── [...slug]/
|
||||||
|
├──── route.ts
|
||||||
|
├── graphql/
|
||||||
|
├──── route.ts
|
||||||
|
├── graphql-playground/
|
||||||
|
├──── route.ts
|
||||||
|
├── custom.scss
|
||||||
|
├── layout.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
<Banner type="info">
|
||||||
|
If you are not familiar with Next.js project structure, you can [learn more about it here](https://nextjs.org/docs/getting-started/project-structure).
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
As shown above, all Payload routes are nested within the `(payload)` route group. This creates a boundary between the Admin Panel and the rest of your application by scoping all layouts and styles. The `layout.tsx` file within this directory, for example, is where Payload manages the `html` tag of the document to set proper `lang` and `dir` attributes, etc.
|
||||||
|
|
||||||
|
The `admin` directory contains all the _pages_ related to the interface itself, and the `api` and `graphql` directories contains all the _routes_ related to the [REST API](../rest-api/overview) and [GraphQL API](../graphql/overview). All admin routes are [easily configurable](#customizing-routes) to meet your application's requirements.
|
||||||
|
|
||||||
|
Finally, the `custom.scss` file is where you can add or override globally-oriented styles in the Admin Panel, such as the color palette. Customizing the look and feel through CSS alone is a powerful feature of the Admin Panel, [more on that here](./customizing-css).
|
||||||
|
|
||||||
|
All auto-generated files will contain the following comments at the top of each file:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */,
|
||||||
|
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||||
|
```
|
||||||
|
|
||||||
## Admin Options
|
## Admin Options
|
||||||
|
|
||||||
All high-level options for the Admin Panel are defined in your Payload config under the `admin` key:
|
All options for the Admin Panel are defined in your [Payload Config](../configuration/overview) under the `admin` key.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { buildConfig } from 'payload'
|
||||||
|
|
||||||
|
const config = buildConfig({
|
||||||
|
// ...
|
||||||
|
admin: { // highlight-line
|
||||||
|
// ...
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The following options are available for the Admin Panel:
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `user` | The `slug` of a Collection that you want to be used to log in to the Admin Panel. [More](/docs/admin/overview#the-admin-user-collection) |
|
| `user` | The `slug` of the Collection that you want to allow to login to the Admin Panel. [More details](#the-admin-user-collection). |
|
||||||
| `buildPath` | Specify an absolute path for where to store the built Admin bundle used in production. Defaults to `path.resolve(process.cwd(), 'build')`. |
|
| `buildPath` | Specify an absolute path for where to store the built Admin bundle used in production. Defaults to `path.resolve(process.cwd(), 'build')`. |
|
||||||
| `meta` | Base meta data to use for the Admin Panel. Included properties are `titleSuffix`, `icons`, and `openGraph`. Can be overridden on a per collection or per global basis. |
|
| `meta` | Base metadata to use for the Admin Panel. Included properties are `titleSuffix`, `icons`, and `openGraph`. Can be overridden on a per Collection or per Global basis. |
|
||||||
| `disable` | If set to `true`, the entire Admin Panel will be disabled. |
|
| `disable` | If set to `true`, the entire Admin Panel will be disabled. |
|
||||||
| `dateFormat` | Global date format that will be used for all dates in the Admin Panel. Any valid [date-fns](https://date-fns.org/) format pattern can be used. |
|
| `dateFormat` | The date format that will be used for all dates within the Admin Panel. Any valid [date-fns](https://date-fns.org/) format pattern can be used. |
|
||||||
| `avatar` | Set account profile picture. Options: `gravatar`, `default` or a custom React component. |
|
| `avatar` | Set account profile picture. Options: `gravatar`, `default` or a custom React component. |
|
||||||
| `autoLogin` | Used to automate admin log-in for dev and demonstration convenience. [More](/docs/authentication/config). |
|
| `autoLogin` | Used to automate admin log-in for dev and demonstration convenience. [More details](../authentication/config). |
|
||||||
| `livePreview` | Enable real-time editing for instant visual feedback of your front-end application. [More](/docs/live-preview/overview). |
|
| `livePreview` | Enable real-time editing for instant visual feedback of your front-end application. [More details](../live-preview/overview). |
|
||||||
| `components` | Component overrides that affect the entirety of the Admin Panel. [More](/docs/admin/components) |
|
| `components` | Component overrides that affect the entirety of the Admin Panel. [More details](./components). |
|
||||||
| `routes` | Replace built-in Admin Panel routes with your own custom routes. [More](#custom-admin-panel-routes) |
|
| `routes` | Replace built-in Admin Panel routes with your own custom routes. [More details](#customizing-routes). |
|
||||||
|
| `custom` | Any custom properties you wish to pass to the Admin Panel. |
|
||||||
|
|
||||||
|
<Banner type="success">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
These are the _root-level_ options for the Admin Panel. You can also customize the admin options of any Collection or Global through their respective `admin` keys.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
### The Admin User Collection
|
### The Admin User Collection
|
||||||
|
|
||||||
<Banner type="warning">
|
To specify which Collection to allow to login to the Admin Panel, pass the `admin.user` key equal to the slug of any auth-enabled Collection:
|
||||||
<strong>Important:</strong>
|
|
||||||
<br />
|
|
||||||
The Admin Panel can only be used by a single auth-enabled Collection. To enable authentication for a Collection, simply set `auth: true` in the Collection's configuration. See [Authentication](/docs/authentication/overview) for more information.
|
|
||||||
</Banner>
|
|
||||||
|
|
||||||
To specify which Collection to allow to login to the Admin Panel, pass the `admin.user` key equal to the slug of any auth-enabled Collection. See [Authentication](/docs/authentication/overview) for more information.
|
|
||||||
|
|
||||||
`payload.config.js`:
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { buildConfig } from 'payload/config'
|
import { buildConfig } from 'payload'
|
||||||
|
|
||||||
const config = buildConfig({
|
const config = buildConfig({
|
||||||
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
user: 'admins', // highlight-line
|
user: 'admins', // highlight-line
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="info">
|
|
||||||
By default, if you have not specified a Collection, Payload will automatically provide a `User` Collection with access the Admin Panel. You can customize or override the fields and settings of the default `User` Collection by adding your own Collection with `slug: 'users'`. Doing this will force Payload to use your provided `User` Collection instead of its default version.
|
|
||||||
</Banner>
|
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
<strong>Note:</strong>
|
<strong>Important:</strong>
|
||||||
<br />
|
<br />
|
||||||
You can use whatever Collection you'd like to access the Admin Panel as long as the Collection supports [Authentication](/docs/authentication/overview). It doesn't need to be called `users`. For example, you could use a Collection called `admins` or `editors` instead.
|
The Admin Panel can only be used by a single auth-enabled Collection. To enable authentication for a Collection, simply set `auth: true` in the Collection's configuration. See [Authentication](../authentication/overview) for more information.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
For example, you may wish to have two Collections that both support Authentication:
|
By default, if you have not specified a Collection, Payload will automatically provide a `User` Collection with access to the Admin Panel. You can customize or override the fields and settings of the default `User` Collection by adding your own Collection with `slug: 'users'`. Doing this will force Payload to use your provided `User` Collection instead of its default version.
|
||||||
|
|
||||||
|
You can use whatever Collection you'd like to access the Admin Panel as long as the Collection supports [Authentication](/docs/authentication/overview). It doesn't need to be called `users`. For example, you may wish to have two Collections that both support authentication:
|
||||||
|
|
||||||
- `admins` - meant to have a higher level of permissions to manage your data and access the Admin Panel
|
- `admins` - meant to have a higher level of permissions to manage your data and access the Admin Panel
|
||||||
- `customers` - meant for end users of your app that should not be allowed to log into the Admin Panel
|
- `customers` - meant for end users of your app that should not be allowed to log into the Admin Panel
|
||||||
|
|
||||||
This is totally possible. For the above scenario, by specifying `admin: { user: 'admins' }`, your Admin Panel will use `admins`. Any users logged in as `customers` will not be able to log in via the Admin Panel.
|
To do this, specify `admin: { user: 'admins' }` in your config. This will provide access to the Admin Panel to only `admins`. Any users authenticated as `customers` will be prevented from accessing the Admin Panel. See [Access Control](/docs/access-control/overview) for full details. For a complete, working example of role-based access control, check out the official [Auth Example](https://github.com/payloadcms/payload/tree/main/examples/auth/payload).
|
||||||
|
|
||||||
### Restricting user access
|
#### Role-based access control
|
||||||
|
|
||||||
It is also possible to allow _multiple admin user types_ into the Admin Panel with limited permissions. To do this, add a `roles` or similar field to your auth-enabled Collection and use the `access.admin` property to limit access. See [Access Control](/docs/access-control/overview) for full details. For a working example, check out the [Auth Example](https://github.com/payloadcms/payload/tree/main/examples/auth/payload).
|
It is also possible to allow multiple user types into the Admin Panel with limited permissions. For example, you may wish to have two roles within the `admins` Collection:
|
||||||
|
|
||||||
### I18n
|
- `super-admin` - full access to the Admin Panel to perform any action
|
||||||
|
- `editor` - limited access to the Admin Panel to only manage content
|
||||||
|
|
||||||
The Payload Admin Panel is translated in over 30 languages and counting. Languages are automatically detected based on the user's browser and all text displays in that language. If no language was detected, or if the user's language is not yet supported, English will be chosen. Users can easily specify their language by selecting one from their account page. See [I18n](../configuration/i18n) for more information.
|
To do this, add a `roles` or similar field to your auth-enabled Collection, then use the `access.admin` property to grant or deny access based on the value of that field. See [Access Control](/docs/access-control/overview) for full details. For a complete, working example of role-based access control, check out the official [Auth Example](https://github.com/payloadcms/payload/tree/main/examples/auth/payload).
|
||||||
|
|
||||||
<Banner>
|
## Customizing Routes
|
||||||
<strong>Note:</strong>
|
|
||||||
<br />
|
|
||||||
If there is a language that Payload does not yet support, we accept code
|
|
||||||
[contributions](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md).
|
|
||||||
</Banner>
|
|
||||||
|
|
||||||
### Light and dark modes
|
You have full control over the routes that Payload binds itself to. This includes both root-level routes such as the REST API, and admin-level routes such as the user's account page. You can customize these routes to meet the needs of your application simply by specifying the desired paths in your config.
|
||||||
|
|
||||||
Users in the Admin Panel have access to choosing between light mode and dark mode for their editing experience. The setting is managed while logged into the admin UI within the user account page and will be stored with the browser. By default, the operating system preference is detected and used.
|
#### Root-level Routes
|
||||||
|
|
||||||
### Custom admin panel routes
|
Root-level routes are those that are not behind the `/admin` path, such as the REST API and GraphQL APIs, or the root path of the Admin Panel itself.
|
||||||
|
|
||||||
You can configure custom routes in the Admin Panel for the following routes:
|
Here is an example of how you might modify root-level routes:
|
||||||
|
|
||||||
| Option | Default route |
|
|
||||||
| ----------------- | ----------------------- |
|
|
||||||
| `account` | `/account` |
|
|
||||||
| `createFirstUser` | `/create-first-user` |
|
|
||||||
| `forgot` | `/forgot` |
|
|
||||||
| `inactivity` | `/logout-inactivity` |
|
|
||||||
| `login` | `/login` |
|
|
||||||
| `logout` | `/logout` |
|
|
||||||
| `reset` | `/reset` |
|
|
||||||
| `unauthorized` | `/unauthorized` |
|
|
||||||
|
|
||||||
`payload.config.js`:
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { buildConfig } from 'payload/config'
|
import { buildConfig } from 'payload'
|
||||||
|
|
||||||
const config = buildConfig({
|
const config = buildConfig({
|
||||||
|
// ...
|
||||||
|
routes: {
|
||||||
|
admin: '/custom-admin-route' // highlight-line
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
You can configure custom paths for the following root-level routes through the `routes` property of your [Payload Config](../configuration/overview):
|
||||||
|
|
||||||
|
| Option | Default route | Description |
|
||||||
|
| ------------------ | ----------------------- | ------------------------------------- |
|
||||||
|
| `admin` | `/admin` | The Admin Panel itself. |
|
||||||
|
| `api` | `/api` | The REST API base path. |
|
||||||
|
| `graphQL` | `/graphql` | The GraphQL API base path. |
|
||||||
|
| `graphQLPlayground`| `/graphql-playground` | The GraphQL Playground. |
|
||||||
|
|
||||||
|
<Banner type="warning">
|
||||||
|
<strong>Reminder:</strong>
|
||||||
|
The `routes` key is defined in the _top-level_ of your [Payload Config](../configuration/overview), _outside_ the `admin` key. To customize the Admin Panel routes, use [admin-level routes](#admin-level-routes) instead.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
<Banner type="success">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
You can easily add _new_ routes to the Admin Panel through the `endpoints` property of the Payload Config. See [Custom Endpoints](../rest-api/overview#custom-endpoints) for more information.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
#### Admin-level Routes
|
||||||
|
|
||||||
|
Admin-level routes are those behind the `/admin` path. These are the routes that are part of the Admin Panel itself, such as the user's account page, the login page, etc.
|
||||||
|
|
||||||
|
Here is an example of how you might modify admin-level routes:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { buildConfig } from 'payload'
|
||||||
|
|
||||||
|
const config = buildConfig({
|
||||||
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
routes: {
|
routes: {
|
||||||
admin: '/custom-admin-route'
|
account: '/my-account' // highlight-line
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can configure custom paths for the following admin-level routes through the `admin.routes` property of your [Payload Config](../configuration/overview):
|
||||||
|
|
||||||
|
| Option | Default route | Description |
|
||||||
|
| ----------------- | ----------------------- | ----------------------------------------------- |
|
||||||
|
| `account` | `/account` | The user's account page. |
|
||||||
|
| `createFirstUser` | `/create-first-user` | The page to create the first user. |
|
||||||
|
| `forgot` | `/forgot` | The password reset page. |
|
||||||
|
| `inactivity` | `/logout-inactivity` | The page to redirect to after inactivity. |
|
||||||
|
| `login` | `/login` | The login page. |
|
||||||
|
| `logout` | `/logout` | The logout page. |
|
||||||
|
| `reset` | `/reset` | The password reset page. |
|
||||||
|
| `unauthorized` | `/unauthorized` | The unauthorized page. |
|
||||||
|
|
||||||
|
<Banner type="success">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
You can also swap out entire _views_ out for your own, using the `admin.views` property of the Payload Config. See [Custom Views](./views) for more information.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
## I18n
|
||||||
|
|
||||||
|
The Payload Admin Panel is translated in over [30 languages and counting](https://github.com/payloadcms/payload/tree/beta/packages/translations). Languages are automatically detected based on the user's browser and used by the Admin Panel to display all text in that language. If no language was detected, or if the user's language is not yet supported, English will be chosen. Users can easily specify their language by selecting one from their account page. See [I18n](../configuration/i18n) for more information.
|
||||||
|
|
||||||
|
<Banner>
|
||||||
|
<strong>Note:</strong>
|
||||||
|
If there is a language that Payload does not yet support, we accept code
|
||||||
|
[contributions](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md).
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
## Light and Dark Modes
|
||||||
|
|
||||||
|
Users in the Admin Panel have the ability to choose between light mode and dark mode for their editing experience. Users can select their preferred theme from their account page. Once selected, it is saved to their user's preferences and persisted across sessions and devices. If no theme was selected, the Admin Panel will automatically detect the operation system's theme and use that as the default.
|
||||||
|
|||||||
@@ -2,17 +2,18 @@
|
|||||||
title: Managing User Preferences
|
title: Managing User Preferences
|
||||||
label: Preferences
|
label: Preferences
|
||||||
order: 50
|
order: 50
|
||||||
desc: Store the preferences of your users as they interact with the Admin panel.
|
desc: Store the preferences of your users as they interact with the Admin Panel.
|
||||||
keywords: admin, preferences, custom, customize, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
keywords: admin, preferences, custom, customize, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||||
---
|
---
|
||||||
|
|
||||||
As your users interact with your Admin panel, you might want to store their preferences in a persistent manner, so that when they revisit the Admin panel, they can pick right back up where they left off.
|
As your users interact with the [Admin Panel](./overview), you might want to store their preferences in a persistent manner, so that when they revisit the Admin Panel in a different session or from a different device, they can pick right back up where they left off.
|
||||||
|
|
||||||
Out of the box, Payload handles the persistence of your users' preferences in a handful of ways, including:
|
Out of the box, Payload handles the persistence of your users' preferences in a handful of ways, including:
|
||||||
|
|
||||||
1. Collection `List` view active columns, and their order, that users define
|
1. Columns in the Collection List View: their active state and order
|
||||||
1. Their last active locale
|
1. The user's last active [Locale](../configuration/localization)
|
||||||
1. The "collapsed" state of blocks, on a document level, as users edit or interact with documents
|
1. The "collapsed" state of `blocks`, `array`, and `collapsible` fields
|
||||||
|
1. The last-known state of the `Nav` component, etc.
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
<strong>Important:</strong>
|
<strong>Important:</strong>
|
||||||
@@ -23,7 +24,7 @@ Out of the box, Payload handles the persistence of your users' preferences in a
|
|||||||
|
|
||||||
## Use cases
|
## Use cases
|
||||||
|
|
||||||
This API is used significantly for internal operations of the Admin panel, as mentioned above. But, if you're building your own React components for use in the Admin panel, you can allow users to set their own preferences in correspondence to their usage of your components. For example:
|
This API is used significantly for internal operations of the Admin Panel, as mentioned above. But, if you're building your own React components for use in the Admin Panel, you can allow users to set their own preferences in correspondence to their usage of your components. For example:
|
||||||
|
|
||||||
- If you have built a "color picker", you could "remember" the last used colors that the user has set for easy access next time
|
- If you have built a "color picker", you could "remember" the last used colors that the user has set for easy access next time
|
||||||
- If you've built a custom `Nav` component, and you've built in an "accordion-style" UI, you might want to store the `collapsed` state of each Nav collapsible item. This way, if an editor returns to the panel, their `Nav` state is persisted automatically
|
- If you've built a custom `Nav` component, and you've built in an "accordion-style" UI, you might want to store the `collapsed` state of each Nav collapsible item. This way, if an editor returns to the panel, their `Nav` state is persisted automatically
|
||||||
@@ -32,14 +33,14 @@ This API is used significantly for internal operations of the Admin panel, as me
|
|||||||
|
|
||||||
## Database
|
## Database
|
||||||
|
|
||||||
Payload automatically creates an internally used `payload-preferences` collection that stores user preferences. Each document in the `payload-preferences` collection contains the following shape:
|
Payload automatically creates an internally used `payload-preferences` Collection that stores user preferences. Each document in the `payload-preferences` Collection contains the following shape:
|
||||||
|
|
||||||
| Key | Value |
|
| Key | Value |
|
||||||
| ----------------- | ----------------------------------------------------------------- |
|
| ----------------- | ----------------------------------------------------------------- |
|
||||||
| `id` | A unique ID for each preference stored. |
|
| `id` | A unique ID for each preference stored. |
|
||||||
| `key` | A unique `key` that corresponds to the preference. |
|
| `key` | A unique `key` that corresponds to the preference. |
|
||||||
| `user.value` | The ID of the `user` that is storing its preference. |
|
| `user.value` | The ID of the `user` that is storing its preference. |
|
||||||
| `user.relationTo` | The `slug` of the collection that the `user` is logged in as. |
|
| `user.relationTo` | The `slug` of the Collection that the `user` is logged in as. |
|
||||||
| `value` | The value of the preference. Can be any data shape that you need. |
|
| `value` | The value of the preference. Can be any data shape that you need. |
|
||||||
| `createdAt` | A timestamp of when the preference was created. |
|
| `createdAt` | A timestamp of when the preference was created. |
|
||||||
| `updatedAt` | A timestamp set to the last time the preference was updated. |
|
| `updatedAt` | A timestamp set to the last time the preference was updated. |
|
||||||
@@ -50,7 +51,7 @@ Preferences are available to both [GraphQL](/docs/graphql/overview#preferences)
|
|||||||
|
|
||||||
## Adding or reading Preferences in your own components
|
## Adding or reading Preferences in your own components
|
||||||
|
|
||||||
The Payload admin panel offers a `usePreferences` hook. The hook is only meant for use within the admin panel itself. It provides you with two methods:
|
The Payload Admin Panel offers a `usePreferences` hook. The hook is only meant for use within the Admin Panel itself. It provides you with two methods:
|
||||||
|
|
||||||
#### `getPreference`
|
#### `getPreference`
|
||||||
|
|
||||||
@@ -71,11 +72,12 @@ Also async, this method provides you with an easy way to set a user preference.
|
|||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
Here is an example for how you can utilize `usePreferences` within your custom Admin panel components. Note - this example is not fully useful and is more just a reference for how to utilize the Preferences API. In this case, we are demonstrating how to set and retrieve a user's last used colors history within a `ColorPicker` or similar type component.
|
Here is an example for how you can utilize `usePreferences` within your custom Admin Panel components. Note - this example is not fully useful and is more just a reference for how to utilize the Preferences API. In this case, we are demonstrating how to set and retrieve a user's last used colors history within a `ColorPicker` or similar type component.
|
||||||
|
|
||||||
```
|
```tsx
|
||||||
|
'use client'
|
||||||
import React, { Fragment, useState, useEffect, useCallback } from 'react';
|
import React, { Fragment, useState, useEffect, useCallback } from 'react';
|
||||||
import { usePreferences } from 'payload/components/preferences';
|
import { usePreferences } from '@payloadcms/ui'
|
||||||
|
|
||||||
const lastUsedColorsPreferenceKey = 'last-used-colors';
|
const lastUsedColorsPreferenceKey = 'last-used-colors';
|
||||||
|
|
||||||
|
|||||||
@@ -6,32 +6,45 @@ desc:
|
|||||||
keywords:
|
keywords:
|
||||||
---
|
---
|
||||||
|
|
||||||
### Root
|
Views are the individual pages that make up the [Admin Panel](./overview), such as the Dashboard, List, and Edit views. One of the most powerful ways to customize the Admin Panel is to create Custom Views. These are [Custom Components](./components) that can either replace built-in ones or be entirely new.
|
||||||
|
|
||||||
You can easily swap entire views with your own by using the `admin.components.views` property. At the root level, Payload renders the following views by default, all of which can be overridden:
|
To swap in your own Custom Views, consult the list of available components below. Determine the scope that corresponds to what you are trying to accomplish, then [author your React component(s)](#building-custom-views) accordingly.
|
||||||
|
|
||||||
|
There are four types of views in Payload:
|
||||||
|
|
||||||
|
- [Root Views](#custom-root-views)
|
||||||
|
- [Collection Views](#custom-collection-views)
|
||||||
|
- [Global Views](#custom-global-views)
|
||||||
|
- [Document Views](#custom-document-views)
|
||||||
|
|
||||||
|
## Custom Root Views
|
||||||
|
|
||||||
|
Root Views are the main views of the [Admin Panel](./overview). These are views that are scoped directly under the `/admin` route, such as the Dashboard or Account views. You can easily swap Root Views with your own or [create entirely new ones](#adding-new-root-views) through the `admin.components.views` property of your [Payload Config](../configuration/overview).
|
||||||
|
|
||||||
|
Here is an example showing what it might look like to swap out Root Views for your own Custom Views. See [Building Custom Views](#building-custom-views) for exact details on how to build them:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { buildConfig } from 'payload'
|
||||||
|
|
||||||
|
const config = buildConfig({
|
||||||
|
// ...
|
||||||
|
admin: {
|
||||||
|
components: {
|
||||||
|
views: {
|
||||||
|
Dashboard: MyCustomDashboardView, // highlight-line
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The following options are available:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| --------------- | ----------------------------------------------------------------------------- |
|
| --------------- | ----------------------------------------------------------------------------- |
|
||||||
| **`Account`** | The Account view is used to show the currently logged in user's Account page. |
|
| **`Account`** | The Account view is used to show the currently logged in user's Account page. |
|
||||||
| **`Dashboard`** | The main landing page of the [Admin Panel](./overview). |
|
| **`Dashboard`** | The main landing page of the [Admin Panel](./overview). |
|
||||||
|
|
||||||
To swap out any of these views, simply pass in your custom component to the `admin.components.views` property of your Payload config. For example:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// payload.config.ts
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
admin: {
|
|
||||||
components: {
|
|
||||||
views: {
|
|
||||||
Account: MyCustomAccountView,
|
|
||||||
Dashboard: MyCustomDashboardView,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For more granular control, pass a configuration object instead. Payload exposes the following properties for each view:
|
For more granular control, pass a configuration object instead. Payload exposes the following properties for each view:
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
@@ -39,227 +52,170 @@ For more granular control, pass a configuration object instead. Payload exposes
|
|||||||
| **`Component`** \* | Pass in the component that should be rendered when a user navigates to this route. |
|
| **`Component`** \* | Pass in the component that should be rendered when a user navigates to this route. |
|
||||||
| **`path`** \* | Any valid URL path or array of paths that [`path-to-regexp`](https://www.npmjs.com/package/path-to-regex) understands. |
|
| **`path`** \* | Any valid URL path or array of paths that [`path-to-regexp`](https://www.npmjs.com/package/path-to-regex) understands. |
|
||||||
| **`exact`** | Boolean. When true, will only match if the path matches the `usePathname()` exactly. |
|
| **`exact`** | Boolean. When true, will only match if the path matches the `usePathname()` exactly. |
|
||||||
| **`strict`** | When true, a path that has a trailing slash will only match a location.pathname with a trailing slash. This has no effect when there are additional URL segments in the location.pathname. |
|
| **`strict`** | When true, a path that has a trailing slash will only match a `location.pathname` with a trailing slash. This has no effect when there are additional URL segments in the pathname. |
|
||||||
| **`sensitive`** | When true, will match if the path is case sensitive. |
|
| **`sensitive`** | When true, will match if the path is case sensitive. |
|
||||||
|
|
||||||
_\* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
#### Adding new root views
|
#### Adding New Views
|
||||||
|
|
||||||
To add a _new_ view to the [Admin Panel](./overview), simply add another key to the `views` object with at least a `path` and `Component` property. For example:
|
To add a _new_ views to the [Admin Panel](./overview), simply add your own key to the `views` object with at least a `path` and `Component` property. For example:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// payload.config.ts
|
import { buildConfig } from 'payload'
|
||||||
{
|
|
||||||
|
const config = buildConfig({
|
||||||
// ...
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
views: {
|
views: {
|
||||||
|
// highlight-start
|
||||||
MyCustomView: {
|
MyCustomView: {
|
||||||
|
// highlight-end
|
||||||
Component: MyCustomView,
|
Component: MyCustomView,
|
||||||
path: '/my-custom-view',
|
path: '/my-custom-view',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The above example shows how to add a new [Root View](#custom-root-views), but the pattern is the same for [Collection Views](#custom-collection-views), [Global Views](#custom-global-views), and [Document Views](#custom-document-views). For help on how to build your own Custom Views, see [Building Custom Views](#building-custom-views).
|
||||||
|
|
||||||
|
<Banner type="warning">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
<br />
|
||||||
|
Routes are cascading, so unless explicitly given the `exact` property, they will
|
||||||
|
match on URLs that simply _start_ with the route's path. This is helpful when creating catch-all
|
||||||
|
routes in your application. Alternatively, define your nested route _before_ your parent
|
||||||
|
route.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
## Custom Collection Views
|
||||||
|
|
||||||
|
Collection Views are views that are scoped under the `/collections` route, such as the Collection List and Document Edit views. You can easily swap out Collection Views with your own or [create entirely new ones](#adding-new-views), through the `admin.components.views` property of your [Collection Config](../collections/overview).
|
||||||
|
|
||||||
|
Here is an example showing what it might look like to swap out Collection Views for your own Custom Views. See [Building Custom Views](#building-custom-views) for exact details on how to build them:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { SanitizedCollectionConfig } from 'payload/types'
|
||||||
|
|
||||||
|
export const MyCollectionConfig: SanitizedCollectionConfig = {
|
||||||
|
// ...
|
||||||
|
admin: {
|
||||||
|
components: {
|
||||||
|
views: {
|
||||||
|
Edit: MyCustomEditView, // highlight-line
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
<strong>Note:</strong>
|
<strong>Note:</strong>
|
||||||
<br />
|
The `Edit` property will replace the _entire_ Edit View, including the title, tabs, etc., _as well as all nested [Document Views](#custom-document-views)_, such as the API, Live Preview, and Version views. To replace only the Edit View precisely, use the `Edit.Default` key instead.
|
||||||
Routes are cascading. This means that unless explicitly given the `exact` property, they will
|
|
||||||
match on URLs that simply _start_ with the route's path. This is helpful when creating catch-all
|
|
||||||
routes in your application. Alternatively, you could define your nested route _before_ your parent
|
|
||||||
route.
|
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
For help on how to build your own custom view components, see [Building Custom View Components](#building-custom-view-components). For more examples regarding how to customize components, [look at the following examples](https://github.com/payloadcms/payload/tree/main/test/admin/components)._
|
The following options are available:
|
||||||
|
|
||||||
### Collections
|
| Property | Description |
|
||||||
|
| ---------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| **`Edit`** | The Edit View is used to edit a single document for any given Collection. [More details](#custom-document-views). |
|
||||||
|
| **`List`** | The List View is used to show a list of documents for any given Collection. |
|
||||||
|
|
||||||
To swap out entire views on collections, you can use the `admin.components.views` property on the collection's config. Payload renders the following views by default, all of which can be overridden:
|
<Banner type="success">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
You can also add _new_ Collection Views to the config by adding a new key to the `views` object with at least a `path` and `Component` property. See [Adding New Views](#adding-new-views) for more information.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
| Property | Description |
|
## Custom Global Views
|
||||||
| ---------- | ------------------------------------------------------------------------- |
|
|
||||||
| **`Edit`** | The Edit view is used to edit a single document for a given collection. |
|
|
||||||
| **`List`** | The List view is used to show a list of documents for a given collection. |
|
|
||||||
|
|
||||||
To swap out any of these views, simply pass in your custom component to the `admin.components.views` property of your Payload config. This will replace the entire view, including the page breadcrumbs, title, tabs, etc, _as well as all nested routes_.
|
Global Views are views that are scoped under the `/globals` route, such as the Document Edit View. You can easily swap out Global Views with your own or [create entirely new ones](#adding-new-views), through the `admin.components.views` property of your [Global Config](../globals/overview).
|
||||||
|
|
||||||
|
Here is an example showing what it might look like to swap out Global Views for your own Custom Views. See [Building Custom Views](#building-custom-views) for exact details on how to build them:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// Collection.ts
|
import type { SanitizedGlobalConfig } from 'payload/types'
|
||||||
{
|
|
||||||
|
export const MyGlobalConfig: SanitizedGlobalConfig = {
|
||||||
// ...
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
views: {
|
views: {
|
||||||
Edit: MyCustomEditView,
|
Edit: MyCustomEditView, // highlight-line
|
||||||
List: MyCustomListView,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
For help on how to build your own custom view components, see [Building Custom View Components](#building-custom-view-components).
|
<Banner type="warning">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
The `Edit` property will replace the _entire_ Edit View, including the title, tabs, etc., _as well as all nested [Document Views](#custom-document-views)_, such as the API, Live Preview, and Version views. To replace only the Edit View precisely, use the `Edit.Default` key instead.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
**Customizing Nested Views within 'Edit' in Collections**
|
The following options are available:
|
||||||
|
|
||||||
The `Edit` view in collections consists of several nested views, each serving a unique purpose. You can customize these nested views using the `admin.components.views.Edit` property in the collection's configuration. This approach allows you to replace specific nested views while keeping the overall structure of the `Edit` view intact, including the page breadcrumbs, title, tabs, etc.
|
|
||||||
|
|
||||||
Here's an example of how you can customize nested views within the `Edit` view in collections, including the use of the `actions` property:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// Collection.ts
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
admin: {
|
|
||||||
components: {
|
|
||||||
views: {
|
|
||||||
Edit: {
|
|
||||||
Default: {
|
|
||||||
Component: MyCustomDefaultTab,
|
|
||||||
actions: [CollectionEditButton], // Custom actions for the default edit view
|
|
||||||
},
|
|
||||||
API: {
|
|
||||||
Component: MyCustomAPIView,
|
|
||||||
actions: [CollectionAPIButton], // Custom actions for API view
|
|
||||||
},
|
|
||||||
LivePreview: {
|
|
||||||
Component: MyCustomLivePreviewView,
|
|
||||||
actions: [CollectionLivePreviewButton], // Custom actions for Live Preview
|
|
||||||
},
|
|
||||||
Version: {
|
|
||||||
Component: MyCustomVersionView,
|
|
||||||
actions: [CollectionVersionButton], // Custom actions for Version view
|
|
||||||
},
|
|
||||||
Versions: {
|
|
||||||
Component: MyCustomVersionsView,
|
|
||||||
actions: [CollectionVersionsButton], // Custom actions for Versions view
|
|
||||||
},
|
|
||||||
},
|
|
||||||
List: {
|
|
||||||
actions: [CollectionListButton],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Adding New Tabs to 'Edit' View**
|
|
||||||
|
|
||||||
You can also add _new_ tabs to the `Edit` view by adding another key to the `components.views.Edit[key]` object with a `path` and `Component` property. See [Custom Tabs](#custom-tabs) for more information.
|
|
||||||
|
|
||||||
### Globals
|
|
||||||
|
|
||||||
To swap out views for globals, you can use the `admin.components.views` property on the global's config. Payload renders the following views by default, all of which can be overridden:
|
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ---------- | ------------------------------------------------------------------- |
|
| ---------- | ------------------------------------------------------------------- |
|
||||||
| **`Edit`** | The Edit view is used to edit a single document for a given Global. |
|
| **`Edit`** | The Edit View is used to edit a single document for any given Global. [More details](#custom-document-views). |
|
||||||
|
|
||||||
To swap out any of these views, simply pass in your custom component to the `admin.components.views` property of your Payload config. This will replace the entire view, including the page breadcrumbs, title, and tabs, _as well as all nested views_.
|
<Banner type="success">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
You can also add _new_ Global Views to the config by adding a new key to the `views` object with at least a `path` and `Component` property. See [Adding New Views](#adding-new-views) for more information.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
## Custom Document Views
|
||||||
|
|
||||||
|
Document Views are views that are scoped under the `/collections/:collectionSlug/:id` or the `/globals/:globalSlug` route, such as the Edit View. You can easily swap out Document Views with your own or [create entirely new ones](#adding-new-document-views) through the `admin.components.views.Edit[key]` property of either your [Collection Config](../collections/overview) or [Global Config](../globals/overview).
|
||||||
|
|
||||||
|
This approach allows you to replace specific nested views while keeping the overall structure of the Edit View intact, including the title, tabs, etc. If you need to replace the _entire_ Edit View, including the nested Document Views, use the `Edit` key itself. See [Custom Collection Views](#custom-collection-views) or [Custom Global Views](#custom-global-views) for more information.
|
||||||
|
|
||||||
|
Here's an example showing what it might look like to swap out Document Views for your own Custom Views. See [Building Custom Views](#building-custom-views) for exact details on how to build them:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// Global.ts
|
import type { SanitizedCollectionConfig } from 'payload/types'
|
||||||
{
|
|
||||||
// ...
|
|
||||||
admin: {
|
|
||||||
components: {
|
|
||||||
views: {
|
|
||||||
Edit: MyCustomEditView,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For help on how to build your own custom view components, see [Building Custom View Components](#building-custom-view-components).
|
export const MyCollectionConfig: SanitizedCollectionConfig = {
|
||||||
|
|
||||||
**Customizing Nested Views within 'Edit' in Globals**
|
|
||||||
|
|
||||||
Similar to collections, Globals allow for detailed customization within the `Edit` view. This includes the ability to swap specific nested views while maintaining the overall structure of the `Edit` view. You can use the `admin.components.views.Edit` property in the Globals configuration to achieve this, and this will only replace the nested view, leaving the page breadcrumbs, title, and tabs intact.
|
|
||||||
|
|
||||||
Here's how you can customize nested views within the `Edit` view in Globals, including the use of the `actions` property:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// Global.ts
|
|
||||||
{
|
|
||||||
// ...
|
// ...
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
views: {
|
views: {
|
||||||
Edit: {
|
Edit: {
|
||||||
Default: {
|
|
||||||
Component: MyCustomGlobalDefaultTab,
|
|
||||||
actions: [GlobalEditButton], // Custom actions for the default edit view
|
|
||||||
},
|
|
||||||
API: {
|
API: {
|
||||||
Component: MyCustomGlobalAPIView,
|
Component: MyCustomAPIView, // highlight-line
|
||||||
actions: [GlobalAPIButton], // Custom actions for API view
|
|
||||||
},
|
|
||||||
LivePreview: {
|
|
||||||
Component: MyCustomGlobalLivePreviewView,
|
|
||||||
actions: [GlobalLivePreviewButton], // Custom actions for Live Preview
|
|
||||||
},
|
|
||||||
Version: {
|
|
||||||
Component: MyCustomGlobalVersionView,
|
|
||||||
actions: [GlobalVersionButton], // Custom actions for Version view
|
|
||||||
},
|
|
||||||
Versions: {
|
|
||||||
Component: MyCustomGlobalVersionsView,
|
|
||||||
actions: [GlobalVersionsButton], // Custom actions for Versions view
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also add _new_ tabs to the `Edit` view by adding another key to the `components.views.Edit[key]` object with a `path` and `Component` property. See [Custom Tabs](#custom-tabs) for more information.
|
<Banner type="warning">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
This applies to _both_ Collection _and_ Global configs.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
### Custom Tabs
|
The following options are available:
|
||||||
|
|
||||||
You can easily swap individual collection or global edit views. To do this, pass an _object_ to the `admin.components.views.Edit` property of the config. Payload renders the following views by default, all of which can be overridden:
|
|
||||||
|
|
||||||
| Property | Description |
|
| Property | Description |
|
||||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`Default`** | The Default view is the primary view in which your document is edited. |
|
| **`Default`** | The Default view is the primary view in which your document is edited. |
|
||||||
| **`Versions`** | The Versions view is used to view the version history of a single document. [More details](../versions) |
|
| **`Versions`** | The Versions view is used to view the version history of a single document. [More details](../versions). |
|
||||||
| **`Version`** | The Version view is used to view a single version of a single document for a given collection. [More details](../versions). |
|
| **`Version`** | The Version view is used to view a single version of a single document for a given collection. [More details](../versions). |
|
||||||
| **`API`** | The API view is used to display the REST API JSON response for a given document. |
|
| **`API`** | The API view is used to display the REST API JSON response for a given document. |
|
||||||
| **`LivePreview`** | The LivePreview view is used to display the Live Preview interface. [More details](../live-preview) |
|
| **`LivePreview`** | The LivePreview view is used to display the Live Preview interface. [More details](../live-preview). |
|
||||||
|
|
||||||
Here is an example:
|
#### Document Tabs
|
||||||
|
|
||||||
|
Each Document View can be given a new tab in the Edit View, if desired. Tabs are highly configurable, from as simple as changing the label to swapping out the entire component, they can be modified in any way. To add or customize tabs in the Edit View, use the `Component.Tab` key:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// Collection.ts or Global.ts
|
import type { SanitizedCollectionConfig } from 'payload/types'
|
||||||
export const MyCollection: SanitizedCollectionConfig = {
|
|
||||||
slug: 'my-collection',
|
|
||||||
admin: {
|
|
||||||
components: {
|
|
||||||
views: {
|
|
||||||
Edit: {
|
|
||||||
// You can also define `components.views.Edit` as a component, this will override _all_ nested views
|
|
||||||
Default: MyCustomDefaultTab,
|
|
||||||
Versions: MyCustomVersionsTab,
|
|
||||||
Version: MyCustomVersionTab,
|
|
||||||
API: MyCustomAPITab,
|
|
||||||
LivePreview: MyCustomLivePreviewTab,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
To add a _new_ tab to the `Edit` view, simply add another key to `components.views.Edit[key]` with at least a `path` and `Component` property. For example:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// `Collection.ts` or `Global.ts`
|
|
||||||
export const MyCollection: SanitizedCollectionConfig = {
|
export const MyCollection: SanitizedCollectionConfig = {
|
||||||
slug: 'my-collection',
|
slug: 'my-collection',
|
||||||
admin: {
|
admin: {
|
||||||
@@ -269,17 +225,17 @@ export const MyCollection: SanitizedCollectionConfig = {
|
|||||||
MyCustomTab: {
|
MyCustomTab: {
|
||||||
Component: MyCustomTab,
|
Component: MyCustomTab,
|
||||||
path: '/my-custom-tab',
|
path: '/my-custom-tab',
|
||||||
// You an swap the entire tab component out for your own
|
Tab: MyCustomTab // highlight-line
|
||||||
Tab: MyCustomTab,
|
|
||||||
},
|
},
|
||||||
AnotherCustomView: {
|
AnotherCustomView: {
|
||||||
Component: AnotherCustomView,
|
Component: AnotherCustomView,
|
||||||
path: '/another-custom-view',
|
path: '/another-custom-view',
|
||||||
// Or you can use the default tab component and just pass in your own label and href
|
// highlight-start
|
||||||
Tab: {
|
Tab: {
|
||||||
label: 'Another Custom View',
|
label: 'Another Custom View',
|
||||||
href: '/another-custom-view',
|
href: '/another-custom-view',
|
||||||
},
|
}
|
||||||
|
// highlight-end
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -288,14 +244,44 @@ export const MyCollection: SanitizedCollectionConfig = {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Building Custom View Components
|
<Banner type="warning">
|
||||||
|
<strong>Note:</strong>
|
||||||
|
This applies to _both_ Collections _and_ Globals.
|
||||||
|
</Banner>
|
||||||
|
|
||||||
Your custom view components will be provided with the following props:
|
### Building Custom Views
|
||||||
|
|
||||||
| Prop | Description |
|
Custom Views are just [Custom Components](./components) rendered at the page-level. To understand how to build Custom Views, first review the [Building Custom Components](./components#building-custom-components) guide. Once you have a Custom Component ready, you can use it as a Custom View.
|
||||||
| ----------------------- | ---------------------------------------------------------------------------- |
|
|
||||||
| **`user`** | The currently logged in user. Will be `null` if no user is logged in. |
|
```ts
|
||||||
| **`canAccessAdmin`** \* | If the currently logged in user is allowed to access the [Admin Panel](./overview) or not. |
|
import type { SanitizedCollectionConfig } from 'payload/types'
|
||||||
|
import { MyCustomView } from './MyCustomView'
|
||||||
|
|
||||||
|
export const MyCollectionConfig: SanitizedCollectionConfig = {
|
||||||
|
// ...
|
||||||
|
admin: {
|
||||||
|
components: {
|
||||||
|
views: {
|
||||||
|
Edit: MyCustomView, // highlight-line
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Your Custom Views will be provided with the following props:
|
||||||
|
|
||||||
|
| Prop | Description |
|
||||||
|
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `payload` | The [Payload](../local-api/overview) class. |
|
||||||
|
| `i18n` | The [i18n](../configuration/i18n) object. |
|
||||||
|
| `user` | The currently logged in user. |
|
||||||
|
| `locale` | The current [Locale](../configuration/localization) of the [Admin Panel](./overview). |
|
||||||
|
| `navGroups` | The grouped navigation items according to `admin.group` in your [Collection Config](../collections/overview) or [Global Config](../globals/overview). |
|
||||||
|
| `params` | An object containing the [Dynamic Route Parameters](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes). |
|
||||||
|
| `permissions` | The permissions of the currently logged in user. |
|
||||||
|
| `searchParams` | An object containing the [Search Parameters](https://developer.mozilla.org/docs/Learn/Common_questions/What_is_a_URL#parameters). |
|
||||||
|
| `visibleEntities` | The current user's visible entities according to your [Access Control](../access-control/overview). |
|
||||||
|
|
||||||
<Banner type="warning">
|
<Banner type="warning">
|
||||||
<strong>Note:</strong>
|
<strong>Note:</strong>
|
||||||
@@ -303,13 +289,3 @@ Your custom view components will be provided with the following props:
|
|||||||
It's up to you to secure your custom views. If your view requires a user to be logged in or to
|
It's up to you to secure your custom views. If your view requires a user to be logged in or to
|
||||||
have certain access rights, you should handle that within your view component yourself.
|
have certain access rights, you should handle that within your view component yourself.
|
||||||
</Banner>
|
</Banner>
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
You can find examples of custom views in the [Payload source code `/test/admin/components/views` folder](https://github.com/payloadcms/payload/tree/main/test/admin/components/views). There, you'll find two custom views:
|
|
||||||
|
|
||||||
1. A custom view that uses the `DefaultTemplate`, which is the built-in Payload template that displays the sidebar and "eyebrow nav"
|
|
||||||
1. A custom view that uses the `MinimalTemplate` - which is just a centered template used for things like logging in or out
|
|
||||||
|
|
||||||
To see how to pass in your custom views to create custom views of your own, take a look at the `admin.components.views` property of the [Payload test admin config](https://github.com/payloadcms/payload/blob/main/test/admin/config.ts).
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,4 +37,4 @@ example/
|
|||||||
├── svelte/
|
├── svelte/
|
||||||
```
|
```
|
||||||
|
|
||||||
...where `payload` is your Payload project, and the other directories are dedicated to their respective front-end framework. We are adding new examples every day, so if your framework of choice is not yet supported in any particular example, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions) or open a new [PR](https://github.com/payloadcms/payload/pulls) to add it yourself.
|
Where `payload` is your Payload project, and the other directories are dedicated to their respective front-end framework. We are adding new examples every day, so if your framework of choice is not yet supported in any particular example, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions) or open a new [PR](https://github.com/payloadcms/payload/pulls) to add it yourself.
|
||||||
|
|||||||
@@ -91,13 +91,13 @@ import { vercelStegaSplit } from '@vercel/stega'
|
|||||||
const { cleaned, encoded } = vercelStegaSplit(text)
|
const { cleaned, encoded } = vercelStegaSplit(text)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Block fields
|
### Blocks and array fields
|
||||||
|
|
||||||
All `blocks` fields by definition do not have plain text strings to encode. For this reason, blocks are given an additional `encodedSourceMap` key, which you can use to enable Content Link on entire sections of your site. You can then specify the editing container by adding the `data-vercel-edit-target` HTML attribute to any top-level element of your block.
|
All `blocks` and `array` fields by definition do not have plain text strings to encode. For this reason, they are given an additional `_encodedSourceMap` property, which you can use to enable Content Link on entire _sections_ of your site. You can then specify the editing container by adding the `data-vercel-edit-target` HTML attribute to any top-level element of your block.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
<div data-vercel-edit-target>
|
<div data-vercel-edit-target>
|
||||||
<span style={{ display: "none" }}>{encodedSourceMap}</span>
|
<span style={{ display: "none" }}>{_encodedSourceMap}</span>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ import config from '../payload.config'
|
|||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const payload = await getPayloadHMR({ config })
|
const payload = await getPayloadHMR({ config })
|
||||||
|
|
||||||
const page = await payload.find({
|
const page = await payload.findByID({
|
||||||
collection: 'pages',
|
collection: 'pages',
|
||||||
|
id: '123',
|
||||||
draft: true
|
draft: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user