fix(theme): make the Theme Generator's colors real - #9
Merged
Conversation
The Theme Generator demo page was broken in two independent ways. Every color picker rendered Bootstrap blue. The page passed `value="#343a40"` to `<x-adminlte-input-color>`, which has no `value` prop — so the color fell through to `$attributes->merge()` and landed *after* the component's own `value` attribute. Browsers keep the first of two duplicate attributes, so all four swatches showed `#0d6efd` no matter what the page asked for. They now use the documented `default` prop, seeded from config. And the config snippet it told you to paste did nothing: four of its five keys were never read by the package, and `color_mode` was not a config key at all. Rather than delete the feature, make the keys real — `primary_color`, `sidebar_color`, `navbar_color` and `footer_color` are now injected into the layout head as CSS custom-property overrides by `Support\ThemeColors`, so the chrome can be recolored without compiling SCSS. All four default to null and emit nothing at all in that case. `primary_color` needs more than `--bs-primary` because Bootstrap compiles `.btn-primary` from Sass literals, so the hover/active shades are recomputed with Bootstrap's own `shade-color()` weights and the button text follows `color-contrast()`. That last one is not "pick the higher ratio": Bootstrap's own $primary contrasts 4.50:1 on white and 4.67:1 on black, so choosing the maximum would render every stock primary button with black text. Tests pin the shades against Bootstrap's compiled output. The style block is rendered unescaped, so colors are matched against a strict `#rgb`/`#rrggbb` pattern and anything else is dropped. The generator now previews every change live, seeds each control from the running config, emits only keys that exist, and labels the color-mode select as preview-only — the runtime mode comes from the topbar toggle and the visitor's system preference, not from config. Co-authored-by: Ruan Pépe <ruanpepe@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Supersedes #8 by @ruanpepe, which correctly spotted that the Theme Generator's color pickers were broken. This lands that fix plus the underlying reason the page never worked.
The rendering bug (#8)
The page passed
value="#343a40"to<x-adminlte-input-color>, which has novalueprop — so the color fell through to$attributes->merge()and landed after the component's ownvalueattribute:Browsers keep the first of two duplicate attributes, so all four swatches rendered
#0d6efdregardless. Now uses the documenteddefaultprop, seeded from config.The deeper bug
The config snippet the page told you to paste did nothing.
sidebar_color,primary_color,navbar_colorandfooter_colorwere never read by the package, andcolor_modewas not a config key at all.Rather than delete the feature, this makes the keys real.
Support\ThemeColorsinjects them into the layout<head>as CSS custom-property overrides, so the chrome can be recolored without compiling SCSS. All four default tonulland emit nothing in that case, so existing installs are untouched.primary_colorneeds more than--bs-primary, because Bootstrap compiles.btn-primaryfrom Sass literals rather than from the variable. Hover/active shades are recomputed with Bootstrap's ownshade-color()weights, and button text followscolor-contrast()— which is deliberately not "pick the higher contrast ratio": Bootstrap's own$primary(#0d6efd) contrasts 4.50:1 against white and 4.67:1 against black, so choosing the maximum would render every stock primary button with black text instead of Bootstrap's white. Tests pin the shades against Bootstrap's compiled output (#0b5ed7,#0a58ca,#0a53be).The block is rendered unescaped, so values are matched against a strict
#rgb/#rrggbbpattern and anything else is dropped. A data provider coversrgb(),var(), named colors and both CSS- and markup-injection attempts.Also
labelprop, so labels are actually associated with their inputs.Checklist
composer checkpasses locally (Pint + PHPStan + PHPUnit)docs/if behaviour or APIs changed (they are served in-app at/docs)CHANGELOG.mdentry under [Unreleased]resources/lang/— n/a, no new strings🤖 Generated with Claude Code