Fields

Reusable Fields

For fields that occur more than once within the codebase, they should be abstract within src/fields. Every field that is configurable should accept overrides so the caller can override particular parts of the fieldd.

FAQs Example

 1import { ArrayField, deepMerge, Field } from 'payload'
 2
 3export type FAQsFieldArgs = {
 4	overrides?: Partial<Omit<ArrayField, 'type'>>
 5}
 6
 7export const FAQsField = (args?: FAQsFieldArgs): Field => {
 8	return deepMerge<ArrayField, Omit<ArrayField, 'type'>>(
 9		{
10			name: 'faqs',
11			label: 'FAQs',
12			type: 'array',
13			fields: [
14				{
15					name: 'question',
16					label: 'Question',
17					type: 'text',
18					required: true,
19					admin: {
20						description: 'Add a question for the FAQ item.',
21					},
22				},
23				{
24					name: 'answer',
25					type: 'textarea',
26					label: 'Answer',
27					required: true,
28					admin: {
29						description: 'Add a content (answer) for the FAQ item.',
30					},
31				},
32			],
33		},
34		args?.overrides || {},
35	)
36}

Slug Example

 1export const SlugField: Slug = (fieldToUse = 'title', overrides = {}) => {
 2	const checkBoxField = deepMerge<CheckboxField, Partial<CheckboxField>>(
 3		{
 4			name: 'slugLock',
 5			type: 'checkbox',
 6			defaultValue: true,
 7			admin: {hidden: true, position: 'sidebar'},
 8		},
 9		checkboxOverrides || {},
10	)
11
12	const slugField = deepMerge<TextField, Partial<TextField>>(
13		{
14			name: 'slug',
15			type: 'text',
16			index: true,
17			unique: true,
18			required: true,
19			hooks: {
20				beforeValidate: [formatSlugHook(fieldToUse)],
21			},
22			admin: {
23				position: 'sidebar',
24				components: {
25					Field: {
26						path: '/fields/Slug/Component#Component',
27						clientProps: {fieldToUse, checkboxFieldPath: checkBoxField.name},
28					},
29				},
30			},
31		},
32		slugOverrides || {},
33	)
34
35	return [slugField, checkBoxField]
36}

Key Patterns

  • Use deepMerge for composing field configurations with overrides.
  • Provide default values but allow customisation via overrides.
  • Co-locate fields that work together (e.g., slug and slugLock).
  • Custom components via path references for admin UI customisation.

Width

Use admin.width to control field widths in rows:

 1{
 2	type: 'row',
 3	fields: [
 4		{
 5			name: 'fieldOne',
 6			type: 'text',
 7			admin: { width: '50%' },
 8		},
 9		{
10			name: 'fieldTwo',
11			type: 'text',
12			admin: { width: '50%' },
13		},
14	],
15}
Last modified: 27/10/2025 2022-2025 ©ainsley.dev, All rights reserved.