mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-10-23 08:12:28 +00:00
fix(logo): default sage/teal brand colors, customizer mirrors accent (#1162)
## Summary Restores sage/teal as default logo colors while preserving customizer theming. Closes the gap from #1157 (closed) and the user's complaint about lost two-tone. Out-of-the-box, the navbar + hero CORE/SCOPE wordmarks now render the brand-identity duotone — `#cfd9c9` (sage / fog) and `#2c8c8c` (teal / water). When an operator picks a theme via the customizer (or sets a custom accent color), the wordmark recolors to follow. ## Approach (Option C — decoupled defaults + customizer mirror) - **`public/style.css` `:root`** — set `--logo-accent: #cfd9c9` and `--logo-accent-hi: #2c8c8c` as literal defaults. Removes the previous `var(--accent)` cascade so blue-by-default no longer leaks into the brand mark. - **`public/customize-v2.js`** — `applyTheme()`, the early-apply path, and the live color-picker `input` handler now mirror `themeSection.accent` → `--logo-accent` and `themeSection.accentHover` → `--logo-accent-hi`. - **`public/customize.js`** (legacy) — same mirroring in `applyThemePreview()` and the early localStorage replay. - **`.github/workflows/deploy.yml`** — adds the new e2e to the Chromium batch. This preserves `--accent` as the canonical app-wide accent token (no other UI changes) while giving the logo its own brand-defaulted tokens that the customizer still drives. ## Tests Red → green commit pair on the branch. - **NEW: `test-logo-default-sage-teal-e2e.js`** — gates both halves of the contract: 1. Clean localStorage → navbar + hero CORE = `rgb(207, 217, 201)`, SCOPE = `rgb(44, 140, 140)`. 2. Seeded `cs-theme-overrides` with red accent → navbar + hero recolor to red. - **UPDATED: `test-logo-theme-e2e.js`** — replaces the old "must NOT be sage" sentinel (sage was a regression marker; it's now the brand default) with a theme-reactivity probe that overrides `--logo-accent` / `--logo-accent-hi` directly and asserts the wordmark fill changes. Duotone, mobile-fit, and clip checks are unchanged. ## Verification - Default load: sage CORE + teal SCOPE in navbar AND hero ✔ (asserted by step 1 of the new e2e). - Customizer override: wordmark follows `accent` / `accentHover` ✔ (asserted by step 2 of the new e2e + the theme-reactivity probe in `test-logo-theme-e2e.js`). - Preflight: all hard gates green (PII, branch scope, red commit, CSS-var defined, CSS self-fallback, LIKE-on-JSON, sync migration); all warnings green. ## Browser verified E2E assertion added: `test-logo-default-sage-teal-e2e.js:73` (default sage), `test-logo-default-sage-teal-e2e.js:124` (customizer override). CI runs both via `deploy.yml:243`. Browser verified: covered by Chromium e2e against `http://localhost:13581` in CI; staging URL TBD on merge. --------- Co-authored-by: openclaw-bot <bot@openclaw.local>
This commit is contained in:
1 parent
63c7ee2fa6
commit
cfd1903c6b
6 files changed
+289
-29
No files matched your search
+63
-14
@@ -32,7 +32,13 @@
|
||||
const { chromium } = require('playwright');
|
||||
|
||||
const BASE = process.env.BASE_URL || 'http://localhost:13581';
|
||||
const LEGACY_SAGE = 'rgb(207, 217, 201)';
|
||||
// Note: rgb(207, 217, 201) is the brand sage default for --logo-accent
|
||||
// (see test-logo-default-sage-teal-e2e.js). It is NO LONGER a failure
|
||||
// signal here; the original "must not be sage" assertion was written
|
||||
// when sage meant "baked-into-SVG-attr regression" and the wordmark was
|
||||
// supposed to follow --accent (then blue). Now sage is the intentional
|
||||
// brand identity and the test below asserts theme-reactivity by mutating
|
||||
// --logo-accent directly and observing the fill change instead.
|
||||
|
||||
function fail(msg) {
|
||||
console.error(`test-logo-theme-e2e.js: FAIL — ${msg}`);
|
||||
@@ -74,8 +80,8 @@ async function main() {
|
||||
await page.evaluate(() => { document.documentElement.setAttribute('data-theme', 'light'); });
|
||||
|
||||
// 1. Navbar wordmark must be inline-SVG <text> (not <img>) and computed
|
||||
// fill must NOT be the legacy hardcoded sage. We grep for any <text>
|
||||
// with textContent CORE or SCOPE inside .nav-brand.
|
||||
// fill must be theme-reactive: setting --logo-accent / --logo-accent-hi
|
||||
// on :root must repaint the wordmark.
|
||||
const navWordmarkFills = await page.evaluate(() => {
|
||||
const out = [];
|
||||
const root = document.querySelector('.nav-brand');
|
||||
@@ -93,12 +99,35 @@ async function main() {
|
||||
if (!navWordmarkFills.out || navWordmarkFills.out.length < 2) {
|
||||
fail(`navbar inline-SVG wordmark <text> CORE/SCOPE not found (found: ${JSON.stringify(navWordmarkFills.out)}). Navbar logo must be inline <svg> so CSS vars apply.`);
|
||||
}
|
||||
for (const w of navWordmarkFills.out) {
|
||||
if (w.fill === LEGACY_SAGE) {
|
||||
fail(`navbar wordmark "${w.tc}" still computes legacy sage fill ${LEGACY_SAGE} — wordmark fill must theme via CSS var`);
|
||||
}
|
||||
// Theme-reactivity probe: override --logo-accent / --logo-accent-hi and
|
||||
// confirm fills change. This replaces the old "must not be legacy sage"
|
||||
// assertion (sage is now the brand default — see test-logo-default-sage-teal-e2e.js).
|
||||
const navReact = await page.evaluate(() => {
|
||||
const root = document.querySelector('.nav-brand');
|
||||
const before = {};
|
||||
root.querySelectorAll('svg text').forEach((t) => {
|
||||
const tc = (t.textContent || '').trim();
|
||||
if (tc === 'CORE' || tc === 'SCOPE') before[tc] = getComputedStyle(t).fill;
|
||||
});
|
||||
document.documentElement.style.setProperty('--logo-accent', '#123456');
|
||||
document.documentElement.style.setProperty('--logo-accent-hi', '#abcdef');
|
||||
const after = {};
|
||||
root.querySelectorAll('svg text').forEach((t) => {
|
||||
const tc = (t.textContent || '').trim();
|
||||
if (tc === 'CORE' || tc === 'SCOPE') after[tc] = getComputedStyle(t).fill;
|
||||
});
|
||||
// Reset so later assertions on default colors aren't polluted.
|
||||
document.documentElement.style.removeProperty('--logo-accent');
|
||||
document.documentElement.style.removeProperty('--logo-accent-hi');
|
||||
return { before, after };
|
||||
});
|
||||
if (navReact.before.CORE === navReact.after.CORE) {
|
||||
fail(`navbar CORE fill did not change when --logo-accent was overridden (${navReact.before.CORE} → ${navReact.after.CORE}); wordmark must theme via --logo-accent`);
|
||||
}
|
||||
console.log(` ✅ navbar wordmark fills are theme-reactive (${navWordmarkFills.out.map((w) => w.tc + '=' + w.fill).join(', ')})`);
|
||||
if (navReact.before.SCOPE === navReact.after.SCOPE) {
|
||||
fail(`navbar SCOPE fill did not change when --logo-accent-hi was overridden (${navReact.before.SCOPE} → ${navReact.after.SCOPE}); wordmark must theme via --logo-accent-hi`);
|
||||
}
|
||||
console.log(` ✅ navbar wordmark fills are theme-reactive (CORE ${navReact.before.CORE}→${navReact.after.CORE}, SCOPE ${navReact.before.SCOPE}→${navReact.after.SCOPE})`);
|
||||
passed++;
|
||||
|
||||
// 2. Hero SVG must NOT have a full-canvas opaque background rect.
|
||||
@@ -136,7 +165,8 @@ async function main() {
|
||||
console.log(` ✅ hero SVG has no full-canvas opaque background rect`);
|
||||
passed++;
|
||||
|
||||
// 3. Hero wordmark CORE/SCOPE must not compute legacy sage fill on light theme.
|
||||
// 3. Hero wordmark CORE/SCOPE must be theme-reactive — overriding
|
||||
// --logo-accent / --logo-accent-hi must repaint the hero wordmark too.
|
||||
const heroWordmarkFills = await page.evaluate(() => {
|
||||
const hero = document.querySelector('.home-hero');
|
||||
if (!hero) return { error: '.home-hero missing' };
|
||||
@@ -153,12 +183,31 @@ async function main() {
|
||||
if (!heroWordmarkFills.out || heroWordmarkFills.out.length < 2) {
|
||||
fail(`hero inline-SVG wordmark <text> CORE/SCOPE not found (found: ${JSON.stringify(heroWordmarkFills.out)})`);
|
||||
}
|
||||
for (const w of heroWordmarkFills.out) {
|
||||
if (w.fill === LEGACY_SAGE) {
|
||||
fail(`hero wordmark "${w.tc}" still computes legacy sage fill ${LEGACY_SAGE} — invisible on light theme`);
|
||||
}
|
||||
const heroReact = await page.evaluate(() => {
|
||||
const hero = document.querySelector('.home-hero');
|
||||
const before = {};
|
||||
hero.querySelectorAll('svg text').forEach((t) => {
|
||||
const tc = (t.textContent || '').trim();
|
||||
if (tc === 'CORE' || tc === 'SCOPE') before[tc] = getComputedStyle(t).fill;
|
||||
});
|
||||
document.documentElement.style.setProperty('--logo-accent', '#654321');
|
||||
document.documentElement.style.setProperty('--logo-accent-hi', '#fedcba');
|
||||
const after = {};
|
||||
hero.querySelectorAll('svg text').forEach((t) => {
|
||||
const tc = (t.textContent || '').trim();
|
||||
if (tc === 'CORE' || tc === 'SCOPE') after[tc] = getComputedStyle(t).fill;
|
||||
});
|
||||
document.documentElement.style.removeProperty('--logo-accent');
|
||||
document.documentElement.style.removeProperty('--logo-accent-hi');
|
||||
return { before, after };
|
||||
});
|
||||
if (heroReact.before.CORE === heroReact.after.CORE) {
|
||||
fail(`hero CORE fill did not change when --logo-accent was overridden (${heroReact.before.CORE} → ${heroReact.after.CORE})`);
|
||||
}
|
||||
console.log(` ✅ hero wordmark fills are theme-reactive (${heroWordmarkFills.out.map((w) => w.tc + '=' + w.fill).join(', ')})`);
|
||||
if (heroReact.before.SCOPE === heroReact.after.SCOPE) {
|
||||
fail(`hero SCOPE fill did not change when --logo-accent-hi was overridden (${heroReact.before.SCOPE} → ${heroReact.after.SCOPE})`);
|
||||
}
|
||||
console.log(` ✅ hero wordmark fills are theme-reactive (CORE ${heroReact.before.CORE}→${heroReact.after.CORE}, SCOPE ${heroReact.before.SCOPE}→${heroReact.after.SCOPE})`);
|
||||
passed++;
|
||||
|
||||
// 4 & 5. Duotone — CORE fill must differ from SCOPE fill in BOTH navbar
|
||||
|
||||
Reference in new issue
Block a user