While designing the Payload Admin panel, we determined it should be as minimal and straightforward as possible to allow easy customization and control. There are many times where you may want to completely control how a whole view or a field works. You might even want to add in your own routes entirely. In order for Payload to support that level of customization without introducing versioning / future-proofing issues, Payload provides for a pattern to supply your own React components via your Payload config.
To swap in your own React component, first, consult the list of available component overrides below. Determine the scope that corresponds to what you are trying to accomplish, and then author your React component 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:
Path | Description |
---|---|
Nav | Contains the sidebar and mobile Nav in its entirety. |
BeforeDashboard | Array of components to inject into the built-in Dashboard, before the default dashboard contents. Demo |
AfterDashboard | Array of components to inject into the built-in Dashboard, after the default dashboard contents. |
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. |
BeforeNavLinks | Array of components to inject into the built-in Nav, before the links themselves. |
AfterNavLinks | Array of components to inject into the built-in Nav, after the links. |
views.Account | The Account view is used to show the currently logged in user's Account page. |
views.Dashboard | The main landing page of the Admin panel. |
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. |
routes | Define your own routes to add to the Payload Admin UI. More |
providers | Define your own provider components that will wrap the Payload Admin UI. More |
payload.config.js
import { buildConfig } from 'payload/config';import { MyCustomNav, MyCustomLogo, MyCustomIcon, MyCustomAccount, MyCustomDashboard, MyProvider } from './customComponents.js';export default buildConfig({admin: {components: {Nav: MyCustomNav,graphics: {Icon: MyCustomIcon,Logo: MyCustomLogo,},views: {Account: MyCustomAccount,Dashboard: MyCustomDashboard,},providers: [MyProvider],}}})
For more examples regarding how to customize components, look at the demo app.
You can override components on a Collection-by-Collection basis via each Collection's admin
property.
Path | Description |
---|---|
views.Edit | Used while a document within this Collection is being edited. |
views.List | The List view is used to render a paginated, filterable table of Documents in this Collection. |
As with Collections, You can override components on a global-by-global basis via their admin
property.
Path | Description |
---|---|
views.Edit | Used while this Global is being edited. |
All Payload fields support the ability to swap in your own React components. So, for example, instead of rendering a default Text input, you might need to render a color picker that provides the editor with a custom color picker interface to restrict the data entered to colors only.
Fields support the following custom components:
Component | Description |
---|---|
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. |
Field | Swap out the field itself within all Edit views. |
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:
import { useField } from 'payload/components/forms';const CustomTextField = ({ path }) => {const { value, setValue } = useField({ path });return (<inputonChange={(e) => setValue(e.target.value)}value={value}/>)}
There are times when a custom field component needs to have access to data from other fields. This can be done using getDataByPath
from useWatchForm
as follows:
import { useWatchForm } from 'payload/components/forms';const DisplayFee = () => {const { getDataByPath } = useWatchForm();const amount = getDataByPath('amount');const feePercentage = getDataByPath('feePercentage');if (amount && feePercentage) {return (<span>The fee is ${ amount * feePercentage / 100 }</span>);}};
The document ID can be very useful for certain custom components. You can get the id
from the useDocumentInfo
hook. Here is an example of a UI
field using id
to link to related collections:
import { useDocumentInfo } from 'payload/components/utilities';const LinkFromCategoryToPosts = () => {const { id } = useDocumentInfo();// id will be undefined on the create formif (!id) {return null;}return (<a href={`/admin/collections/posts?where[or][0][and][0][category][in][0]=[${id}]`} >View posts</a>)};
You can easily add your own custom routes to the Payload Admin panel using the admin.components.routes
property. Payload currently uses the extremely powerful React Router v5.x and custom routes support all the properties of the React Router <Route />
component.
Custom routes support the following properties:
Property | Description |
---|---|
Component * | Pass in the component that should be rendered when a user navigates to this route. |
path * | React Router path . See the React Router docs for more info. |
exact | React Router exact property. More |
strict | React Router strict property. More |
sensitive | React Router sensitive property. More |
* An asterisk denotes that a property is required.
Your custom route components will be given all the props that a React Router <Route />
typically would receive, as well as two props from Payload:
Prop | Description |
---|---|
user | The currently logged in user. Will be null if no user is logged in. |
canAccessAdmin * | If the currently logged in user is allowed to access the admin panel or not. |
You can find examples of custom route views in the Payload source code /demo/client/components/views
folder. There, you'll find two custom routes:
DefaultTemplate
, which is the built-in Payload template that displays the sidebar and "eyebrow nav"MinimalTemplate
- which is just a centered template used for things like logging in or outTo see how to pass in your custom views to create custom routes of your own, take a look at the admin.components.routes
property of the Payload demo config.
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. Within your config add admin.components.providers
, these can be used to share context or provide other custom functionality. Read the React context docs to learn more.
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';
In any custom component you can get the selected locale with the useLocale
hook. Here is a simple example:
import { useLocale } from 'payload/components/utilities';const Greeting = () => {const locale = useLocale();const trans = {en: 'Hello',es: 'Hola',};return (<span> { trans[locale] } </span>)}