feat: add new option for admin.components.header (#7647)
## Description Adds `admin.components.header` option to allow users to insert custom components in the page header / top of page. [Related discussion](https://github.com/payloadcms/payload/discussions/7584) - [X] I have read and understand the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository. ## Type of change - [ ] Chore (non-breaking change which does not add functionality) - [X] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Change to the [templates](https://github.com/payloadcms/payload/tree/main/templates) directory (does not affect core functionality) - [ ] Change to the [examples](https://github.com/payloadcms/payload/tree/main/examples) directory (does not affect core functionality) - [x] This change requires a documentation update ## Checklist: - [x] I have added tests that prove my fix is effective or that my feature works - will add - [X] Existing test suite passes locally with my changes
This commit is contained in:
committed by
GitHub
parent
7c8272b467
commit
3b59416298
@@ -276,7 +276,8 @@ The following options are available:
|
||||
| **`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. [More details](#custom-providers). |
|
||||
| **`actions`** | An array of Custom Components to be rendered in the header of the Admin Panel, providing additional interactivity and functionality. |
|
||||
| **`actions`** | An array of Custom Components to be rendered _within_ the header of the Admin Panel, providing additional interactivity and functionality. |
|
||||
| **`header`** | An array of Custom Components to be injected above the Payload header. |
|
||||
| **`views`** | Override or create new views within the Admin Panel. [More details](./views). |
|
||||
|
||||
<Banner type="success">
|
||||
|
||||
@@ -10,17 +10,22 @@
|
||||
}
|
||||
|
||||
&__nav-toggler-wrapper {
|
||||
position: fixed;
|
||||
position: sticky;
|
||||
z-index: var(--z-modal);
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: var(--app-header-height);
|
||||
height: 0;
|
||||
width: var(--gutter-h);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&__nav-toggler {
|
||||
height: var(--app-header-height);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__wrap {
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
|
||||
@@ -31,7 +31,8 @@ export const DefaultTemplate: React.FC<DefaultTemplateProps> = ({
|
||||
}) => {
|
||||
const {
|
||||
admin: {
|
||||
components: { Nav: CustomNav } = {
|
||||
components: { header: CustomHeader, Nav: CustomNav } = {
|
||||
header: undefined,
|
||||
Nav: undefined,
|
||||
},
|
||||
} = {},
|
||||
@@ -57,10 +58,18 @@ export const DefaultTemplate: React.FC<DefaultTemplateProps> = ({
|
||||
'CustomNav',
|
||||
)
|
||||
|
||||
const MappedCustomHeader = createMappedComponent(
|
||||
CustomHeader,
|
||||
undefined,
|
||||
undefined,
|
||||
'CustomHeader',
|
||||
)
|
||||
|
||||
return (
|
||||
<EntityVisibilityProvider visibleEntities={visibleEntities}>
|
||||
<BulkUploadProvider>
|
||||
<div>
|
||||
<RenderComponent mappedComponent={MappedCustomHeader} />
|
||||
<div style={{ position: 'relative' }}>
|
||||
<div className={`${baseClass}__nav-toggler-wrapper`} id="nav-toggler">
|
||||
<NavToggler className={`${baseClass}__nav-toggler`}>
|
||||
<NavHamburger />
|
||||
|
||||
@@ -36,10 +36,12 @@ export function iterateConfig({
|
||||
imports,
|
||||
})
|
||||
|
||||
typeof config.admin?.avatar === 'object' && addToImportMap(config.admin?.avatar?.Component)
|
||||
if (typeof config.admin?.avatar === 'object') {
|
||||
addToImportMap(config.admin?.avatar?.Component)
|
||||
}
|
||||
|
||||
addToImportMap(config.admin?.components?.Nav)
|
||||
|
||||
addToImportMap(config.admin?.components?.header)
|
||||
addToImportMap(config.admin?.components?.logout?.Button)
|
||||
addToImportMap(config.admin?.components?.graphics?.Icon)
|
||||
addToImportMap(config.admin?.components?.graphics?.Logo)
|
||||
|
||||
@@ -697,6 +697,10 @@ export type Config = {
|
||||
/** Replace the logo on the login page */
|
||||
Logo?: CustomComponent
|
||||
}
|
||||
/**
|
||||
* Add custom header to top of page globally
|
||||
*/
|
||||
header?: CustomComponent[]
|
||||
/** Replace logout related components */
|
||||
logout?: {
|
||||
/** Replace the logout button */
|
||||
|
||||
30
test/admin/components/CustomHeader/index.tsx
Normal file
30
test/admin/components/CustomHeader/index.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import type { PayloadServerReactComponent, SanitizedConfig } from 'payload'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
const baseClass = 'custom-header'
|
||||
|
||||
export const CustomHeader: PayloadServerReactComponent<
|
||||
SanitizedConfig['admin']['components']['header'][0]
|
||||
> = () => {
|
||||
return (
|
||||
<div
|
||||
className={baseClass}
|
||||
style={{
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'var(--theme-success-500)',
|
||||
display: 'flex',
|
||||
minHeight: 'var(--app-header-height)',
|
||||
padding: '0 var(--gutter-h)',
|
||||
// position: 'sticky',
|
||||
top: 0,
|
||||
width: '100%',
|
||||
zIndex: 'var(--z-modal)',
|
||||
}}
|
||||
>
|
||||
<p style={{ color: 'var(--theme-text)', margin: 0 }}>
|
||||
Here is a custom header inserted with admin.components.header
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -47,6 +47,7 @@ export default buildConfigWithDefaults({
|
||||
],
|
||||
afterNavLinks: ['/components/AfterNavLinks/index.js#AfterNavLinks'],
|
||||
beforeLogin: ['/components/BeforeLogin/index.js#BeforeLogin'],
|
||||
header: ['/components/CustomHeader/index.js#CustomHeader'],
|
||||
logout: {
|
||||
Button: '/components/Logout/index.js#Logout',
|
||||
},
|
||||
|
||||
@@ -680,6 +680,14 @@ describe('admin1', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('custom components', () => {
|
||||
test('should render custom header', async () => {
|
||||
await page.goto(`${serverURL}/admin`)
|
||||
const header = page.locator('.custom-header')
|
||||
await expect(header).toContainText('Here is a custom header')
|
||||
})
|
||||
})
|
||||
|
||||
describe('API view', () => {
|
||||
test('collection — should not show API tab when disabled in config', async () => {
|
||||
await page.goto(postsUrl.collection(noApiViewCollectionSlug))
|
||||
|
||||
Reference in New Issue
Block a user