fix(frontend): style the paywall header and guard undefined class names
The onboarding paywall wrote `dialog-header`, a class no stylesheet defines, so its close button stacked under the title instead of sitting beside it. The session-delete confirm buttons had the same problem, and a `message-entry` wrapper added in August had quietly killed the `.message + .message` spacing rule in the main chat. Fixes all three against the patterns already in the codebase, then adds a contract test so the next undefined class fails instead of shipping: it scopes itself to our own class families so Tailwind utilities stay out, strips CSS comments before deciding what counts as defined, and carries an allowlist of the fifteen deliberate no-op modifiers that must shrink rather than grow. Also collapses the paywall's duplicate display heading into the intro sentence, leaving one heading in the dialog. BUG-434, BUG-435, BUG-436. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
This commit is contained in:
@@ -6638,3 +6638,51 @@
|
||||
- 修复版本:待发布
|
||||
|
||||
|
||||
## BUG-434 | 入门付费墙的关闭按钮掉到标题下面,弹窗头部从未有过样式
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-08-29
|
||||
- 最近更新:2026-08-29
|
||||
- 影响面:`/` 入门问题完成后弹出的「解锁完整咨询」弹窗,移动端最明显
|
||||
- 用户现象:标题「解锁完整咨询」独占一行,关闭「×」以灰色圆角块的形式落在标题下方靠左,和礼物图标那段挤在一起;头部与正文之间没有间距。
|
||||
- 触发条件:打开该弹窗即出现,与账号状态无关。
|
||||
- 根因:`onboarding-redeem-paywall.tsx` 写的是 `<div className="dialog-header">`,而 `dialog-header` 这个类在全仓 CSS 里**没有任何定义**。同类弹窗(`account-dialog-overlay.tsx`、`membership/page.tsx`)用的都是 `<header className="account-modal-header">`(`display:flex; justify-content:space-between; padding-bottom`)。付费墙自 `a17ff258` 引入起就拼错,未被任何测试或样式覆盖,因此一直是无样式块级 div,标题与按钮竖排。
|
||||
- 修复:改为 `<header className="account-modal-header">`,与另外两处弹窗完全一致。未新增任何 CSS,未改文案、`aria-label="关闭"`、`aria-modal`、焦点陷阱与 44px 触达。
|
||||
- 验证:`frontend/tests/membership-page.test.ts` 新增两条 —— 一条锁付费墙必须复用 `account-modal-header` 且不得再出现 `dialog-header`;一条**通用守卫**,抽出该组件所有静态 `className` 逐个断言在 `globals.css` 里有对应选择器。反向验证:把 `dialog-header` 放回去,两条同时变红;还原后 38 pass / 0 fail。
|
||||
- 防复发:弹窗头部一律用 `account-modal-header`,不得为单个弹窗另造头部类名。新增组件若引入新类名,必须同时在 `globals.css` 落规则 —— 上面那条通用守卫会挡住这类拼写漂移。
|
||||
- 相关记录:BUG-433
|
||||
- 复发自:无
|
||||
- 修复版本:待发布
|
||||
|
||||
## BUG-435 | 删除会话确认弹窗的两个按钮没有任何样式,"确认删除"也不是红色
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-08-29
|
||||
- 最近更新:2026-08-29
|
||||
- 影响面:`/` 侧边栏删除会话时弹出的「删除聊天记录?」确认框
|
||||
- 用户现象:「取消」和「确认删除」渲染成浏览器原生灰色按钮 —— 没有圆角、没有 44px 高度、没有内边距,破坏性操作也没有任何红色提示。
|
||||
- 触发条件:打开该确认框即出现。
|
||||
- 根因:`page.tsx:4000` 的「取消」完全没写 class;`page.tsx:4001` 的「确认删除」写的是 `danger-button`,而这个类在全仓 CSS 里没有定义。全局只给 `button` 设了 `font: inherit; color: inherit`,没有任何兜底规则,所以两个按钮都是裸原生按钮。同一文件 60 行之前的退出登录确认框用的是正确写法 `button-secondary` + `button-primary danger-primary`。
|
||||
- 修复:两个按钮改成与退出登录框完全一致的 `button-secondary` / `button-primary danger-primary`。未新增 CSS,未改文案与 `role="alertdialog"`。星盘库「删除」上同样无定义的 `danger-button` 修饰符一并去掉(它本就没生效,渲染不变)。
|
||||
- 验证:`./node_modules/.bin/next build` 后用类名扫描脚本核对,`danger-button` 已从"无规则类名"清单消失;`tsc --noEmit` exit 0、`eslint` 0 error、全量测试无新增失败。
|
||||
- 防复发:破坏性确认框一律复用 `button-secondary` + `button-primary danger-primary`,不得临时造修饰符。新类名必须同时在 `globals.css` 落规则 —— 参见 BUG-434 在 `membership-page.test.ts` 里加的通用守卫。
|
||||
- 相关记录:BUG-434
|
||||
- 复发自:无
|
||||
- 修复版本:待发布
|
||||
|
||||
## BUG-436 | 主对话消息间距规则从 8-19 起失效,消息比设计稿挤
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-08-29
|
||||
- 最近更新:2026-08-29
|
||||
- 影响面:`/` 主对话(非空、非生时校正会话)里相邻消息之间的竖向间距
|
||||
- 用户现象:消息之间只剩气泡自身的内边距,比设计稿定的 `--space-8`(移动端 `--space-6`)窄。
|
||||
- 触发条件:任何有历史消息的普通咨询会话。
|
||||
- 根因:`globals.css` 的 `.conversation:not(.is-empty):not(.is-rectification) .message + .message { margin-top: var(--space-8) }` 写于 `200c39d2`(2026-07-22),当时消息是 `.message-list` 的直接兄弟。`7d667fec`(2026-08-19)给每条消息套了一层 `<div className="message-entry">`,而这个类在 CSS 里没有任何定义,两条 `.message` 从此不再相邻,选择器永久不匹配。同一规则组里 `.message` 又被覆盖成 `padding: 0`,于是间距归零。`3198fb6b` 把同一层包装搬进 `ChatTranscript`,未改变这一点。
|
||||
- 修复:选择器改为 `.message-entry + .message-entry`,桌面 `--space-8`、移动 `--space-6` 数值不变。`.message-list` 里除 `.message-entry` 外只有可选的 `.error-message`,不会误伤。引导语消息在 `.welcome` 内且只在 `.is-empty` 时渲染,本就被选择器排除。
|
||||
- 验证:`frontend/tests/class-name-definition-contract.test.ts`(本次新增的通用守卫)反向验证 —— 把选择器改回 `.message + .message` 后 `message-entry` 立即被判为无规则类名,测试变红;改回则绿。
|
||||
- 防复发:给消息列表加包装层时必须同步迁移依赖相邻兄弟的选择器。新类名漏定义由上述守卫兜底;该守卫会剥掉 CSS 注释再判定,避免"只在注释里出现过"被当成已定义。
|
||||
- 相关记录:BUG-434、BUG-435
|
||||
- 复发自:无
|
||||
- 修复版本:待发布
|
||||
|
||||
|
||||
Reference in New Issue
Block a user