From 4d69aaee502a842636d46c3546016350cff21d30 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 15 Oct 2026 23:22:18 +0800 Subject: [PATCH] fix(frontend): scope the credits button skins to the user-center shell The user-center route rendered a 4px top-nav publish chip while every other route kept the 50px pill. assets/css/routes/user-center/credits.css restated border-radius on bare legacy colour modifiers (.but.jb-blue, .but.b-blue-2, .but.c-blue-2.hollow, .but.c-green.hollow). Those rules are (0,2,0) and load after public.css, so they out-rank .but.radius's 50px and flatten the publish chip, which is newadd-btns but jb-blue radius, down to 4px. The same leak also repainted every site-wide .but.jb-blue outside the panel with the flat #3b82f6 skin instead of the legacy gradient, so login, submit, badge and cashier buttons lost their reference surface on that route too. Scope the four rules to .uc-content, the shell every credits panel and its modals render inside (templates/pages/page-profile.php wraps templates/parts/user-center/panel.php). The panel keeps its own button skins and the top-nav chips get the reference pill back. The .btn-block restatement that sat in the same block is byte-identical to the one in core/buttons.css, which loads earlier on every page, so it could never win; it is dropped rather than scoped. Verified: node --test across tests/ (604 passing), plus a stubbed navbar rendered against each route's real stylesheet set measuring the computed border-radius of the publish chip and of the panel's own buttons. A new contract test fails on the previous stylesheet and passes on this one. --- assets/css/routes/user-center/credits.css | 32 +++++++++++++------ .../legacy-navigation-contract.test.cjs | 29 +++++++++++++++++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/assets/css/routes/user-center/credits.css b/assets/css/routes/user-center/credits.css index b037f232..2f2f69af 100644 --- a/assets/css/routes/user-center/credits.css +++ b/assets/css/routes/user-center/credits.css @@ -304,12 +304,24 @@ body.uc-modal-open { overflow: hidden; } -.btn-block { - display: block; - width: 100%; -} -.but.jb-blue, -.but.b-blue-2 { +/* Scoped to the user-center content shell. These are the credits panel's own + * button skins, and every element they target renders inside .uc-content (the + * panels and their modals are all emitted through templates/parts/user-center/ + * panel.php, which templates/pages/page-profile.php wraps in .uc-content). + * + * Left unscoped they are (0,2,0) rules that load after public.css, so they + * out-rank the legacy .but.radius pill and flatten every .but.jb-blue on the + * page down to 4px. The top-nav publish chip is .but.jb-blue.radius, so on the + * user-center route it lost its 50px pill and no longer matched the homepage. + * Site-wide .but.jb-blue callers outside the panel (login, submit, badge and + * cashier buttons) also picked up the flat #3b82f6 skin instead of the legacy + * gradient. + * + * The .btn-block restatement that used to sit here was byte-identical to the + * one in core/buttons.css, which loads earlier on every page, so it could never + * win and is dropped rather than scoped. */ +.uc-content .but.jb-blue, +.uc-content .but.b-blue-2 { background: #3b82f6; color: #fff; border: 0; @@ -317,18 +329,18 @@ body.uc-modal-open { padding: 0.45em 1em; cursor: pointer; } -.but.c-blue-2.hollow, -.but.c-green.hollow { +.uc-content .but.c-blue-2.hollow, +.uc-content .but.c-green.hollow { background: transparent; border: 1px solid currentColor; border-radius: 4px; padding: 0.4em 0.9em; cursor: pointer; } -.but.c-blue-2 { +.uc-content .but.c-blue-2 { color: #3b82f6; } -.but.c-green { +.uc-content .but.c-green { color: #16a34a; } diff --git a/tests/navigation/legacy-navigation-contract.test.cjs b/tests/navigation/legacy-navigation-contract.test.cjs index a5edd529..a713721b 100644 --- a/tests/navigation/legacy-navigation-contract.test.cjs +++ b/tests/navigation/legacy-navigation-contract.test.cjs @@ -180,6 +180,35 @@ test('guest account member VIP and publish contracts share reference header DOM' assert.match(userboxCss, /\.aksrt-header-userbox\s*>\s*\.mt6\.em09\s*>\s*\.but\.block\s*\{[^}]*display:\s*block;[^}]*box-sizing:\s*border-box;[^}]*width:\s*100%;/s); }); +test('route and feature modules do not restyle the legacy top-nav chips', () => { + // Route and feature modules may not restyle the legacy .but colour modifiers + // without an enclosing scope. The top-nav chips ride the legacy geometry + // verbatim (newadd-btns but radius and pay-vip but jb-red radius + // payvip-icon), so their pill comes from .but.radius at (0,2,0). A later, + // equally specific rule that restates border-radius on a bare .but. + // out-ranks it and flattens the pill: user-center/credits.css did exactly that + // with .but.jb-blue, so the user-center route rendered a 4px publish chip while + // every other route kept the 50px one. Such rules must be scoped to their own + // shell, as credits.css now is with .uc-content. + const moduleCss = [ + ...listFiles('assets/css/routes', new Set(['.css'])), + ...listFiles('assets/css/frontend', new Set(['.css'])), + ].filter((file) => file !== 'assets/css/frontend/header-userbox.css'); + for (const file of moduleCss) { + const css = read(file); + for (const [, selector, declarations] of css.matchAll(/([^{}]+)\{([^{}]*)\}/g)) { + if (!/border-radius/.test(declarations)) continue; + for (const part of selector.split(',')) { + assert.doesNotMatch( + part.trim(), + /^\.but\./, + `${file} restates border-radius on an unscoped legacy .but modifier (${part.trim()}); scope it to the module's own shell so the top-nav chips keep the reference pill` + ); + } + } + } +}) + test('the account popover rows match the reference user box structure', () => { const identity = read('inc/helpers/aksrt-identity.php'); const legacyMainCss = read('assets/css/main.css');