Skip to content

Commit 3c5aa1b

Browse files
docs: improvements and fixes to blocks documentation (#13782)
The information about the block field and the blocks themselves wasn't separated in the documentation, and in fact, there were times when they were confused and incorrectly mixed. This caused confusion among our users. This PR closes an issue, a discussion, and another PR that arose because it wasn't clear that the `blockName` could be programmatically modified with the block's content. This is possible through `admin.components.Label`, which isn't the best name, as it changes the `label` and the `name` of the block, two different concepts. I've added a section to the documentation that I think will make all of this much clearer. Before: <img width="266" height="362" alt="image" src="https://github.com/user-attachments/assets/3b5c95f0-2cdb-4995-a25d-9984f9ab54cb" /> After: <img width="266" height="383" alt="image" src="https://github.com/user-attachments/assets/99936f64-326f-4d69-a464-626d7f53fa08" /> Replaces #12135 Fixes #12112 & addresses #4648 --------- Co-authored-by: Said Akhrarov <[email protected]>
1 parent 13af91f commit 3c5aa1b

File tree

1 file changed

+87
-86
lines changed

1 file changed

+87
-86
lines changed

docs/fields/blocks.mdx

Lines changed: 87 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,23 @@
22
title: Blocks Field
33
label: Blocks
44
order: 30
5-
desc: The Blocks Field is a great layout build and can be used to construct any flexible content model. Learn how to use Block Fields, see examples and options.
5+
desc: The Blocks Field is a great layout builder and can be used to construct any flexible content model. Learn how to use Block Fields, see examples and options.
66
keywords: blocks, fields, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
77
---
88

9-
The Blocks Field is **incredibly powerful**, storing an array of objects based on the fields that you define, where each item in the array is a "block" with its own unique schema.
9+
The Blocks Field is one of the most flexible tools in Payload. It stores an array of objects, where each object is a “block” with its own schema. Unlike a simple array (where every item looks the same), blocks let you mix and match different content types in any order.
1010

11-
Blocks are a great way to create a flexible content model that can be used to build a wide variety of content types, including:
11+
This makes Blocks perfect for building dynamic, editor-friendly experiences, such as:
1212

13-
- A layout builder tool that grants editors to design highly customizable page or post layouts. Blocks could include configs such as `Quote`, `CallToAction`, `Slider`, `Content`, `Gallery`, or others.
14-
- A form builder tool where available block configs might be `Text`, `Select`, or `Checkbox`.
15-
- Virtual event agenda "timeslots" where a timeslot could either be a `Break`, a `Presentation`, or a `BreakoutSession`.
16-
17-
<LightDarkImage
18-
srcLight="https://payloadcms.com/images/docs/fields/blocks.png"
19-
srcDark="https://payloadcms.com/images/docs/fields/blocks-dark.png"
20-
alt="Admin Panel screenshot of add Blocks drawer view"
21-
caption="Admin Panel screenshot of add Blocks drawer view"
22-
/>
13+
- A page builder with blocks like `Quote`, `CallToAction`, `Slider`, or `Gallery`.
14+
- A form builder with block types like `Text`, `Select`, or `Checkbox`.
15+
- An event agenda where each timeslot could be a `Break`, `Presentation`, or `BreakoutSession`.
16+
<LightDarkImage
17+
srcLight="https://payloadcms.com/images/docs/fields/blocks.png"
18+
srcDark="https://payloadcms.com/images/docs/fields/blocks-dark.png"
19+
alt="Admin Panel screenshot of add Blocks drawer view"
20+
caption="Admin Panel screenshot of add Blocks drawer view"
21+
/>
2322

2423
To add a Blocks Field, set the `type` to `blocks` in your [Field Config](./overview):
2524

@@ -37,7 +36,11 @@ export const MyBlocksField: Field = {
3736
}
3837
```
3938

40-
## Config Options
39+
This page is divided into two parts: first, the settings of the Blocks Field, and then the settings of the blocks inside it.
40+
41+
## Block Field
42+
43+
### Config Options
4144

4245
| Option | Description |
4346
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -62,7 +65,7 @@ export const MyBlocksField: Field = {
6265

6366
_\* An asterisk denotes that a property is required._
6467

65-
## Admin Options
68+
### Admin Options
6669

6770
To customize the appearance and behavior of the Blocks Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
6871

@@ -80,12 +83,10 @@ export const MyBlocksField: Field = {
8083

8184
The Blocks Field inherits all of the default admin options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
8285

83-
| Option | Description |
84-
| ---------------------- | -------------------------------------------------------------------------- |
85-
| **`group`** | Text or localization object used to group this Block in the Blocks Drawer. |
86-
| **`initCollapsed`** | Set the initial collapsed state |
87-
| **`isSortable`** | Disable order sorting by setting this value to `false` |
88-
| **`disableBlockName`** | Hide the blockName field by setting this value to `true` |
86+
| Option | Description |
87+
| ------------------- | ------------------------------------------------------ |
88+
| **`initCollapsed`** | Set the initial collapsed state |
89+
| **`isSortable`** | Disable order sorting by setting this value to `false` |
8990

9091
#### Customizing the way your block is rendered in Lexical
9192

@@ -132,7 +133,9 @@ import {
132133
} from '@payloadcms/richtext-lexical/client'
133134
```
134135

135-
## Block Configs
136+
## Blocks Items
137+
138+
### Config Options
136139

137140
Blocks are defined as separate configs of their own.
138141

@@ -149,74 +152,45 @@ Blocks are defined as separate configs of their own.
149152
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
150153
| **`slug`** \* | Identifier for this block type. Will be saved on each block as the `blockType` property. |
151154
| **`fields`** \* | Array of fields to be stored in this block. |
152-
| **`labels`** | Customize the block labels that appear in the Admin dashboard. Auto-generated from slug if not defined. |
155+
| **`labels`** | Customize the block labels that appear in the Admin dashboard. Auto-generated from slug if not defined. Alternatively you can use `admin.components.Label` for greater control. |
153156
| **`imageURL`** | Provide a custom image thumbnail to help editors identify this block in the Admin UI. |
154157
| **`imageAltText`** | Customize this block's image thumbnail alt text. |
155158
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
156159
| **`graphQL.singularName`** | Text to use for the GraphQL schema name. Auto-generated from slug if not defined. NOTE: this is set for deprecation, prefer `interfaceName`. |
157160
| **`dbName`** | Custom table name for this block type when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from slug if not defined. |
158161
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
159162

160-
### Auto-generated data per block
163+
### Admin Options
161164

162-
In addition to the field data that you define on each block, Payload will store two additional properties on each block:
165+
Blocks are not fields, so they don’t inherit the base properties shared by all fields (not to be confused with the Blocks Field, documented above, which does). Here are their available admin options:
163166

164-
**`blockType`**
167+
| Option | Description |
168+
| ---------------------- | -------------------------------------------------------------------------- |
169+
| **`components.Block`** | Custom component for replacing the Block, including the header. |
170+
| **`components.Label`** | Custom component for replacing the Block Label. |
171+
| **`disableBlockName`** | Hide the blockName field by setting this value to `true`. |
172+
| **`group`** | Text or localization object used to group this Block in the Blocks Drawer. |
173+
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
165174

166-
The `blockType` is saved as the slug of the block that has been selected.
175+
### blockType, blockName, and block.label
167176

168-
**`blockName`**
177+
Each block stores two pieces of data alongside your fields. The `blockType` identifies which schema to use and it is exactly the block’s `slug`. The `blockName` is an optional label you can give to a block to make editing and scanning easier.
169178

170-
The Admin Panel provides each block with a `blockName` field which optionally allows editors to label their blocks for better editability and readability. This can be visually hidden via `admin.disableBlockName`.
179+
The **label** is shared by all blocks of the same type and is defined in the block config via `label` with a fallback to `slug`. On the other hand, the **blockName** is specific to each block individually. You can hide the editable name with `admin.disableBlockName`.
171180

172-
## Example
181+
If you provide `admin.components.Label`, that component replaces both the name and the label in the Admin UI.
173182

174-
`collections/ExampleCollection.js`
175-
176-
```ts
177-
import { Block, CollectionConfig } from 'payload'
178-
179-
const QuoteBlock: Block = {
180-
slug: 'Quote', // required
181-
imageURL: 'https://google.com/path/to/image.jpg',
182-
imageAltText: 'A nice thumbnail image to show what this block looks like',
183-
interfaceName: 'QuoteBlock', // optional
184-
fields: [
185-
// required
186-
{
187-
name: 'quoteHeader',
188-
type: 'text',
189-
required: true,
190-
},
191-
{
192-
name: 'quoteText',
193-
type: 'text',
194-
},
195-
],
196-
}
197-
198-
export const ExampleCollection: CollectionConfig = {
199-
slug: 'example-collection',
200-
fields: [
201-
{
202-
name: 'layout', // required
203-
type: 'blocks', // required
204-
minRows: 1,
205-
maxRows: 20,
206-
blocks: [
207-
// required
208-
QuoteBlock,
209-
],
210-
},
211-
],
212-
}
213-
```
183+
| Property | Scope | Source | Visible in UI | Notes |
184+
| ------------- | ---------- | ------------------------------------------ | ------------- | -------------------------------------------------------------------------------------------------- |
185+
| `blockType` | Each block | The block’s `slug` | Not a header | Used to resolve which block schema to render |
186+
| `blockName` | Each block | Editor input in the Admin | Yes | Optional label; hide with `admin.disableBlockName` or replace with custom `admin.components.Label` |
187+
| `block.label` | Block type | `label` in block config or `slug` fallback | Yes | Shared by all blocks of that type. Can be replaced with custom `admin.components.Label` |
214188

215-
## Custom Components
189+
### Custom Components
216190

217-
### Field
191+
#### Field
218192

219-
#### Server Component
193+
##### Server Component
220194

221195
```tsx
222196
import type React from 'react'
@@ -240,7 +214,7 @@ export const CustomBlocksFieldServer: BlocksFieldServerComponent = ({
240214
}
241215
```
242216

243-
#### Client Component
217+
##### Client Component
244218

245219
```tsx
246220
'use client'
@@ -253,9 +227,9 @@ export const CustomBlocksFieldClient: BlocksFieldClientComponent = (props) => {
253227
}
254228
```
255229

256-
### Label
230+
#### Label
257231

258-
#### Server Component
232+
##### Server Component
259233

260234
```tsx
261235
import React from 'react'
@@ -276,7 +250,7 @@ export const CustomBlocksFieldLabelServer: BlocksFieldLabelServerComponent = ({
276250
}
277251
```
278252

279-
#### Client Component
253+
##### Client Component
280254

281255
```tsx
282256
'use client'
@@ -299,19 +273,46 @@ export const CustomBlocksFieldLabelClient: BlocksFieldLabelClientComponent = ({
299273
}
300274
```
301275

302-
### Row Label
303-
304-
```tsx
305-
'use client'
276+
## Example
306277

307-
import { useRowLabel } from '@payloadcms/ui'
278+
`collections/ExampleCollection.js`
308279

309-
export const BlockRowLabel = () => {
310-
const { data, rowNumber } = useRowLabel<{ title?: string }>()
280+
```ts
281+
import { Block, CollectionConfig } from 'payload'
311282

312-
const customLabel = `${data.type} ${String(rowNumber).padStart(2, '0')} `
283+
const QuoteBlock: Block = {
284+
slug: 'Quote', // required
285+
imageURL: 'https://google.com/path/to/image.jpg',
286+
imageAltText: 'A nice thumbnail image to show what this block looks like',
287+
interfaceName: 'QuoteBlock', // optional
288+
fields: [
289+
// required
290+
{
291+
name: 'quoteHeader',
292+
type: 'text',
293+
required: true,
294+
},
295+
{
296+
name: 'quoteText',
297+
type: 'text',
298+
},
299+
],
300+
}
313301

314-
return <div>Custom Label: {customLabel}</div>
302+
export const ExampleCollection: CollectionConfig = {
303+
slug: 'example-collection',
304+
fields: [
305+
{
306+
name: 'layout', // required
307+
type: 'blocks', // required
308+
minRows: 1,
309+
maxRows: 20,
310+
blocks: [
311+
// required
312+
QuoteBlock,
313+
],
314+
},
315+
],
315316
}
316317
```
317318

0 commit comments

Comments
 (0)