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.