From ef591f673e3e5124787741af09a5dabb6d62b1f5 Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Thu, 13 Aug 2026 16:27:59 +0800 Subject: [PATCH] fix(frontend): restore homepage display typography --- docs/BUG_HISTORY.md | 15 +++++++++++++++ frontend/src/app/globals.css | 8 ++++---- frontend/tests/consultation-entrypoint.test.ts | 13 +++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 9d53efea..2ef6ca01 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -3108,3 +3108,18 @@ - 防复发:候选卡 CTA 与数据库状态机必须共享同一行为合同;任何“改选”文案都必须有跨分钟成功路径测试,不能只测试按钮未禁用或同值幂等。 - 相关记录:BUG-127、BUG-144、BUG-179、BUG-181 - 修复版本:本次 staging 发布提交(精确 SHA 以提交与部署结果为准) + +## BUG-183 | 首页主标题展示字体被重构为粗黑体 + +- 状态:resolved(本地候选,待 staging 部署与视觉验收) +- 首次发现:2026-08-13 +- 最近更新:2026-08-13 +- 影响面:首页欢迎主标题与两个产品入口卡片标题。 +- 用户现象:首页原有的宋体/衬线标题变成黑体加粗,整体视觉层级和既有编辑感丢失。 +- 触发条件:加载 `starter-hero` 与 `product-entrypoint` 首页区域。 +- 根因:前端视觉清理提交将 `.starter-hero h1` 和 `.product-entrypoint-copy h2` 从既有 `var(--font-display)` / `font-weight: 400` 改为 `var(--font-body)` / `font-weight: 650-680`;中文因此回退到 `PingFang SC` 等无衬线字体并明显加粗。全局展示字体变量本身并未删除。 +- 修复:仅恢复两个首页标题使用现有 `var(--font-display)` 和常规字重 `400`,保留当前重构后的字号、行高与布局,不新增字体依赖或平台硬编码。 +- 验证:新增首页字体合同测试,分别锁定欢迎主标题和产品入口标题使用 `font-display`、`font-weight: 400`,并拒绝回退到 `font-body`;聚焦测试、目标 ESLint、生产构建、`git diff --check` 与 staging 视觉验收按发布结果记录。 +- 防复发:首页编辑型主标题与产品入口标题必须继续使用设计系统的展示字体 token;通用去风格化或排版重构不得把展示标题批量替换成正文无衬线字体。 +- 相关记录:BUG-026 +- 修复版本:本次 staging 发布提交(精确 SHA 以提交与部署结果为准) diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index 87884ccc..cc9584d3 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -1014,9 +1014,9 @@ input:not([class^="ant-"]):not([class*=" ant-"]):not(.ant-picker input):disabled max-width: 760px; margin: 0; color: var(--color-ink); - font-family: var(--font-body); + font-family: var(--font-display); font-size: clamp(34px, 5vw, 52px); - font-weight: 680; + font-weight: 400; letter-spacing: -.04em; line-height: 1.08; text-wrap: balance; @@ -1141,9 +1141,9 @@ input:not([class^="ant-"]):not([class*=" ant-"]):not(.ant-picker input):disabled .product-entrypoint-copy h2 { margin: 0; color: var(--color-ink); - font-family: var(--font-body); + font-family: var(--font-display); font-size: clamp(24px, 2.4vw, 31px); - font-weight: 650; + font-weight: 400; letter-spacing: -.03em; line-height: 1.12; } diff --git a/frontend/tests/consultation-entrypoint.test.ts b/frontend/tests/consultation-entrypoint.test.ts index 859c3e5d..06befb86 100644 --- a/frontend/tests/consultation-entrypoint.test.ts +++ b/frontend/tests/consultation-entrypoint.test.ts @@ -266,6 +266,19 @@ test("starter cards use transient pressed feedback instead of sticky hover shadi for (const rule of disabledProductRules) assert.match(rule[1], /opacity:\s*1\s*;/); }); +test("starter homepage keeps its editorial display typography", () => { + const styles = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8"); + const heroHeading = styles.match(/\.starter-hero h1\s*\{([^}]*)\}/)?.[1] ?? ""; + const entrypointHeading = styles.match(/\.product-entrypoint-copy h2\s*\{([^}]*)\}/)?.[1] ?? ""; + + assert.match(heroHeading, /font-family:\s*var\(--font-display\)\s*;/); + assert.match(heroHeading, /font-weight:\s*400\s*;/); + assert.doesNotMatch(heroHeading, /font-family:\s*var\(--font-body\)/); + assert.match(entrypointHeading, /font-family:\s*var\(--font-display\)\s*;/); + assert.match(entrypointHeading, /font-weight:\s*400\s*;/); + assert.doesNotMatch(entrypointHeading, /font-family:\s*var\(--font-body\)/); +}); + test("starter homepage stays editorial and hides technical chart parameters", () => { const source = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8"); const styles = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8");