Organise your theme options into a clean hierarchical sidebar using sections and subsections.
Overview
ThemePlus organises all fields into a sidebar navigation. At the top level are sections — each appears as a clickable item in the sidebar. Sections can contain fields directly, or they can be divided into subsections which appear as nested items below the parent. You can use both at the same time.
Adding a Section
Use themeplus_add_section() on the init hook. Always wrap it in a function_exists() check:
add_action( 'init', function () {
if ( ! function_exists( 'themeplus_add_section' ) ) {
return;
}
themeplus_add_section([
'id' => 'general',
'title' => __( 'General Settings', 'your-textdomain' ),
'icon' => 'cog',
'priority' => 10,
'fields' => [
[
'id' => 'enable_preloader',
'type' => 'toggle',
'title' => __( 'Enable Preloader', 'your-textdomain' ),
'default' => true,
],
],
]);
} );
Section Options
| Option | Type | Default | Description |
|---|---|---|---|
id | string | — | Required. Unique section identifier. Used as the key in the database and in conditional logic. |
title | string | — | Required. Label shown in the sidebar. |
icon | string | 'cog' | FontAwesome icon name — the part after fa-solid fa-. Example: 'palette', 'code', 'layer-group'. |
priority | int | 10 | Controls the order sections appear in the sidebar. Lower numbers appear first. |
fields | array | [] | Array of field definition arrays registered directly in this section. |
subsections | array | [] | Array of subsection definition arrays nested under this section. |
Icon convention: The
iconkey takes a FontAwesome name only — just the part afterfa-solid fa-. For example'pen','palette','ruler-combined'. Do not pass the full class string here — that format is only used by the Icon fielddefaultvalue.
Adding Subsections
Subsections can be added in two ways — inline when registering the section, or separately via themeplus_add_subsection().
Inline subsections
Pass subsections directly in the subsections key when registering the section:
themeplus_add_section([
'id' => 'header',
'title' => __( 'Header', 'your-textdomain' ),
'icon' => 'rectangle-ad',
'priority' => 20,
'fields' => [],
'subsections' => [
[
'id' => 'logo',
'title' => __( 'Logo', 'your-textdomain' ),
'icon' => 'image',
'fields' => [
[
'id' => 'logo_image',
'type' => 'image',
'title' => __( 'Logo Image', 'your-textdomain' ),
],
[
'id' => 'logo_width',
'type' => 'number',
'title' => __( 'Logo Width', 'your-textdomain' ),
'default' => 160,
'unit' => 'px',
],
],
],
[
'id' => 'navigation',
'title' => __( 'Navigation', 'your-textdomain' ),
'icon' => 'bars',
'fields' => [
// ...
],
],
],
]);
Subsection Options
| Option | Type | Required | Description |
|---|---|---|---|
id | string | ✅ | Unique subsection identifier within the parent section. |
title | string | ✅ | Label shown in the sidebar under the parent section. |
icon | string | — | FontAwesome icon name — same format as section icons. |
fields | array | ✅ | Array of field definition arrays for this subsection. |
Note: Subsections do not have a
prioritykey — they appear in the order they are added.
Attaching a Subsection Separately
Use themeplus_add_subsection() to attach a subsection to an already-registered section from a separate hook. This is the recommended pattern for child themes and extension pluginsthat need to add fields to a parent theme’s panel without modifying its source:
add_action( 'init', function () {
if ( ! function_exists( 'themeplus_add_subsection' ) ) {
return;
}
themeplus_add_subsection( 'header', [
'id' => 'sticky_header',
'title' => __( 'Sticky Header', 'your-textdomain' ),
'icon' => 'arrow-up',
'fields' => [
[
'id' => 'enable_sticky',
'type' => 'toggle',
'title' => __( 'Enable Sticky Header', 'your-textdomain' ),
'default' => false,
],
],
]);
}, 20 ); // Priority 20 or later — the parent section must exist first
Important:
themeplus_add_subsection()silently does nothing if the parent section ID does not exist yet. Always use a hook priority of20or later to ensure the parent section is registered before you attach to it.
Sections With Both Fields and Subsections
A section can contain both top-level fields and subsections at the same time. Top-level fields appear when the section heading itself is clicked; subsection fields appear when a subsection is clicked:
themeplus_add_section([
'id' => 'typography',
'title' => __( 'Typography', 'your-textdomain' ),
'icon' => 'font',
'priority' => 30,
'fields' => [
// These fields appear at the section level
[
'id' => 'base_font_size',
'type' => 'number',
'title' => __( 'Base Font Size', 'your-textdomain' ),
'default' => 16,
'unit' => 'px',
],
],
'subsections' => [
[
'id' => 'body_typography',
'title' => __( 'Body', 'your-textdomain' ),
'icon' => 'align-left',
'fields' => [
[
'id' => 'body_font',
'type' => 'typography',
'title' => __( 'Body Font', 'your-textdomain' ),
'font-size' => true,
'font-weight' => true,
'line-height' => true,
],
],
],
[
'id' => 'heading_typography',
'title' => __( 'Headings', 'your-textdomain' ),
'icon' => 'heading',
'fields' => [
[
'id' => 'heading_font',
'type' => 'typography',
'title' => __( 'Heading Font', 'your-textdomain' ),
'font-weight' => true,
],
],
],
],
]);
Controlling Section Order
Use the priority key to control the order sections appear in the sidebar. Sections are sorted by priority — lower numbers appear first:
themeplus_add_section(['id' => 'general', 'priority' => 10, ...]);
themeplus_add_section(['id' => 'header', 'priority' => 20, ...]);
themeplus_add_section(['id' => 'typography', 'priority' => 30, ...]);
themeplus_add_section(['id' => 'footer', 'priority' => 40, ...]);Sections with the same priority value appear in the order they were registered.
Helper Functions
| Function | Description |
|---|---|
themeplus_add_section( array $section ) | Register a new section |
themeplus_add_subsection( string $parent_id, array $subsection ) | Attach a subsection to an existing section |
themeplus_get_sections() | Get all registered sections as an array |
themeplus_get_section( string $id ) | Get a single section by its ID |