Theme Options internals
How the Theme Options panel is built, how to read its values and how to add your own options. Every option the theme has is listed in the Theme Options reference.
How it fits together
- Schema:
BlueTheme\Options\Schema\Registrycollects the sections (inc/Options/Schema/Sections/). A section has subsections, and a subsection has fields. Labels are translated, so the schema is built afterinit. - Storage: one option,
bluetheme_options, holds only the values that differ from the defaults.Options::all()merges them over the defaults. - Panel: a React app (
src/admin/options/) under BlueTheme → Theme Options. It loads the schema and values, and saves through the REST API (bluetheme/v1/options,edit_theme_options). Every value is cleaned by its field type on save (Options\Sanitizer). - CSS: fields with a
csskey become CSS custom properties in one generated stylesheet,wp-content/uploads/bluetheme/css/options.css. It is rebuilt when options are saved, imported or reset, and from Global → Performance → Regenerate now. - Secrets: password fields (API keys) are never exported, and an import keeps the site's own.
Reading values
use BlueTheme\Options\Options;
$width = Options::get( 'site_width' ); // with the default applied
$logo = Options::get( 'logo', array() ); // second argument: if the field doesn't exist
$gutter = Options::device( 'grid_gutter', 'mobile' ); // per-device value; a device without its own uses the next larger one
Values can be changed on the fly with the bluetheme_options filter. Page Options use it to apply a page's own settings.
Field types
Theme Options and builder elements use the same field types.
| Type | Value | Notes |
|---|---|---|
text, textarea, email, url, password |
string | textarea keeps line breaks. |
html |
string | Filtered with wp_kses_post unless the user has unfiltered_html. |
code |
string | Code editor; mode is css, js or html. Saving needs unfiltered_html. |
number, slider |
number | min, max, step, unit. |
switch |
bool | |
select, radio, visual |
string | One of choices (value => label). visual shows pictures. |
multiselect, sortable |
string[] | sortable keeps the order. |
color |
string | Hex, rgb(), or a palette reference such as palette:primary. |
gradient |
string | A CSS gradient. |
image, upload |
{ id, url } |
|
gallery |
[ { id, url }, … ] |
|
typography |
{ family, size, size_unit, line_height, letter_spacing, weight, style, transform } |
Size, line height and letter spacing per device. |
font |
string | A font family from Theme Options → Fonts. |
dimensions |
{ top, end, bottom, start, unit, linked } |
Logical sides: start is right in RTL. |
size |
string | A builder wrap width: 1/6 … 1/1, or a percentage such as 37.5%. |
shadow |
{ x, y, blur, spread, color, inset } |
|
background |
{ color, gradient, image, position, repeat, size, attachment } |
attachment can be parallax. |
repeater |
[ { _id, … }, … ] |
Its fields describe one item. |
datetime |
string | |
icon |
string | pack:name, such as bi:star. |
page, sidebar, categories |
id(s) | Choices come from the site. |
Keys every field can have:
responsive: true: one value per device ({ desktop, laptop, tablet, mobile }).description: help text under the field.show_if:[ field id, operator, value ], shows the field only when the condition is true.css:{ var: '--bt-name', unit: 'px' }writes the value as a custom property. Composite types (typography, dimensions, background) write one property per part, named after the base, such as--bt-btn-size.capability: the capability needed to change this field.
Adding options
Add a subsection (or a whole section) with the bluetheme_options_sections filter, from a child theme's functions.php or a plugin:
use BlueTheme\Options\Schema\Field;
add_filter( 'bluetheme_options_sections', function ( array $sections ): array {
foreach ( $sections as &$section ) {
if ( 'global' !== $section['id'] ) {
continue;
}
$section['subsections'][] = Field::group(
'site_notice',
__( 'Site notice', 'bluetheme-child' ),
array(
Field::make( 'switch', 'site_notice_on', __( 'Show the notice', 'bluetheme-child' ), false ),
Field::make( 'text', 'site_notice_text', __( 'Text', 'bluetheme-child' ), '' ),
Field::make( 'color', 'site_notice_color', __( 'Color', 'bluetheme-child' ), '#1e5eff', array(
'css' => array( 'var' => '--site-notice-color' ),
) ),
)
);
}
return $sections;
} );
- Field ids are one namespace across all sections: prefix yours.
- The panel shows the new subsection under Global with search, reset and export working as for the theme's own options.
- Read the values with
Options::get( 'site_notice_on' ), and usevar(--site-notice-color)in your CSS. Save Theme Options once (or Regenerate now) so the stylesheet includes the new property. - A new section is an array
[ 'id', 'title', 'icon' => 'pack:name', 'subsections' => [ … ] ]added to the list. - Rules that depend on several values go through the
bluetheme_options_cssfilter, which receives the compiled CSS and all values. bluetheme_options_savedruns after every save, for your own caches.
Page Options
Pages, posts, projects and products have Page Options, edited in a box under the editor and in the live builder's Page tab (inc/PageOptions). Every field starts empty, which means "as in Theme Options". Only the fields that differ are saved, in the post meta _bluetheme_page_options (JSON). The block editor saves it with the post; the builder saves it through bluetheme/v1/page-options/{id}, which requires edit_post. More post types: the bluetheme_page_options_post_types filter.
- Layout: site layout (full or boxed), sidebars (none, start, end, both) and which ones, content width, page background.
- Header: header template (by display conditions, a chosen one, or none for the classic header), transparent header template (on or off). For the classic header: its style, position and sticky (default, on or off).
- Title bar: show or hide, layout, a custom title, background, breadcrumbs.
- Footer: footer template (by display conditions, a chosen one, or none), footer style, back to top button.
- Colors: every light-mode color of Theme Options → Colors, in the same groups. Dark mode keeps its own colors.
- Advanced: one-page mode, extra body classes, custom CSS for the page.
How they apply (PageOptions\Apply):
- Settings that mirror a Theme Options field (
Schema::OVERRIDES) replace its value through thebluetheme_optionsfilter, from thewpaction on. The site-wide options stylesheet is always compiled without them. - Colors and backgrounds are printed as CSS variables, with the page's custom CSS, after the site stylesheet.
- Sidebars and content width go through
bluetheme_layout, templates throughbluetheme_template, transparency throughbluetheme_transparent_header, and the title throughbluetheme_subheader_title. - On the blog page, the posts page's options apply; on the shop, the shop page's.