BuildWithMatija
  1. Home
  2. Blog
  3. Payload
  4. Payload CMS @payloadcms/ui Component Reference

Payload CMS @payloadcms/ui Component Reference

Quick lookup for Payload Admin UI elements, field wrappers, document controls, and hooks

13th November 2025·Updated on:22nd September 2026·MŽMatija Žiberna·
Payload
Payload CMS @payloadcms/ui Component Reference

Evaluating Payload CMS Implementation Costs?

Scope design, content structure, and migration hours to estimate a realistic production timeline and hosting setup.

Try the Cost EstimatorGet a Second Opinion

📚 Comprehensive Payload CMS Guides

Detailed Payload guides with field configuration examples, custom components, and workflow optimization tips to speed up your CMS development process.

No spam. Unsubscribe anytime.

Related Posts:

  • •How to Create Dynamic Cross-Collection Dropdowns in Payload CMS v3
  • •Payload CMS Custom Admin Fields and Views: A Guide to @payloadcms/ui
  • •How to Dynamically Filter Payload CMS Relationship Fields Based on Sibling Data in Array Fields
📄View markdown version
0

Frequently Asked Questions

Comments

About the author

Matija Žiberna

Matija Žiberna

Full-stack developer, co-founder

AboutResume

Self-taught full-stack developer sharing lessons from building software and startups.

I'm Matija Žiberna, a self-taught full-stack developer and co-founder passionate about building products, writing clean code, and figuring out how to turn ideas into businesses. I write about web development with Next.js, lessons from entrepreneurship, and the journey of learning by doing. My goal is to provide value through code—whether it's through tools, content, or real-world software.

You might be interested in

How to Create Dynamic Cross-Collection Dropdowns in Payload CMS v3
How to Create Dynamic Cross-Collection Dropdowns in Payload CMS v3

29th September 2025

Payload CMS Custom Admin Fields and Views: A Guide to @payloadcms/ui
Payload CMS Custom Admin Fields and Views: A Guide to @payloadcms/ui

16th October 2025

How to Dynamically Filter Payload CMS Relationship Fields Based on Sibling Data in Array Fields
How to Dynamically Filter Payload CMS Relationship Fields Based on Sibling Data in Array Fields

12th October 2025

Contents

  • Import Rules for `@payloadcms/ui`
  • Component Quick Finder
  • Core Elements and Field Primitives
  • Button
  • ReactSelect
  • TextInput
  • FieldLabel, FieldDescription, and FieldError
  • DatePickerField
  • Collapsible
  • DraggableSortable
  • Popup and PopupButtonList
  • Banner, Pill, and toast
  • ConfirmationModal and useModal
  • Card, Table, Tooltip, and Drawer
  • Payload Field Wrappers
  • SelectInput
  • RelationshipField
  • DateTimeField
  • CheckboxField
  • ArrayField
  • BlocksField
  • UploadField
  • TextareaInput
  • Admin and Document Controls
  • DocumentControls
  • StickyToolbar and Gutter
  • PublishButton, SaveButton, and SaveDraftButton
  • DeleteDocument and DuplicateDocument
  • DocumentDrawer and ListDrawer
  • Hooks
  • useField
  • useFormFields
  • useConfig
  • useAuth
  • useModal
  • Primitive or Field Wrapper?
  • Inspecting the Version Installed in Your Project
  • Reference Maintenance Notes
On this page:
  • Import Rules for `@payloadcms/ui`
  • Component Quick Finder
  • Core Elements and Field Primitives
  • Payload Field Wrappers
  • Admin and Document Controls
Build with Matija logo

Build with Matija

Senior-led B2B websites, applications, content systems, and digital infrastructure. Business-first, full-stack, AI-assisted, no handoffs.

Services

  • B2B Website Development
  • CMS Architecture Review & Platform Blueprint
  • Next.js + Payload Advisory
  • AI Integration & Implementation

Resources

  • CMS Hub
  • B2B Website Strategy
  • E-commerce Hub
  • Blog
  • Case Studies
  • About Matija

Payload CMS

  • Payload CMS Developer
  • Payload CMS Migration
  • Payload CMS Demos
  • All Payload CMS Resources

Discuss your project

Planning a rebuild, migration, application, workflow change, or platform decision? Start with the business problem and the system behind it.

Book a discovery callContact me →
© 2026Build with Matija•All rights reserved•Privacy Policy•Terms of Service
BuildWithMatija
Get In Touch

This is the lookup companion to my guide to building custom Payload CMS admin fields and views. 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

NeedUseCategory
Standard action buttonButtonElement
Searchable selectReactSelectElement
Native text inputTextInputField primitive
Field labelFieldLabelField primitive
Helper textFieldDescriptionField primitive
Validation messageFieldErrorField primitive
Calendar inputDatePickerFieldElement
Expandable sectionCollapsibleElement
Reorderable rowsDraggableSortableElement
Action menuPopup + PopupButtonListElement
Warning or info messageBannerElement
Status badgePillElement
Success or error notificationtoastUtility
Confirmation stepConfirmationModal + useModalElement + hook
Clickable summary tileCardElement
Data tableTableElement
Hover helpTooltipElement
Side overlayDrawer / DocumentDrawer / ListDrawerElement / admin
Full select field behaviorSelectInputField wrapper
Relationship pickerRelationshipFieldField wrapper
Date field with Payload behaviorDateTimeFieldField wrapper
Checkbox fieldCheckboxFieldField wrapper
Native array fieldArrayFieldField wrapper
Native blocks fieldBlocksFieldField wrapper
Upload fieldUploadFieldField wrapper
Connect to one fielduseFieldHook
Subscribe to selected form stateuseFormFieldsHook
Read Payload configuseConfigHook
Read current admin useruseAuthHook

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.

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 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 needPrefer
Payload styling inside a compound custom UIPrimitives such as TextInput, ReactSelect, Button
Native configured field behaviorField wrappers such as RelationshipField, DateTimeField, UploadField
Full document operationsAdmin controls such as DocumentControls, SaveButton, PublishButton
Custom form state tied to one fielduseField
Read other values in the same formuseFormFields

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 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. To see broader production examples, explore the Payload CMS demos.

Thanks, Matija

Comments