Docs

This page isn't translated yet

next

Field helpers

rangeField, slugField, buttonGroupField, colorSelectField, icon fields, drawerField, messageField, richTextField, keyField.

On this page

Field helpers build Payload fields with Systhema's Admin components. Import them from @systhemaui/payload/fields, except richTextField, which comes from the package root.

rangeFieldLink to this section

Slider-style number input with markers and previews.

rangeField({
  name: 'padding',
  min: 0,
  max: 6,
  defaultValue: 2,
  showPreview: true,
  markers: [
    { value: 0, label: '0' },
    { value: 2, label: 'Default' },
    { value: 6, label: 'Max' },
  ],
})

slugField / nestedSlugFieldLink to this section

Auto-generated slug fields with a lock toggle. The nested variant also returns a fullPath field for parent/child collections.

A slug that formats to nothing (an empty title, whitespace, punctuation only) is stored as null, not ''. Posts, Categories and Tags carry a unique slug index, and NULLs do not collide, so any number of unfinished drafts can exist side by side and a blank draft can be moved to Trash and restored. The same rule applies to a draft version that stored an empty string before this behaviour existed: the next write, including a metadata-only one, stores null. Non-empty slugs stay unique and are never regenerated by trashing or restoring.

const [slug, slugLock] = slugField('title', { slugOverrides: { required: true } }, '/blog')

const [slug2, slugLock2, fullPath] = nestedSlugField('title', {}, '/docs')
// Use as: fields: [{ name: 'title', type: 'text' }, slug, slugLock]

buttonGroupFieldLink to this section

Button-group input (better UX than a select for short option sets).

In buttonGroupField, colorSelectField and iconGroupField, an option label made with systhemaLabel() or with the label() of your own definePayloadAdminTranslations() definition follows the current Admin language. Any other label function is resolved once on the server and can keep the language that first loaded the form, so use a translation-definition label or a per-language record ({ en: 'Left', fr: 'Gauche' }) for translated options.

buttonGroupField({
  name: 'alignment',
  options: [
    { label: 'Left', value: 'left' },
    { label: 'Center', value: 'center' },
    { label: 'Right', value: 'right' },
  ],
  defaultValue: 'left',
  hideWhenNoChoice: true,
})

colorSelectFieldLink to this section

Color picker that previews each option. Often built dynamically from your design tokens.

import { getResolvedValue, getTokens } from '@systhemaui/core'
const { colorSystem } = getTokens()

colorSelectField({
  name: 'theme',
  label: 'Color theme',
  options: Object.keys(colorSystem || {}).map((key) => ({
    color: getResolvedValue(colorSystem, 'layout.bg.default', key, true) as string,
    value: key,
    label: key,
  })),
})

iconGroupField / iconPickerField / faIconPickerFieldLink to this section

iconGroupField({
  name: 'textAlign',
  options: [
    { html: '<svg>...</svg>', value: 'left', label: 'Left' },
    /* ... */
  ],
})

// Each option provides either `html` (an SVG icon, rendered as before) or
// `char` (a plain glyph rendered as text). `appearance: 'tiles'` swaps the
// default joined-buttons look for a Yoast-style wrapping grid of rounded
// tiles with a check badge on the selected one — used by the SEO tab's
// title separator picker (see below).
iconGroupField({
  name: 'titleSeparator',
  appearance: 'tiles',
  options: [{ value: 'dash', char: '-', label: 'dash' } /* ... */],
})

iconPickerField({
  name: 'icon',
  // `packs` restricts/extends the packs for this picker (same shape as the
  // plugin-wide `icons` option). Omit to inherit the admin-wide packs.
  packs: {
    custom: [{ id: 'company', label: 'Company', icons: { logo: '<svg>...</svg>' } }],
  },
})

// Pre-configured Font Awesome variant.
faIconPickerField({ name: 'icon' })

drawerFieldLink to this section

Wrap fields in a drawer/dialog for advanced/optional settings.

drawerField({
  label: 'Advanced settings',
  drawerID: 'mediaAdvanced',
  appearance: 'button',
  fields: [
    { name: 'lazy', type: 'checkbox' },
    { name: 'priority', type: 'checkbox' },
  ],
})

A label made with systhemaLabel() (or a definePayloadAdminTranslations() definition's label()) is translated in the browser, so the drawer button and title follow the current Admin language. Any other label function is resolved once on the server and can keep the language that first loaded the form.

messageFieldLink to this section

Inline notice rendered in the admin (no value stored).

messageField({
  type: 'warning',
  title: 'Important',
  content: 'This setting affects performance.',
})
// type: 'none' | 'highlight' | 'info' | 'warning' | 'success' | 'error'

richTextFieldLink to this section

Wrapper around Payload's lexical editor with sensible Systhema defaults.

richTextField({
  name: 'content',
  editor: regionLexicalEditor(),
  required: true,
})
// Also exports: defaultRichTextValue, ensureNonEmptyRichTextFields

keyFieldLink to this section

Auto-formatted key field — useful for stable identifiers (slugs that don't include /).