Skip to content

Commit 94254da

Browse files
feat: add support for custom UnpublishButton component (#15400)
### What Adds the ability to customize the `UnpublishButton` component in collection and global configs, following the same pattern as `PublishButton`. ### Why `UnpublishButton` was hardcoded while other document control buttons (`PublishButton`, `SaveButton`, etc.) could be customized. ### How Added type definitions, config options, component resolution in renderDocumentSlots, and updated DocumentControls to use the RenderCustomComponent pattern. --------- Co-authored-by: Alessio Gravili <github@gravili.net>
1 parent 2ce26fa commit 94254da

22 files changed

Lines changed: 256 additions & 16 deletions

File tree

‎docs/configuration/collections.mdx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ The following options are available:
242242
|`SaveDraftButton`| Replace the default Save Draft Button within the Edit View. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#savedraftbutton). |
243243
|`Status`| Replace the default Status component within the Edit View. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#status). |
244244
|`PublishButton`| Replace the default Publish Button within the Edit View. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publishbutton). |
245+
|`UnpublishButton`| Replace the default Unpublish Button within the Edit View. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#unpublishbutton). |
245246
|`PreviewButton`| Replace the default Preview Button within the Edit View. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#previewbutton). |
246247
|`Upload`| Replace the default Upload component within the Edit View. [Upload](../upload/overview) must be enabled. [More details](../custom-components/edit-view#upload). |
247248

‎docs/configuration/globals.mdx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ The following options are available:
186186
|`SaveButton`| Replace the default Save Button with a Custom Component. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#savebutton). |
187187
|`SaveDraftButton`| Replace the default Save Draft Button with a Custom Component. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#savedraftbutton). |
188188
|`PublishButton`| Replace the default Publish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publishbutton). |
189+
|`UnpublishButton`| Replace the default Unpublish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#unpublishbutton). |
189190
|`PreviewButton`| Replace the default Preview Button with a Custom Component. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#previewbutton). |
190191
|`Status`| Replace the default Status component with a Custom Component. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#status). |
191192

‎docs/custom-components/edit-view.mdx‎

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ The following options are available:
108108
|`SaveButton`| A button that saves the current document. [More details](#savebutton). |
109109
|`SaveDraftButton`| A button that saves the current document as a draft. [More details](#savedraftbutton). |
110110
|`PublishButton`| A button that publishes the current document. [More details](#publishbutton). |
111+
|`UnpublishButton`| A button that unpublishes the current document. [More details](#unpublishbutton). |
111112
|`PreviewButton`| A button that previews the current document. [More details](#previewbutton). |
112113
|`Description`| A description of the Collection. [More details](#description). |
113114
|`Status`| A component that represents the status of the current document. [More details](#status). |
@@ -143,6 +144,7 @@ The following options are available:
143144
|`SaveButton`| A button that saves the current document. [More details](#savebutton). |
144145
|`SaveDraftButton`| A button that saves the current document as a draft. [More details](#savedraftbutton). |
145146
|`PublishButton`| A button that publishes the current document. [More details](#publishbutton). |
147+
|`UnpublishButton`| A button that unpublishes the current document. [More details](#unpublishbutton). |
146148
|`PreviewButton`| A button that previews the current document. [More details](#previewbutton). |
147149
|`Description`| A description of the Global. [More details](#description). |
148150
|`Status`| A component that represents the status of the global. [More details](#status). |
@@ -429,7 +431,7 @@ Here's an example of a custom `PublishButton` component:
429431
```tsx
430432
importReactfrom'react'
431433
import { PublishButton } from'@payloadcms/ui'
432-
importtype { PublishButtonClientProps } from'payload'
434+
importtype { PublishButtonServerProps } from'payload'
433435

434436
exportfunction MyPublishButton(props:PublishButtonServerProps) {
435437
return <PublishButtonlabel="Publish" />
@@ -442,13 +444,61 @@ export function MyPublishButton(props: PublishButtonServerProps) {
442444
'use client'
443445
importReactfrom'react'
444446
import { PublishButton } from'@payloadcms/ui'
445-
importtype { PublishButtonClientProps } from'payload'
446447

447-
exportfunction MyPublishButton(props:PublishButtonClientProps) {
448+
exportfunction MyPublishButton() {
448449
return <PublishButtonlabel="Publish" />
449450
}
450451
```
451452

453+
### UnpublishButton
454+
455+
The `UnpublishButton` property allows you to render a custom Unpublish Button in the Edit View.
456+
457+
To add an `UnpublishButton` component, use the `components.edit.UnpublishButton` property in your [Collection Config](../configuration/collections) or `components.elements.UnpublishButton` in your [Global Config](../configuration/globals):
458+
459+
```ts
460+
importtype { CollectionConfig } from'payload'
461+
462+
exportconst MyCollection:CollectionConfig= {
463+
// ...
464+
admin: {
465+
components: {
466+
edit: {
467+
// highlight-start
468+
UnpublishButton: '/path/to/MyUnpublishButton',
469+
// highlight-end
470+
},
471+
},
472+
},
473+
}
474+
```
475+
476+
Here's an example of a custom `UnpublishButton` component:
477+
478+
#### Server Component
479+
480+
```tsx
481+
importReactfrom'react'
482+
import { UnpublishButton } from'@payloadcms/ui'
483+
importtype { UnpublishButtonServerProps } from'payload'
484+
485+
exportfunction MyUnpublishButton(props:UnpublishButtonServerProps) {
486+
return <UnpublishButtonlabel="Unpublish" />
487+
}
488+
```
489+
490+
#### Client Component
491+
492+
```tsx
493+
'use client'
494+
importReactfrom'react'
495+
import { UnpublishButton } from'@payloadcms/ui'
496+
497+
exportfunction MyUnpublishButton() {
498+
return <UnpublishButtonlabel="Unpublish" />
499+
}
500+
```
501+
452502
### PreviewButton
453503

454504
The `PreviewButton` property allows you to render a custom Preview Button in the Edit View.

‎packages/next/src/views/Document/renderDocumentSlots.tsx‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
ServerFunction,
1414
ServerProps,
1515
StaticDescription,
16+
UnpublishButtonServerPropsOnly,
1617
ViewDescriptionClientProps,
1718
ViewDescriptionServerPropsOnly,
1819
}from'payload'
@@ -148,6 +149,18 @@ export const renderDocumentSlots: (args: {
148149
})
149150
}
150151

152+
constCustomUnpublishButton=
153+
collectionConfig?.admin?.components?.edit?.UnpublishButton||
154+
globalConfig?.admin?.components?.elements?.UnpublishButton
155+
156+
if(CustomUnpublishButton){
157+
components.UnpublishButton=RenderServerComponent({
158+
Component: CustomUnpublishButton,
159+
importMap: req.payload.importMap,
160+
serverProps: serverPropssatisfiesUnpublishButtonServerPropsOnly,
161+
})
162+
}
163+
151164
constCustomSaveDraftButton=
152165
collectionConfig?.admin?.components?.edit?.SaveDraftButton||
153166
globalConfig?.admin?.components?.elements?.SaveDraftButton
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
importtype{ServerProps}from'../../config/types.js'
22

3-
exporttypePublishButtonClientProps={
4-
label?: string
5-
}
3+
exporttypePublishButtonClientProps={}
64

75
exporttypePublishButtonServerPropsOnly={}&ServerProps
86

9-
exporttypePublishButtonServerProps=PublishButtonClientProps&PublishButtonServerPropsOnly
7+
exporttypePublishButtonServerProps=PublishButtonServerPropsOnly
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
importtype{ServerProps}from'../../config/types.js'
2+
3+
exporttypeUnpublishButtonClientProps={}
4+
5+
exporttypeUnpublishButtonServerPropsOnly={}&ServerProps
6+
7+
exporttypeUnpublishButtonServerProps=UnpublishButtonServerPropsOnly

‎packages/payload/src/admin/types.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,16 @@ export type {
8080
SaveDraftButtonServerProps,
8181
SaveDraftButtonServerPropsOnly,
8282
}from'./elements/SaveDraftButton.js'
83-
8483
exporttype{CustomStatus}from'./elements/Status.js'
8584

8685
exporttype{Column}from'./elements/Table.js'
8786

87+
exporttype{
88+
UnpublishButtonClientProps,
89+
UnpublishButtonServerProps,
90+
UnpublishButtonServerPropsOnly,
91+
}from'./elements/UnpublishButton.js'
92+
8893
exporttype{CustomUpload}from'./elements/Upload.js'
8994

9095
exporttype{
@@ -570,6 +575,7 @@ export type DocumentSlots = {
570575
SaveButton?: React.ReactNode
571576
SaveDraftButton?: React.ReactNode
572577
Status?: React.ReactNode
578+
UnpublishButton?: React.ReactNode
573579
Upload?: React.ReactNode
574580
UploadControls?: React.ReactNode
575581
}

‎packages/payload/src/bin/generateImportMap/iterateCollections.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export function iterateCollections({
4343
addToImportMap(collection.admin?.components?.edit?.SaveButton)
4444
addToImportMap(collection.admin?.components?.edit?.SaveDraftButton)
4545
addToImportMap(collection.admin?.components?.edit?.Status)
46+
addToImportMap(collection.admin?.components?.edit?.UnpublishButton)
4647
addToImportMap(collection.admin?.components?.edit?.Upload)
4748

4849
if(collection.upload?.admin?.components?.controls){

‎packages/payload/src/bin/generateImportMap/iterateGlobals.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export function iterateGlobals({
3636
addToImportMap(global.admin?.components?.elements?.SaveButton)
3737
addToImportMap(global.admin?.components?.elements?.SaveDraftButton)
3838
addToImportMap(global.admin?.components?.elements?.Status)
39+
addToImportMap(global.admin?.components?.elements?.UnpublishButton)
3940

4041
if(global.admin?.components?.views?.edit){
4142
for(consteditViewConfigofObject.values(global.admin?.components?.views?.edit)){

‎packages/payload/src/collections/config/types.ts‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22
importtype{GraphQLInputObjectType,GraphQLNonNull,GraphQLObjectType}from'graphql'
33
importtype{DeepRequired,IsAny,MarkOptional}from'ts-essentials'
44

5-
importtype{CustomStatus,CustomUpload,ViewTypes}from'../../admin/types.js'
5+
importtype{
6+
CustomStatus,
7+
CustomUpload,
8+
PublishButtonClientProps,
9+
PublishButtonServerProps,
10+
UnpublishButtonClientProps,
11+
UnpublishButtonServerProps,
12+
ViewTypes,
13+
}from'../../admin/types.js'
614
importtype{ArgumentsasMeArguments}from'../../auth/operations/me.js'
715
importtype{
816
ArgumentsasRefreshArguments,
@@ -358,7 +366,7 @@ export type CollectionAdminOptions = {
358366
* Replaces the "Publish" button
359367
* + drafts must be enabled
360368
*/
361-
PublishButton?: CustomComponent
369+
PublishButton?: PayloadComponent<PublishButtonServerProps,PublishButtonClientProps>
362370
/**
363371
* Replaces the "Save" button
364372
* + drafts must be disabled
@@ -374,6 +382,11 @@ export type CollectionAdminOptions = {
374382
* Replaces the "Status" section
375383
*/
376384
Status?: CustomStatus
385+
/**
386+
* Replaces the "Unpublish" button
387+
* + drafts must be enabled
388+
*/
389+
UnpublishButton?: PayloadComponent<UnpublishButtonServerProps,UnpublishButtonClientProps>
377390
/**
378391
* Replaces the "Upload" section
379392
* + upload must be enabled

0 commit comments

Comments
 (0)