---
title: "Payload CMS @payloadcms/ui Component Reference"
slug: "payload-admin-ui-components-glossary-v3-6"
published: "2025-11-13"
updated: "2026-09-22"
validated: "2026-09-02"
categories:
  - "Payload"
tags:
  - "Payload CMS @payloadcms/ui"
  - "Payload admin UI components"
  - "Payload UI component reference"
  - "Payload custom admin"
  - "useField"
  - "useFormFields"
  - "ReactSelect"
  - "Payload admin hooks"
llm-intent: "reference"
audience-level: "advanced"
framework-versions:
  - "payload@3.6+"
  - "next@13+ (App Router / src/app)"
  - "react@18+"
  - "typescript@4.8+"
status: "stable"
llm-purpose: "Choose and import reusable Payload Admin UI components, field wrappers, document controls, and hooks correctly."
llm-prereqs:
  - "Payload CMS v3"
  - "React and TypeScript basics"
  - "Basic familiarity with Payload custom components"
llm-outputs:
  - "Choose the appropriate @payloadcms/ui abstraction for a custom admin interface"
  - "Use the correct Admin Panel versus frontend import pattern"
  - "Find common fields, elements, admin controls, and hooks quickly"
---

**Summary Triples**
- (@payloadcms/ui elements, are located under, node_modules/@payloadcms/ui/elements/<Component>)
- (Field primitives, are located under, node_modules/@payloadcms/ui/fields/<Component>)
- (Hooks (e.g., useField), should be imported from, '@payloadcms/ui' (package root))
- (Type definitions, can be inspected at, node_modules/@payloadcms/ui/dist/elements/*.d.ts and dist/fields/*.d.ts)
- (Source inspection, recommended action, open nearby index.js files to confirm transitions, context requirements, and composed children)
- (CSS classes shipped with package, should be reused, copy class names from the package's .scss files (e.g., array-field, pill, tooltip) instead of inventing new selectors)
- (Import conventions, for elements, import { Component } from '@payloadcms/ui/elements/Component')
- (Import conventions, for fields, import { Field } from '@payloadcms/ui/fields/Field')
- (Most components, are, safe to use in client and server components when used appropriately in Next.js App Router)
- (Custom admin extensions, should live in, Next.js (payload) routes under src/app to integrate with Payload admin chrome)
- (Maintenance rule, when bumping Payload, update version notes and component prop docs in the glossary)
- (Local examples, demonstrate composition, check src/components/fields/InventoryBatchBulkTable.tsx for real-world usage)

### {GOAL}
Choose and import reusable Payload Admin UI components, field wrappers, document controls, and hooks correctly.

### {PREREQS}
- Payload CMS v3
- React and TypeScript basics
- Basic familiarity with Payload custom components

### {STEPS}
1. Follow the detailed walkthrough in the article content below.

<!-- llm:goal="Choose and import reusable Payload Admin UI components, field wrappers, document controls, and hooks correctly." -->
<!-- llm:prereq="Payload CMS v3" -->
<!-- llm:prereq="React and TypeScript basics" -->
<!-- llm:prereq="Basic familiarity with Payload custom components" -->
<!-- llm:output="Choose the appropriate @payloadcms/ui abstraction for a custom admin interface" -->
<!-- llm:output="Use the correct Admin Panel versus frontend import pattern" -->
<!-- llm:output="Find common fields, elements, admin controls, and hooks quickly" -->

# Payload CMS @payloadcms/ui Component Reference
> Reference for Payload CMS @payloadcms/ui components, field wrappers, admin controls, hooks, import rules, and practical usage examples.
Matija Žiberna · 2025-11-13

This is the lookup companion to my [guide to building custom Payload CMS admin fields and views](/blog/payload-cms-custom-admin-ui-components-guide). Use the guide when you want the full implementation workflow. Use this page when you already know what you are building and need to find the Payload-native component, field wrapper, admin control, or hook that fits the job.

The reference focuses on reusable pieces from `@payloadcms/ui` that come up repeatedly in production custom admin work. It is not a substitute for the types installed in your project. Payload's UI package evolves with Payload itself, so when a prop or export matters to production code, verify it against your installed version.

## Import Rules for `@payloadcms/ui`

The most important rule is context.

Inside the Payload Admin Panel, import client UI components and hooks from the package entry point:

```tsx
'use client'

import {
  Button,
  ReactSelect,
  TextInput,
  useField,
} from '@payloadcms/ui'
```

Payload also exposes `@payloadcms/ui/rsc` and `@payloadcms/ui/shared` for specific server or shared cases. Use those when the component or Payload documentation calls for them.

For frontend code outside the Payload Admin Panel, use deep imports so you do not bundle the entire admin UI package:

```tsx
import { Button } from '@payloadcms/ui/elements/Button'
```

Do not copy that deep-import pattern back into Admin Panel custom components. Inside admin code, keep reusable client UI imports on `@payloadcms/ui`.

## Component Quick Finder

| Need | Use | Category |
| --- | --- | --- |
| Standard action button | `Button` | Element |
| Searchable select | `ReactSelect` | Element |
| Native text input | `TextInput` | Field primitive |
| Field label | `FieldLabel` | Field primitive |
| Helper text | `FieldDescription` | Field primitive |
| Validation message | `FieldError` | Field primitive |
| Calendar input | `DatePickerField` | Element |
| Expandable section | `Collapsible` | Element |
| Reorderable rows | `DraggableSortable` | Element |
| Action menu | `Popup` + `PopupButtonList` | Element |
| Warning or info message | `Banner` | Element |
| Status badge | `Pill` | Element |
| Success or error notification | `toast` | Utility |
| Confirmation step | `ConfirmationModal` + `useModal` | Element + hook |
| Clickable summary tile | `Card` | Element |
| Data table | `Table` | Element |
| Hover help | `Tooltip` | Element |
| Side overlay | `Drawer` / `DocumentDrawer` / `ListDrawer` | Element / admin |
| Full select field behavior | `SelectInput` | Field wrapper |
| Relationship picker | `RelationshipField` | Field wrapper |
| Date field with Payload behavior | `DateTimeField` | Field wrapper |
| Checkbox field | `CheckboxField` | Field wrapper |
| Native array field | `ArrayField` | Field wrapper |
| Native blocks field | `BlocksField` | Field wrapper |
| Upload field | `UploadField` | Field wrapper |
| Connect to one field | `useField` | Hook |
| Subscribe to selected form state | `useFormFields` | Hook |
| Read Payload config | `useConfig` | Hook |
| Read current admin user | `useAuth` | Hook |

## Core Elements and Field Primitives

### Button

Use `Button` for actions that should match Payload's admin styling and interaction states.

```tsx
import { Button } from '@payloadcms/ui'

<Button
  buttonStyle="primary"
  size="medium"
  icon="plus"
  iconPosition="left"
  onClick={onAddRow}
>
  Add another row
</Button>
```

Common `buttonStyle` values include `primary`, `secondary`, `error`, `subtle`, `pill`, `tab`, `icon-label`, `transparent`, and `none`. Use one dominant primary action per local interface where possible.

### ReactSelect

Use `ReactSelect` when you need Payload styling around a searchable or clearable select without adopting the full relationship field behavior.

```tsx
import { ReactSelect, type Option } from '@payloadcms/ui'

<ReactSelect
  options={products}
  value={selectedProduct}
  isSearchable
  isClearable
  onChange={(option) => setSelectedProduct(option as Option<number> | null)}
/>
```

Use `RelationshipField` instead when you need Payload's relationship-specific behavior such as collection-aware fetching or create/edit flows.

### TextInput

`TextInput` is the lightweight Payload-styled input primitive for custom forms and compound fields.

```tsx
import { TextInput } from '@payloadcms/ui'

<TextInput
  path={`${row.id}-totalStock`}
  value={row.totalStock ?? ''}
  onChange={(event) => updateStock(row.id, event.target.value)}
  placeholder="Enter quantity"
/>
```

Keep every `path` stable and unique within the form.

### FieldLabel, FieldDescription, and FieldError

Use these primitives instead of recreating Payload's field chrome with custom typography and spacing.

```tsx
import {
  FieldDescription,
  FieldError,
  FieldLabel,
} from '@payloadcms/ui'

<FieldLabel label="Bulk inventory batches" required />
<FieldDescription
  path="bulkRows"
  description="Add one row per product variant."
/>
<FieldError message="Quantity must be greater than zero" />
```

### DatePickerField

Use `DatePickerField` when you want the calendar UI without adopting a complete configured Payload date field.

```tsx
import { DatePickerField } from '@payloadcms/ui'

<DatePickerField
  value={receivedDate}
  onChange={setReceivedDate}
  placeholder="Select received date"
/>
```

Use `DateTimeField` when you want the fuller Payload field behavior around date configuration, validation, and form integration.

### Collapsible

Use `Collapsible` to group complex custom content into sections that behave like Payload's expandable admin UI.

```tsx
import { Collapsible } from '@payloadcms/ui'

<Collapsible
  initCollapsed={false}
  header={<span>{rowTitle}</span>}
>
  {children}
</Collapsible>
```

### DraggableSortable

Use `DraggableSortable` for reorderable custom rows.

```tsx
import { DraggableSortable } from '@payloadcms/ui'

<DraggableSortable
  ids={rows.map((row) => row.id)}
  className="array-field__draggable-rows"
  onDragEnd={({ moveFromIndex, moveToIndex }) => {
    reorderRows(moveFromIndex, moveToIndex)
  }}
>
  {rows.map(renderRow)}
</DraggableSortable>
```

The IDs must remain unique and aligned with the rendered row order.

### Popup and PopupButtonList

Use this pair for action menus that should inherit Payload's positioning and menu interaction patterns.

```tsx
import { Popup, PopupButtonList } from '@payloadcms/ui'

<Popup
  button={<Button buttonStyle="secondary">Actions</Button>}
  buttonType="custom"
  horizontalAlign="right"
  verticalAlign="bottom"
>
  <PopupButtonList.ButtonGroup>
    <PopupButtonList.Button onClick={handleDuplicate}>
      Duplicate
    </PopupButtonList.Button>
    <PopupButtonList.Button onClick={handleArchive}>
      Archive
    </PopupButtonList.Button>
  </PopupButtonList.ButtonGroup>
</Popup>
```

### Banner, Pill, and toast

These cover three different feedback levels: persistent message, compact status, and transient notification.

```tsx
import { Banner, Pill, toast } from '@payloadcms/ui'

<Banner type="warning">This document has unsaved changes.</Banner>
<Pill>Draft</Pill>

toast.success('Document saved')
toast.error('Save failed')
```

### ConfirmationModal and useModal

Use `ConfirmationModal` for destructive or consequential custom actions instead of creating a parallel modal pattern.

```tsx
import { Button, ConfirmationModal, useModal } from '@payloadcms/ui'

const modalSlug = `approval-${requestId}-reject`
const { openModal } = useModal()

<Button onClick={() => openModal(modalSlug)}>Reject</Button>

<ConfirmationModal
  modalSlug={modalSlug}
  heading="Reject this request?"
  body={<p>This will notify the requester.</p>}
  confirmLabel="Reject"
  confirmingLabel="Rejecting..."
  onConfirm={() => rejectRequest(requestId)}
/>
```

Give each modal a stable, unique slug. This matters when the same action can appear on multiple rows or documents.

### Card, Table, Tooltip, and Drawer

These are useful building blocks when the custom interface moves beyond individual fields.

```tsx
import {
  Card,
  Drawer,
  DrawerToggler,
  Table,
  Tooltip,
} from '@payloadcms/ui'
```

`Card` works well for dashboard or summary navigation. `Table` is useful for compact list-style data. `Tooltip` adds Payload-native hover or focus help. `Drawer` and `DrawerToggler` provide a generic side overlay pattern when you do not need the higher-level document or list drawers.

## Payload Field Wrappers

Use field wrappers when you want more than matching visuals. These components carry more of Payload's configured field behavior and form integration.

```tsx
import {
  ArrayField,
  BlocksField,
  CheckboxField,
  DateTimeField,
  RelationshipField,
  SelectInput,
  TextareaInput,
  UploadField,
} from '@payloadcms/ui'
```

### SelectInput

Use `SelectInput` for a Payload-managed select field when you already have the relevant field options and want the normal select behavior rather than a standalone `ReactSelect`.

### RelationshipField

Use `RelationshipField` when the value is a relationship to one or more Payload collections and you want collection-aware behavior rather than manually fetching options.

In custom field work, prefer passing the real client field configuration supplied by Payload rather than reconstructing a partial field config by hand.

### DateTimeField

Use `DateTimeField` when the custom interface should behave like a configured Payload date field. Use `DatePickerField` when you only need the calendar input primitive.

### CheckboxField

Use `CheckboxField` when you need the complete Payload checkbox field behavior. For a custom compound UI, verify whether the field wrapper or a lighter primitive better matches your state model.

### ArrayField

Use `ArrayField` when the native array experience already solves the problem. If the data entry workflow needs a radically different layout, reuse lower-level pieces such as `Collapsible`, `DraggableSortable`, `Button`, and the field primitives instead of rebuilding every visual detail.

### BlocksField

Use `BlocksField` when you want Payload's standard block stack and chooser. If you are designing the schemas those blocks manage, see [Creating Custom Block Types in Payload CMS](/blog/create-custom-block-types-payload-cms).

### UploadField

Use `UploadField` when you need the standard Payload upload relationship, preview, and field behavior.

### TextareaInput

Use `TextareaInput` as the lightweight multi-line text primitive inside compound custom interfaces.

## Admin and Document Controls

Payload also exposes higher-level controls that are useful when building complete custom views or document experiences.

```tsx
import {
  DeleteDocument,
  DocumentControls,
  DocumentDrawer,
  DuplicateDocument,
  Gutter,
  ListDrawer,
  PublishButton,
  SaveButton,
  SaveDraftButton,
  StickyToolbar,
} from '@payloadcms/ui'
```

### DocumentControls

Use `DocumentControls` when a custom document view should expose the familiar save, publish, and related document actions provided by Payload. It expects the relevant document context, so it is not a generic standalone toolbar.

### StickyToolbar and Gutter

`StickyToolbar` gives custom views the same sticky header behavior as Payload's edit interfaces. `Gutter` keeps custom content aligned with the Admin Panel's standard horizontal spacing.

### PublishButton, SaveButton, and SaveDraftButton

These are useful when you need individual document actions rather than the complete `DocumentControls` group. Prefer them over duplicating Payload's save or publish interaction logic.

### DeleteDocument and DuplicateDocument

These provide the standard document-level destructive and duplication flows. Use them when your custom document interface still lives inside Payload's document context.

### DocumentDrawer and ListDrawer

Use these higher-level drawers when you want Payload's document or collection list experience inside a side panel. Use the generic `Drawer` when the overlay contains your own custom content instead.

## Hooks

### useField

`useField` connects a client custom component to one field in Payload's form state.

```tsx
'use client'

import { useField } from '@payloadcms/ui'

const { value, setValue, showError } = useField<string>({
  path: 'internalCode',
})
```

Use it when the custom component owns or edits a specific field value.

### useFormFields

Use `useFormFields` when a component needs to subscribe to selected form state outside its own field. A selector keeps the subscription narrow and reduces unnecessary re-renders.

```tsx
'use client'

import { useFormFields } from '@payloadcms/ui'

const status = useFormFields(([fields]) => fields.status?.value)
```

Do not subscribe to the entire form when you only need one or two values.

### useConfig

`useConfig` exposes the current Payload client configuration inside Admin Panel client components.

```tsx
import { useConfig } from '@payloadcms/ui'

const { config } = useConfig()
```

Use it when the custom UI needs configuration context instead of hardcoded collection or server assumptions.

### useAuth

`useAuth` gives client admin components access to the authenticated Payload user.

```tsx
import { useAuth } from '@payloadcms/ui'

const { user } = useAuth()
```

For multi-tenant applications, the shape of the user record and its tenant memberships matters. [Why Payload CMS users should not be tenant-scoped](/blog/payload-cms-users-not-tenant-scoped) covers that architecture separately.

### useModal

`useModal` opens and closes modal instances by slug. Pair it with `ConfirmationModal` or other Payload modal components rather than maintaining a second modal state system.

## Primitive or Field Wrapper?

A useful rule is to choose the lowest abstraction that still gives you the Payload behavior you need.

| If you need | Prefer |
| --- | --- |
| Payload styling inside a compound custom UI | Primitives such as `TextInput`, `ReactSelect`, `Button` |
| Native configured field behavior | Field wrappers such as `RelationshipField`, `DateTimeField`, `UploadField` |
| Full document operations | Admin controls such as `DocumentControls`, `SaveButton`, `PublishButton` |
| Custom form state tied to one field | `useField` |
| Read other values in the same form | `useFormFields` |

This avoids two common problems: rebuilding behavior Payload already provides, or importing a heavyweight field wrapper when a small visual primitive would be simpler.

## Inspecting the Version Installed in Your Project

When a component is missing from this reference or a prop has changed, inspect your installed package rather than relying on an old blog post.

Useful places include:

```text
node_modules/@payloadcms/ui/dist/elements/
node_modules/@payloadcms/ui/dist/fields/
node_modules/@payloadcms/ui/dist/admin/
```

The generated `.d.ts` files are particularly useful because they describe the exports and props for the exact version in your lockfile.

Also keep the core Payload packages aligned on matching versions. If admin hooks or components behave as if their context is missing, duplicated or mismatched `payload` and `@payloadcms/*` packages are worth checking before debugging the component itself.

## Reference Maintenance Notes

This page intentionally stays narrower than the tutorial. New production patterns belong in the [custom admin UI guide](/blog/payload-cms-custom-admin-ui-components-guide) when they need explanation. New reusable exports belong here when they are useful as lookup entries.

When upgrading Payload:

- verify imports against the current Admin Panel guidance
- diff relevant `@payloadcms/ui` type definitions
- check whether field wrapper props changed
- verify hooks against the installed version
- re-test document controls inside real Payload context

For a worked implementation that combines these primitives into a production custom field, continue with the [Payload CMS Custom Admin Fields and Views guide](/blog/payload-cms-custom-admin-ui-components-guide). To see broader production examples, [explore the Payload CMS demos](/payload-cms-demos).

Thanks,
Matija

## LLM Response Snippet
```json
{
  "goal": "Choose and import reusable Payload Admin UI components, field wrappers, document controls, and hooks correctly.",
  "responses": [
    {
      "question": "What does the article \"Payload CMS Admin UI Components: Complete Glossary\" cover?",
      "answer": "Payload CMS admin UI components: quick reference of @payloadcms/ui elements and field primitives (v3.6+). Learn props, imports, and best practices — read…"
    }
  ]
}
```