140 lines
4.5 KiB
Markdown
140 lines
4.5 KiB
Markdown
---
|
|
title: "Tabs Field"
|
|
aliases: [tabs-field, payload-tabs]
|
|
tags: [payloadcms, fields, layout, admin-ui]
|
|
sources: [raw/fields__tabs.md]
|
|
created: 2026-05-15
|
|
updated: 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.
|
|
|
|
```ts
|
|
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:
|
|
|
|
```ts
|
|
{
|
|
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
|
|
|
|
```ts
|
|
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|Collapsible Field]] (accordion) and [[wiki/payloadcms/fields-row|Row Field]] (horizontal layout) — all three are presentational-only
|
|
- Named tabs behave like [[wiki/payloadcms/fields-group|Group Field]] — fields stored under a namespaced key
|
|
|
|
## Related
|
|
|
|
- [[wiki/payloadcms/fields-collapsible|Collapsible Field]] — accordion-style grouping (no nesting)
|
|
- [[wiki/payloadcms/fields-group|Group Field]] — named nesting without tabs UI
|
|
- [[wiki/payloadcms/fields-row|Row Field]] — horizontal layout, no DB column
|
|
- [[wiki/payloadcms/fields-overview|Fields Overview]] — `admin.condition`, virtual fields, custom components
|
|
- [[wiki/payloadcms/custom-components-authoring|Custom Components]] — replacing tab UI with custom React
|
|
|
|
## Sources
|
|
|
|
- `raw/fields__tabs.md` — https://payloadcms.com/docs/fields/tabs
|