Docs/Developer Guide/Creating Field Groups
Creating Field Groups
Three ways to group fields together, depending on what you're grouping for: sections for an options panel, repeaters for "the same fields, several times", and the group type for inline layout.
Option panel sections
An options panel is registered with TPMeta_Options::set_args(), then one set_section() call per section — a section is a tab in the panel's admin page, and every field inside it belongs to that group.
add_action( 'init', function () {
$opt = 'mytheme_options';
TPMeta_Options::set_args( $opt, [
'menu_title' => 'Theme Options',
'page_title' => 'Theme Options',
'capability' => 'manage_options',
'output_css' => true,
'customizer_integration' => true,
] );
TPMeta_Options::set_section( $opt, [
'title' => 'General',
'id' => 'general',
'fields' => [
[ 'id' => 'accent_color', 'type' => 'colorpicker', 'label' => 'Accent',
'default' => '#3362FF',
'output' => [ [ 'selector' => 'a, .btn', 'property' => 'color' ] ] ],
],
] );
}, 5 );
Panels must register on the init hook (priority 5, before the builder loader runs). Registering later means the menu page never appears.
Use tpmeta/options/saved ($opt_name, $saved) or the per-panel tpmeta/options/{opt_name}/saved ($saved) — ideal for busting a cache. Full list: Hooks & Filters.
Repeaters — repeat a group of fields
A repeater field lets an editor add unlimited rows of the same sub-fields. Nest a fields array inside the repeater definition, exactly like a metabox's top-level fields array:
[
'id' => 'social_links',
'type' => 'repeater',
'label' => 'Social Links',
'columns' => 2,
'default' => [],
'fields' => [
[ 'id' => 'platform', 'type' => 'select', 'label' => 'Platform',
'options' => [ 'facebook' => 'Facebook', 'twitter' => 'Twitter / X' ] ],
[ 'id' => 'url', 'type' => 'text', 'label' => 'Profile URL', 'placeholder' => 'https://' ],
],
]
Works identically inside a metabox's fields array or an option panel section. Reading a repeater back is covered in Helper Functions.
To show/hide one sub-field based on another sub-field in the same row, give the controlling sub-field a bind key and reference it in the dependent field's conditional rule — each row then evaluates independently. Full details: Advanced Topics → Dynamic Data.
The group field type
Use type => 'group' to lay a handful of related sub-fields out inline, side by side, without giving the editor an "add row" button. Use it for something like a single heading + subheading pair that always belongs together — for anything repeatable, use repeater instead.