BlueTheme Docs

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\Registry collects the sections (inc/Options/Schema/Sections/). A section has subsections, and a subsection has fields. Labels are translated, so the schema is built after init.
  • 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 css key 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 use var(--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_css filter, which receives the compiled CSS and all values.
  • bluetheme_options_saved runs 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 the bluetheme_options filter, from the wp action 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 through bluetheme_template, transparency through bluetheme_transparent_header, and the title through bluetheme_subheader_title.
  • On the blog page, the posts page's options apply; on the shop, the shop page's.