Consuming tokens

Design Controller publishes the site's design system as CSS custom properties named --dc-* on :root โ€” printed once at wp_head from a single autoloaded option, so reading them costs no query โ€” and as three PHP helpers for the cases where you need the actual value. This page is for anyone whose theme or plugin should "follow the site" without a settings screen of its own.

The one rule: var(--dc-โ€ฆ, fallback)

Example: a plugin that follows the site

Say your plugin's stylesheet declares its own variables:

:root {
	--my-primary: #0b67b2;
	--my-primary-dark: #084d86;
	--my-radius: 8px;
}

Make each one "the site's value if there is one, mine otherwise" โ€” a single line per variable, and no other selector changes:

:root {
	--my-primary: var(--dc-color-brand-primary, #0b67b2);
	--my-primary-dark: var(--dc-color-brand-primary-strong, #084d86);
	--my-font: var(--dc-font-family-body, "Sarabun", sans-serif);
	--my-radius: var(--dc-radius-md, 8px);
}
.my-button {
	background: var(--my-primary);
	border-radius: var(--my-radius);
	font-family: var(--my-font);
}

Change the brand colour or the body font in Design Controller and the plugin follows at once โ€” inside the live preview too โ€” without knowing the plugin exists.

The variables you will use most

| Group | Variables | Notes | | --- | --- | --- | | Brand colours | --dc-color-brand-primary, -secondary, -accent | each with -soft, -strong, -contrast (derived; -contrast is the text colour on it) | | Neutrals | --dc-color-neutral-50 โ€ฆ -950 | a ladder from one seed | | Semantic | --dc-color-semantic-success, -warning, -danger, -info | with -soft, -contrast | | Surfaces and text | --dc-color-surface-page, -card, -muted, -inverse; --dc-color-text-default, -muted, -inverse, -link, -link-hover; --dc-color-border-default, -strong | | | Fonts | --dc-font-family-heading, -body, -ui, -mono | the full stack, metric-matched fallbacks included | | Sizes | --dc-font-size-xs โ€ฆ -5xl (-md is the base), --dc-font-heading-h1-size โ€ฆ -h6-size | fluid clamp() when enabled | | Weights and leading | --dc-font-weight-regular, -medium, -semibold, -bold; --dc-font-line-height-tight, -normal, -relaxed | | | Spacing | --dc-space-1 โ€ฆ -12, --dc-space-section-sm, -md, -lg, --dc-layout-container-sm โ€ฆ -xl, --dc-layout-gutter | | | Shape and shadow | --dc-radius-sm, -md, -lg, -xl, -full; --dc-shadow-sm, -md, -lg; --dc-border-width-thin, -thick | | | Motion | --dc-motion-duration-fast, -normal, --dc-motion-easing | | | Components | --dc-component-button-primary-background, -text, -border, -radius, -padding-x, -padding-y, -weight; โ€ฆ-secondary-*, โ€ฆ-outline-*; --dc-component-input-*, --dc-component-card-*, --dc-component-nav-* | always set, even with the recipe off |

A variable name is the token path with camelCase turned to kebab-case and . to -: font.lineHeight.normal becomes --dc-font-line-height-normal. wp dctl export --resolved prints every resolved value as DTCG JSON.

In PHP, when you need the value itself

For a PDF, an email or a chart โ€” anything that cannot read the page's CSS:

// A resolved hex (aliases and derived values computed); $fallback when there is no plugin or no value.
$primary = function_exists( 'dctl_token' ) ? dctl_token( 'color.brand.primary' ) : null;
$primary = $primary ?? '#0b67b2';

// A ready-made var(--dc-โ€ฆ, fallback) string for an inline style.
$css = function_exists( 'dctl_var' ) ? dctl_var( 'radius.md', '8px' ) : '8px';

// The font stack for a role (heading | body | ui | mono), as a CSS string.
$font = function_exists( 'dctl_font_stack' ) ? dctl_font_stack( 'body' ) : '"Sarabun", sans-serif';

All three read the autoloaded option โ€” no query โ€” and are safe in any template. The font files Design Controller hosts live in wp_font_dir(); wp dctl fonts list prints them.

Hooks worth knowing

| Hook | When | | --- | --- | | dctl_design_published (action; $design_id, $compiled) | something must happen after a publish โ€” regenerate a CSS file of your own, say | | dctl_compiled_updated (action; $design_id, $compiled, $published) | every time the CSS on the site changes, recompiles from fonts or settings included | | dctl_cache_purged (action; $ids) | after a purge โ€” purge your own cache too | | dctl_cache_targets (filter) | add a host or plugin cache the plugin does not know: ['id', 'label', 'detect' => callable, 'purge' => callable] | | dctl_component_selectors (filter; $map, $theme) | let the button, field, card and menu recipes cover your plugin's selectors | | dctl_frontend_css (filter; $css, $compiled) | print more CSS in <style id="dctl-bridges"> โ€” only var(--dc-*), never a query | | dctl_bridges (filter) | add a whole bridge for another module (BridgeInterface) |

Three things not to do