| title |
aliases |
tags |
sources |
created |
updated |
| Tabs Field |
|
| payloadcms |
| fields |
| layout |
| admin-ui |
|
|
2026-05-15 |
2026-05-15 |
Overview
The Tabs Field is a presentational layout field that organizes sub-fields into a tabbed Admin UI. It has no database impact by default — unless a tab has a name, which groups its fields into a nested object in the DB.
import type { Field } from 'payload'
export const MyTabsField: Field = {
type: 'tabs',
tabs: [
{
label: 'Hero',
fields: [...],
},
{
name: 'layout', // creates layout.* in DB
label: 'Page Layout',
fields: [...],
},
],
}
Config Options
| Option |
Required |
Description |
tabs |
✅ |
Array of tab objects |
admin |
|
Admin-specific config |
custom |
|
Plugin extension point |
Per-Tab Config
| Option |
Required |
Description |
fields |
✅ |
Fields rendered inside the tab |
label |
✅ (if no name) |
Tab display label; defaults to name-as-words |
name |
|
Groups field data into a DB object |
description |
|
Renders descriptive text above fields in the tab |
interfaceName |
|
Creates a reusable TypeScript interface (requires name) |
virtual |
|
true to exclude from DB, or a path to link a virtual relationship |
admin |
|
Supports condition and description |
id |
|
Required if admin.condition is used on an unnamed tab |
Named vs Unnamed Tabs
| Aspect |
Unnamed tab |
Named tab |
| DB storage |
Fields stored flat |
Fields nested under tabName.* |
interfaceName |
❌ |
✅ available |
| TS access |
doc.someField |
doc.tabName.fieldName |
Conditional Tabs
Tabs support the same condition function as fields:
{
type: 'tabs',
tabs: [
{
label: 'Always Visible',
fields: [{ name: 'showExtra', type: 'checkbox' }],
},
{
label: 'Conditional Tab',
admin: {
condition: (data) => !!data.showExtra,
},
fields: [{ name: 'extraField', type: 'text' }],
},
],
}
- When condition returns
false, the tab and all its fields are hidden from the Admin Panel
- If the currently active tab becomes hidden, Payload auto-switches to the next visible tab
- Unnamed tabs using
admin.condition require an id (auto-generated if omitted)
Full Example
export const ExampleCollection: CollectionConfig = {
slug: 'example-collection',
fields: [
{
type: 'tabs',
tabs: [
{
label: 'Tab One Label',
description: 'Appears inside the tab, above fields.',
fields: [
{ name: 'someTextField', type: 'text', required: true },
],
},
{
name: 'tabTwo',
label: 'Tab Two Label',
interfaceName: 'TabTwo',
fields: [
{ name: 'numberField', type: 'number', required: true },
// accessed as tabTwo.numberField
],
},
],
},
],
}
Key Takeaways
- Tabs are presentational-only by default — no DB column created
- Adding a
name to a tab creates a nested object in the database
interfaceName generates a reusable TypeScript type (requires name)
- Tabs support
admin.condition for dynamic show/hide — unnamed tabs need an id
- If the active tab is hidden by a condition, Payload auto-switches to the next visible tab
- Compare with wiki/payloadcms/fields-collapsible (accordion) and wiki/payloadcms/fields-row (horizontal layout) — all three are presentational-only
- Named tabs behave like wiki/payloadcms/fields-group — fields stored under a namespaced key
Related
Sources