---
title: Swap in your own React components
label: Custom Components
order: 20
desc: Fully customize your Admin Panel by swapping in your own React components. Add fields, remove views, update routes and change functions to sculpt your perfect Dashboard.
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.
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
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.
Tip:
Custom components will automatically be provided with all props that the default component
normally accepts.
## Base Component Overrides
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 / mobile menu in its entirety. |
| **`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. |
| **`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.
`payload.config.js`
```ts
import { buildConfig } from 'payload/config'
import {
MyCustomNav,
MyCustomLogo,
MyCustomIcon,
MyCustomAccount,
MyCustomDashboard,
MyProvider,
MyCustomAdminAction,
} from './customComponents'
export default buildConfig({
admin: {
components: {
Nav: MyCustomNav,
graphics: {
Icon: MyCustomIcon,
Logo: MyCustomLogo,
},
actions: [MyCustomAdminAction],
views: {
Account: MyCustomAccount,
Dashboard: MyCustomDashboard,
},
providers: [MyProvider],
},
},
})
```
## Collections
You can override components on a collection-by-collection basis via the `admin.components` property.
| Path | Description |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| **`BeforeList`** | Array of components to inject _before_ the built-in List view |
| **`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 |
| **`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.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.PreviewButton`** | Replace the default `Preview` button with a custom component. |
| **`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:
`CustomSaveButton.tsx`
```tsx
import { CustomSaveButtonProps } from 'payload/types'
const CustomSaveButton: CustomSaveButtonProps = ({
DefaultButton,
label,
save
}) => {
return (
)
}
```
`CustomSaveDraftButton.tsx`
```tsx
import { CustomSaveDraftButtonProps } from 'payload/types'
export const CustomSaveDraftButton: CustomSaveDraftButtonProps = ({
DefaultButton,
disabled,
label,
saveDraft,
}) => {
return (
)
}
```
`CustomPublishButton.tsx`
```tsx
import { CustomPreviewButtonProps } from 'payload/types'
export const CustomPublishButton: CustomPublishButtonProps = ({
DefaultButton,
disabled,
label,
publish,
}) => {
return (
)
}
```
`CustomPreviewButton`
```tsx
import { CustomPreviewButtonProps } from 'payload/types'
export const CustomPreviewButton: CustomPreviewButtonProps = ({
DefaultButton,
disabled,
label,
preview,
}) => {
return (
)
}
```
`collection.ts`
```tsx
import * as React from 'react'
import { CustomSaveButton } from './CustomSaveButton'
import { CustomSaveDraftButton } from './CustomSaveDraftButton'
import { CustomPublishButton } from './CustomPublishButton'
import { CustomPreviewButton } from './CustomPreviewButton'
export const MyCollection: SanitizedCollectionConfig = {
slug: 'my-collection',
admin: {
components: {
edit: {
SaveButton: CustomSaveButton,
SaveDraftButton: CustomSaveDraftButton,
PublishButton: CustomPublishButton,
PreviewButton: CustomPreviewButton,
},
},
},
}
```
## Globals
As with Collections, you can override components on a global-by-global basis via the `admin.components` property.
| Path | Description |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| **`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.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. |
| **`views`** | Override or create new [Views](./views) within the [Admin Panel](./overview). |
## Custom providers
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.
Reminder: Don't forget to pass the **children** prop through the provider
component for the admin UI to show
## Styling Custom Components
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
import { useTranslation } from '@payloadcms/ui/providers/Translation'
const CustomComponent: React.FC = () => {
// highlight-start
const { t, i18n } = useTranslation()
// highlight-end
return (
- {t('namespace1:key', { variable: 'value' })}
- {t('namespace2:key', { variable: 'value' })}
- {i18n.language}
)
}
```
## Getting the current locale
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:
```tsx
import { useLocale } from 'payload/components/utilities'
const Greeting: React.FC = () => {
// highlight-start
const locale = useLocale()
// highlight-end
const trans = {
en: 'Hello',
es: 'Hola',
}
return {trans[locale.code]}
}
```