From 3c108d5254c885bcabdb35816591f7bac4ea3cae Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 25 May 2026 13:57:44 +0000 Subject: [PATCH 1/4] fix(bricks): use official bricks/builder/color_palette filter for color injection The previous option_bricks_color_palette filter only fires when WordPress reads the DB option directly; Bricks fires its own bricks/builder/color_palette filter when assembling the builder color picker, bypassing get_option. Colors were never appearing in the builder because the wrong hook was used. The option_* filters are kept as fallbacks for REST/import/older Bricks paths. --- integrations/bricks/includes/class-colors.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/integrations/bricks/includes/class-colors.php b/integrations/bricks/includes/class-colors.php index c7bb2662..65d88574 100644 --- a/integrations/bricks/includes/class-colors.php +++ b/integrations/bricks/includes/class-colors.php @@ -64,9 +64,12 @@ class Slashed_Bricks_Colors { * Constructor. Register hooks. */ public function __construct() { - // Inject SLASHED palettes when Bricks (or anything else) reads the - // bricks_color_palette option. Run late so any other plugin's - // additions are preserved. + // Official Bricks builder filter — fires when the builder assembles + // the color picker, regardless of how the option is stored/cached. + add_filter( 'bricks/builder/color_palette', array( $this, 'inject_palettes' ), 20 ); + + // Fallback: inject when WordPress reads the option directly (e.g. + // REST, imports, or older Bricks versions that call get_option). add_filter( 'option_bricks_color_palette', array( $this, 'inject_palettes' ), 20 ); add_filter( 'default_option_bricks_color_palette', array( $this, 'inject_palettes' ), 20 ); From 8f71ffaf9e4bdabe2239a16fd15d2f1dc989e6ce Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 25 May 2026 14:05:21 +0000 Subject: [PATCH 2/4] fix(bricks/colors): use correct flat {hex} shape for bricks/builder/color_palette The bricks/builder/color_palette filter expects a flat array of {hex, rgb?} objects (per Bricks Academy docs), not the {id, name, colors:[]} palette-group shape used by the option. The previous fix wired the wrong callback to the filter, so nothing appeared in the builder color picker. Added inject_builder_colors() with the correct flat structure, using var(--sf-color-*) references so swatches track the live theme via CSS variable resolution in the editor iframe. --- integrations/bricks/includes/class-colors.php | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/integrations/bricks/includes/class-colors.php b/integrations/bricks/includes/class-colors.php index 65d88574..057220db 100644 --- a/integrations/bricks/includes/class-colors.php +++ b/integrations/bricks/includes/class-colors.php @@ -64,20 +64,44 @@ class Slashed_Bricks_Colors { * Constructor. Register hooks. */ public function __construct() { - // Official Bricks builder filter — fires when the builder assembles - // the color picker, regardless of how the option is stored/cached. - add_filter( 'bricks/builder/color_palette', array( $this, 'inject_palettes' ), 20 ); + // Official Bricks filter (bricks/builder/color_palette) — expects a + // flat array of {hex, rgb?} objects, per the Bricks Academy docs. + add_filter( 'bricks/builder/color_palette', array( $this, 'inject_builder_colors' ), 20 ); - // Fallback: inject when WordPress reads the option directly (e.g. - // REST, imports, or older Bricks versions that call get_option). + // option_* filters inject the named-palette group structure that + // appears in the palette dropdown (id/name/colors shape). Kept as a + // secondary path for REST, imports, and older Bricks versions. add_filter( 'option_bricks_color_palette', array( $this, 'inject_palettes' ), 20 ); add_filter( 'default_option_bricks_color_palette', array( $this, 'inject_palettes' ), 20 ); // Strip SLASHED palettes before they are persisted back to the DB. - // pre_update_option_* signature is ($value, $old_value, $option). add_filter( 'pre_update_option_bricks_color_palette', array( $this, 'strip_palettes' ), 10, 1 ); } + /** + * Inject SLASHED color variables into the Bricks builder flat color + * palette (the swatch strip in the color picker). + * + * Called via bricks/builder/color_palette which expects a flat array of + * {hex, rgb?} objects. We pass var(--sf-color-*) references so swatches + * always reflect the live theme — the SLASHED bundle is loaded in the + * editor iframe so the browser resolves the variables when painting swatches. + * + * @param mixed $colors Existing flat palette from Bricks. + * @return array + */ + public function inject_builder_colors( $colors ) { + if ( ! is_array( $colors ) ) { + $colors = array(); + } + + foreach ( Slashed_Bricks_Inventory::get_color_variables() as $var ) { + $colors[] = array( 'hex' => 'var(' . $var . ')' ); + } + + return $colors; + } + /** * Inject SLASHED palettes into the Bricks palette list. * From b67eaab6a9f745429f2cae5a83dc0f4c67129332 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 25 May 2026 14:45:02 +0000 Subject: [PATCH 3/4] fix(bricks): register data managers at plugins_loaded, not after_setup_theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: Bricks' Database::__construct() reads bricks_global_variables, bricks_global_classes, and bricks_color_palette via get_option() during theme functions.php load — which happens AFTER plugins_loaded but BEFORE after_setup_theme. Our option filters were registered in after_setup_theme, so Bricks had already read and internally cached the options before our filters were ever in place. Nothing appeared in any of the three managers. Fix: split initialization into two phases. - plugins_loaded (priority 20): instantiate Variables, Classes, Colors so their option filters are registered before the theme loads and Bricks reads options. - after_setup_theme: instantiate Enqueue only (needs theme + Bricks version check). Also removes the bricks/builder/color_palette flat-swatch hook added in the previous two commits. That filter cannot assign names to injected colors per Bricks' own docs ("id and name are generated after it is applied"), making it unsuitable for Color Manager integration. Named palette groups via the option filter are the correct mechanism and now fire at the right time. --- .../bricks/includes/class-classes.php | 10 ++- integrations/bricks/includes/class-colors.php | 70 ++++++------------- .../bricks/includes/class-variables.php | 15 ++-- integrations/bricks/slashed-bricks.php | 41 ++++++++--- 4 files changed, 72 insertions(+), 64 deletions(-) diff --git a/integrations/bricks/includes/class-classes.php b/integrations/bricks/includes/class-classes.php index 14bfffbe..b5a21dc3 100644 --- a/integrations/bricks/includes/class-classes.php +++ b/integrations/bricks/includes/class-classes.php @@ -19,9 +19,13 @@ * Strategy * -------- * Bricks reads global classes from the wp_options row `bricks_global_classes` - * (and class categories from `bricks_global_classes_categories`). We treat - * SLASHED entries as managed/virtual - the same pattern the Colors module - * uses for the color palette option: + * (categories from `bricks_global_classes_categories`). Both options are read + * via get_option() inside Bricks' Database::__construct() which runs during + * theme functions.php load — before after_setup_theme fires. This class must + * therefore be instantiated at plugins_loaded (handled in slashed-bricks.php) + * so our option filters are registered before that first read. + * + * We treat SLASHED entries as managed/virtual: * * 1. On every read of either option, inject our entries. * 2. On every write (save from the UI, import, etc.), strip our entries diff --git a/integrations/bricks/includes/class-colors.php b/integrations/bricks/includes/class-colors.php index 057220db..894bf180 100644 --- a/integrations/bricks/includes/class-colors.php +++ b/integrations/bricks/includes/class-colors.php @@ -12,28 +12,26 @@ /** * Class Slashed_Bricks_Colors * - * Registers SLASHED color tokens with Bricks Builder as a set of separate, - * named color palettes that appear under the "Color palettes" dropdown of - * the Bricks color picker - distinct from the site's global colors. + * Registers SLASHED color tokens with Bricks Builder as a set of named color + * palettes that appear under the Color Manager palette dropdown. * * Strategy * -------- - * Bricks stores user-managed color palettes in the wp_options row - * `bricks_color_palette`. We treat SLASHED palettes as managed/virtual: + * Bricks stores color palettes in the wp_options row `bricks_color_palette` + * as an array of `{id, name, colors:[{id,name,hex}]}` palette-group objects. + * We treat SLASHED palettes as managed/virtual: * - * 1. On every read of that option (option_bricks_color_palette / - * default_option_bricks_color_palette), we inject our palettes into - * the array Bricks sees. - * 2. On every write (pre_update_option_bricks_color_palette), we strip - * our palettes back out so the database never persists them. That - * way the integration is the single source of truth - bumping the - * framework or changing the active bundle automatically updates - * what Bricks shows, without leaving stale rows behind on the site. + * 1. On every read of the option (option_bricks_color_palette / + * default_option_bricks_color_palette) we inject our palette groups. + * The plugin is registered early (plugins_loaded) so our filters are + * in place before Bricks' Database::__construct() reads the option. + * 2. On every write (pre_update_option_bricks_color_palette) we strip + * our palettes back out so the DB never persists them. The plugin + * remains the single source of truth. * - * Each palette's swatch references the framework variable directly via - * var(--sf-color-X). Modern browsers resolve var() inside the picker - * preview because the SLASHED bundle is loaded into the editor iframe. - * This keeps swatches in sync with theme customization and dark mode. + * Each color swatch references the framework variable via var(--sf-color-X). + * The SLASHED bundle loaded in the editor iframe resolves the var() reference + * so swatches track the live theme including dark mode and token overrides. * * Note: the 'raw' field is included alongside 'hex' for forward * compatibility with Bricks 1.9.2+, which prefers 'raw' when present. @@ -64,13 +62,13 @@ class Slashed_Bricks_Colors { * Constructor. Register hooks. */ public function __construct() { - // Official Bricks filter (bricks/builder/color_palette) — expects a - // flat array of {hex, rgb?} objects, per the Bricks Academy docs. - add_filter( 'bricks/builder/color_palette', array( $this, 'inject_builder_colors' ), 20 ); - - // option_* filters inject the named-palette group structure that - // appears in the palette dropdown (id/name/colors shape). Kept as a - // secondary path for REST, imports, and older Bricks versions. + // Inject SLASHED named palette groups when Bricks reads the palette + // option. This populates the Color Manager dropdown with organized, + // labeled palettes (Primary, Secondary, …) rather than anonymous + // swatches. The bricks/builder/color_palette filter is intentionally + // not used here: per the Bricks forum that filter cannot assign names + // — "id and name are generated after it is applied" — making it + // unsuitable for Color Manager integration. add_filter( 'option_bricks_color_palette', array( $this, 'inject_palettes' ), 20 ); add_filter( 'default_option_bricks_color_palette', array( $this, 'inject_palettes' ), 20 ); @@ -78,30 +76,6 @@ public function __construct() { add_filter( 'pre_update_option_bricks_color_palette', array( $this, 'strip_palettes' ), 10, 1 ); } - /** - * Inject SLASHED color variables into the Bricks builder flat color - * palette (the swatch strip in the color picker). - * - * Called via bricks/builder/color_palette which expects a flat array of - * {hex, rgb?} objects. We pass var(--sf-color-*) references so swatches - * always reflect the live theme — the SLASHED bundle is loaded in the - * editor iframe so the browser resolves the variables when painting swatches. - * - * @param mixed $colors Existing flat palette from Bricks. - * @return array - */ - public function inject_builder_colors( $colors ) { - if ( ! is_array( $colors ) ) { - $colors = array(); - } - - foreach ( Slashed_Bricks_Inventory::get_color_variables() as $var ) { - $colors[] = array( 'hex' => 'var(' . $var . ')' ); - } - - return $colors; - } - /** * Inject SLASHED palettes into the Bricks palette list. * diff --git a/integrations/bricks/includes/class-variables.php b/integrations/bricks/includes/class-variables.php index e0f2608f..3b6998c9 100644 --- a/integrations/bricks/includes/class-variables.php +++ b/integrations/bricks/includes/class-variables.php @@ -18,11 +18,16 @@ * Strategy * -------- * Bricks 1.9.8+ stores user-managed variables in the `bricks_global_variables` - * wp_option (categories in `bricks_global_variables_categories`). Same as - * the Colors and Classes modules, we treat SLASHED entries as managed/virtual: - * inject on read, strip on save, so the integration is the single source of - * truth and bumping the framework or switching the active CSS bundle keeps - * the Variable Manager in sync without leaving stale rows in the DB. + * wp_option (categories in `bricks_global_variables_categories`). Both options + * are read via get_option() inside Bricks' Database::__construct() which runs + * during theme functions.php load — before after_setup_theme fires. This class + * must therefore be instantiated at plugins_loaded (handled in slashed-bricks.php) + * so our option filters are registered before that first read. + * + * We treat SLASHED entries as managed/virtual: inject on read, strip on save, + * so the integration is the single source of truth and bumping the framework or + * switching the active CSS bundle keeps the Variable Manager in sync without + * leaving stale rows in the DB. * * Naming * ------ diff --git a/integrations/bricks/slashed-bricks.php b/integrations/bricks/slashed-bricks.php index 0b3f0fdb..24aef89e 100644 --- a/integrations/bricks/slashed-bricks.php +++ b/integrations/bricks/slashed-bricks.php @@ -131,28 +131,53 @@ function slashed_bricks_admin_init() { } /** - * Initialize the plugin. + * Data managers: early initialization at plugins_loaded. + * + * Bricks' Database::__construct() reads bricks_global_variables, + * bricks_global_classes, and bricks_color_palette via get_option() during + * theme functions.php load — which happens AFTER plugins_loaded but BEFORE + * after_setup_theme. Registering our option filters here guarantees they are + * in place when Bricks reads those options for the first time. + * + * Runs unconditionally: if Bricks is not the active theme the option filters + * simply never fire, which is harmless. */ -function slashed_bricks_init() { - if ( ! slashed_bricks_is_bricks_active() ) { - add_action( 'admin_notices', 'slashed_bricks_missing_bricks_notice' ); +function slashed_bricks_data_init() { + // Bail early on non-Bricks sites to avoid loading classes needlessly. + if ( 'bricks' !== get_option( 'template' ) ) { return; } - require_once SLASHED_BRICKS_PATH . 'includes/class-token-defaults.php'; - require_once SLASHED_BRICKS_PATH . 'includes/class-css-generator.php'; require_once SLASHED_BRICKS_PATH . 'includes/class-css-parser.php'; require_once SLASHED_BRICKS_PATH . 'includes/class-inventory.php'; - require_once SLASHED_BRICKS_PATH . 'includes/class-enqueue.php'; require_once SLASHED_BRICKS_PATH . 'includes/class-variables.php'; require_once SLASHED_BRICKS_PATH . 'includes/class-classes.php'; require_once SLASHED_BRICKS_PATH . 'includes/class-colors.php'; - new Slashed_Bricks_Enqueue(); new Slashed_Bricks_Variables(); new Slashed_Bricks_Classes(); new Slashed_Bricks_Colors(); } +add_action( 'plugins_loaded', 'slashed_bricks_data_init', 20 ); + +/** + * CSS enqueue: late initialization at after_setup_theme. + * + * Enqueue needs the theme to be active and Bricks version checks to pass. + * Data managers (variables, classes, colors) are already initialized above. + */ +function slashed_bricks_init() { + if ( ! slashed_bricks_is_bricks_active() ) { + add_action( 'admin_notices', 'slashed_bricks_missing_bricks_notice' ); + return; + } + + require_once SLASHED_BRICKS_PATH . 'includes/class-token-defaults.php'; + require_once SLASHED_BRICKS_PATH . 'includes/class-css-generator.php'; + require_once SLASHED_BRICKS_PATH . 'includes/class-enqueue.php'; + + new Slashed_Bricks_Enqueue(); +} add_action( 'after_setup_theme', 'slashed_bricks_init' ); /** From e54abba283c182c9f629103457ece44d5a399765 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 25 May 2026 15:27:54 +0000 Subject: [PATCH 4/4] fix(bricks): normalise template option check in slashed_bricks_data_init get_option('template') returns false when the option is absent; casting to string and using strtolower() makes the Bricks check robust against missing options and any case variation in the theme directory name. --- integrations/bricks/slashed-bricks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/bricks/slashed-bricks.php b/integrations/bricks/slashed-bricks.php index 24aef89e..c3744982 100644 --- a/integrations/bricks/slashed-bricks.php +++ b/integrations/bricks/slashed-bricks.php @@ -144,7 +144,7 @@ function slashed_bricks_admin_init() { */ function slashed_bricks_data_init() { // Bail early on non-Bricks sites to avoid loading classes needlessly. - if ( 'bricks' !== get_option( 'template' ) ) { + if ( 'bricks' !== strtolower( (string) get_option( 'template', '' ) ) ) { return; }