eddev
Snippets

Type-Safe ACF Dropdowns

Register one enum field and use its generated TypeScript type

Use this when a CMS dropdown should become a narrow TypeScript type instead of a loose string.

For the fundamentals, see Custom Enums. For broader color-theme usage, see Color Schemes. For schema extension context, see Extending GraphQL.

Register The Enum Field Type

Put enum field registrations in backend field files. For a page color selector, use:

<?php

ED()->registerEnumFieldType("page-color", [
  "label" => "Page Color",
  "type" => "select",
  "allow_null" => 1,
  "options" => [
    "silver" => "Silver",
    "green" => "Green",
    "blue" => "Blue",
    "orange" => "Orange",
    "yellow" => "Yellow",
  ],
]);

type controls the underlying ACF UI. eddev supports select, button_group, radio, and checkbox; use select unless the field needs a different editing control. checkbox returns multiple values.

Add It Anywhere ACF Fields Are Used

Once registered, page-color is available as an ACF field type. Add it to a block field group, post type field group, options page, taxonomy, or any other ACF location the same way you would add a normal ACF field.

When that field is selected in GraphQL, codegen uses the enum field name to create a TypeScript type: page-color becomes PageColor. Current generated GraphQL exports include an Option suffix, so the import is PageColorOption.

Use The Generated Type In React

Keep the component API simple. Alias the generated type if the component wants the shorter PageColor name.

import type { PageColorOption } from "@generated-types"
import type { ReactNode } from "react"

type PageColor = PageColorOption

type Props = {
  color: PageColor
  title: string
  children: ReactNode
}

const colorClasses: Record<PageColor, string> = {
  silver: "theme-silver",
  green: "theme-green",
  blue: "theme-blue",
  orange: "theme-orange",
  yellow: "theme-yellow",
}

export function PageColorPanel(props: Props) {
  return (
    <section className={colorClasses[props.color]}>
      <h2>{props.title}</h2>
      {props.children}
    </section>
  )
}

Keep the PHP options and colorClasses in sync. If a new CMS option is added, TypeScript will force you to decide how it renders.

On this page