Files
Jyotisha/docs/tasks/TASK-settings-dialog-size-and-nav-20260915.md
T
Jesse_ChenandClaude Fable 5 4c002a084e docs(tasks): brief the settings dialog size recurrence and the nav emphasis bar
BUG-698 复发自 BUG-554。四个分区确实都映射到 .settings-modal,CSS 里
width 与 height 也都写了——但 .settings-modal 的 height/max-height 只用
dvh,没有 vh 回退。不支持 dvh 时整条声明作废,height 退回 auto,高度改由
内容决定,正是「切分区就立马缩小」。全文件 18 处 dvh 只有 sidebar-provider
那一处配了回退,本仓自己知道这个写法。

BUG-554 的防复发「设置弹窗必须同时声明 width 与 height」拦不住这次:它
检查声明存在性,不检查声明是否生效;守它的断言也只是一句 CSS 文本匹配。
本单把防线换成「height 用 dvh 必须先写 vh 回退」的全文件契约测试。

首要嫌疑不等于已证实——本会话没有浏览器。任务 1.1 要求执行方先量四个分区
的 getBoundingClientRect 并确认 height 是否被划掉,量不出来就转 investigating
交回产品,不得盲改。

另去掉设置分区菜单的左侧强调条(移动端下边框同理)。删之前必须先拆开选中态
与悬停态——它们共用同一条声明,色条是当前唯一的区分。左侧会话列表的 2px 色条
本轮保留,口径暂时不一致已授权。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
2026-09-15 04:56:45 +00:00

14 KiB
Raw Blame History

TASK · 设置弹窗尺寸随分区变化(BUG-698,复发自 BUG-554)+ 分区菜单去掉强调条

  • 日期:2026-09-15
  • 基线 commitorigin/staging @ 6c748d86
  • 执行分支:codex/settings-dialog-size-and-nav-20260915
  • 工作树:.worktrees/settings-dialog-size-and-nav-20260915
  • 线上状态:staging 当前部署 8d56d0ab(早于本基线两轮实现提交,但晚于 BUG-554 的修复 dc6598d7)。用户现象是在已含 BUG-554 修复的版本上复现的。

1. 产品诉求(原话)

设置面板的弹窗大小不一样,选别的就立马缩小了。而且菜单项不要加粗左边框的强调条。

两件事:任务 1 是缺陷(BUG-698),任务 2 是产品决策。


2. 事故实证

行号会漂移,定位以符号名为准。核对于 origin/staging@6c748d86

2.1 这是 BUG-554 的复发

docs/BUG_HISTORY.mdBUG-554 | 设置弹窗随分区跳变,星盘资料铺开整张表单,账户与点数离开首页resolved,修复版本 dc6598d7):

  • 当时的用户现象第一句就是「三个设置分区弹窗尺寸不同」。
  • 当时的根因:accountDialogClasses 给每个分区不同宽度,高度随内容撑开。
  • 当时的修复:四个分区共用 .settings-modal 固定尺寸。
  • 当时的防复发:「设置弹窗必须同时声明 width 与 height」

现在 frontend/src/lib/home-types.tsaccountDialogClasses 的四个分区确实都是 "settings-modal"globals.css 里也确实同时声明了 width 与 height

.settings-modal { width: min(100vw - 32px, 880px); height: min(84dvh, 640px); max-height: min(84dvh, 640px); overflow: hidden; display: grid; grid-template-rows: auto 1fr; }

防复发措施仍在,现象仍复现。 说明那条防复发写错了层次——它防的是「有没有写 height」,防不住「写了但没生效」。

守着它的测试也只是一句文本匹配,frontend/tests/account-dialog-overlay.test.ts

assert.match(styles, /\.settings-modal \{[^}]*width:[^}]*height:/);

它读的是 CSS 源文本,既不渲染也不量盒子,所以声明只要存在就绿。

2.2 首要嫌疑:dvh 没有 vh 回退,不支持时整条 height 被丢弃

.settings-modalheightmax-height 都只写了 dvh没有 vh 回退。浏览器遇到不认识的单位会整条声明作废,于是:

  • height: min(84dvh, 640px) 作废 → height 回到 auto高度由内容决定
  • max-height: min(84dvh, 640px) 作废 → 落回 .account-modalmax-height: min(84dvh, 760px)同样作废 → 没有任何高度约束

结果正好是用户描述的:内容多的分区高,内容少的分区矮,切分区就立刻变大小。而 width 用的是 100vw,不受影响——所以看上去是「高度在跳,宽度没动」。

这个仓库自己知道要写回退globals.css 里就有一处标准写法:

.group\/sidebar-provider[data-viewport] { height: 100vh; height: 100dvh; min-height: 0; overflow: hidden; }

全文件 18 处 dvh 声明,只有这一处配了 vh 回退.settings-modal 是其中后果最严重的一处,因为它是唯一一个「固定高度就是功能本身」的面板。

⚠️ 这是首要嫌疑,不是已证实的根因。 会话环境没有浏览器,无法实测。执行方必须先复现并确认,见任务 1.1。若实测发现 dvh 正常生效、尺寸仍在变,按 1.2 继续排查,不得直接把回退当作修复交付

2.3 分区菜单的强调条

frontend/src/app/globals.css

.settings-dialog-nav-item:hover,
.settings-dialog-nav-item[aria-current="page"] { background: var(--color-canvas-muted); color: var(--color-ink); }
.settings-dialog-nav-item[aria-current="page"] { box-shadow: inset 2px 0 0 var(--color-action); }

移动端(@media (max-width: 767px),导航变成顶部四栏)是同一条的下边框版本:

.settings-dialog-nav-item[aria-current="page"] { box-shadow: inset 0 -2px 0 var(--color-action); }

产品要去掉的就是这两条 box-shadow

去掉之后有一个必须同时解决的问题:选中态与悬停态共用同一条规则(上面第一条),强调条是当前唯一区分它们的东西。直接删 box-shadow 会让「鼠标划过某项」和「当前就在某项」长得一模一样。任务 2 必须把这两态拆开。


3. 决策记录(产品已授权)

  1. 去掉设置分区菜单的左侧强调条(移动端的下边框同理)。选中态改用面(背景)与墨色等级表达,不用色条。
  2. 这条只针对设置弹窗的分区菜单。左侧会话列表当前会话的 2px 色条(--sidebar-ring,见 frontend/DESIGN.md「Where the action color appears」第 2 条)本轮不动。改完两处观感会不一致,产品知情并接受;若之后也要去掉,另开一轮。
  3. 不要用加粗(font-weight)来区分选中态。 产品原话就是不要"加粗"的强调;frontend/DESIGN.md 也写明导航层级来自墨色等级而不是色相。
  4. 尺寸问题按缺陷处理,占 BUG-698,并在记录里写明复发自 BUG-554、旧防复发为何没拦住。

4. 硬红线

  1. ./node_modules/.bin/tsc --noEmit 0 错;npm run lint 0 error
  2. 测试总数不得低于开工时 origin/staging 的实测;改既有断言写「原值 / 新值 / 原因」三栏。
  3. BUG-554 的其余防复发条款继续有效,不得顺手破坏:星盘资料默认视图不得无条件渲染 <form/ 保持 ○ Static,不得 useSearchParams;收银台仍 window.open;硬跳转清单不得变长。
  4. 不得改 accountDialogClasses 让四个分区重新用不同的类——那正是 BUG-554 的原始根因。
  5. 不得动 adminantd + Refine)。
  6. 不得顺手升级依赖。
  7. 改 UI 的同一提交内更新 frontend/DESIGN.md

5. 任务分解

任务 1 · BUG-698:设置弹窗尺寸随分区变化

1.1 先复现并确认机制(不得跳过)

  1. 起本地 dev,登录,打开设置弹窗,在四个分区之间来回切:个人资料 → 星盘资料 → 账户与点数 → 通用设置。
  2. 用 DevTools 量 section.account-modal.settings-modalgetBoundingClientRect(),四个分区各记一次。
  3. 在 Computed 面板看 heightmax-height计算值,以及 Styles 面板里 .settings-modalheight 声明有没有被划掉
  4. 把四组数字和结论写进 PROGRESS。
  • height 被划掉 / 计算值为 auto → §2.2 成立,做 1.2。
  • height 正常生效、盒子四个分区一致 → 说明用户看到的是别的东西(例如内容在固定盒子里塌成一小块、或某个分区的内容把 overflow: hidden 顶破)。此时不要硬改 CSS,把量到的数字和截图写进 PROGRESS,本任务转 investigating,由产品补充现象(哪两个分区、什么浏览器、窗口多大)后再开一轮。

1.2 修复:给固定高度补 vh 回退

按仓库既有写法(.group\/sidebar-provider[data-viewport] 那一行)补成两条声明,新值写在旧值之后:

.settings-modal {
  width: min(100vw - 32px, 880px);
  height: min(84vh, 640px);
  height: min(84dvh, 640px);
  max-height: min(84vh, 640px);
  max-height: min(84dvh, 640px);
  
}

同样处理同一批里高度即功能的几处,其余只写 max-height 的可以不动(作废后退化成无上限,不会让盒子随分区跳变):

  • .account-modalmax-height: min(84dvh, 760px)
  • 移动端 .settings-modal { height: 100dvh }.account-modal { max-height/min-height: 100dvh }

1.3 把防复发从「有没有写」升级成「量不量得到」

现有断言只是文本匹配,挡不住本次复发。新增两条契约测试:

  • 回退契约globals.css 中凡是在 height(非 max-height)里用了 dvh 的规则,同一规则内必须存在一条 vh 版本的同名属性声明,且 vh 在前。这条可以纯文本实现,覆盖全文件而不只是设置弹窗——它才是真正能防住下一次的那条。
  • 同尺寸契约:断言 accountDialogClasses 的四个设置分区映射到同一个类名(现有测试只验了 dialogClass: "settings-modal" 这一个分区的渲染)。

原有的 assert.match(styles, /\.settings-modal \{[^}]*width:[^}]*height:/) 保留,但在它上面加注释说明它只是存在性检查、真正的防线是上面两条。

验收标准(任务 1

  • 1.1 的四组 getBoundingClientRect() 数字写进 PROGRESS,四个分区高度与宽度完全一致。
  • 1.3 的两条新测试通过;故意把某处 height: …dvh 的回退删掉,回退契约测试必须变红(执行方本地验一次,结论写进 PROGRESS,不用把破坏提交上去)。
  • 桌面与 375px 两种宽度下四个分区逐一切换,弹窗外框不跳变——浏览器项,写进 docs/testing/

任务 2 · 分区菜单去掉强调条,并拆开选中态与悬停态

2.1 删除这两条:

.settings-dialog-nav-item[aria-current="page"] { box-shadow: inset 2px 0 0 var(--color-action); }          /* 桌面 */
.settings-dialog-nav-item[aria-current="page"] { box-shadow: inset 0 -2px 0 var(--color-action); }         /* 移动端 */

2.2 把现在共用的那条规则拆成两态。目标:选中比悬停"重"一档,且两者都不用强调色条、不用 font-weight。建议值(执行方可在同族 token 内微调,但必须给出选择理由):

.settings-dialog-nav-item:hover {
  background: color-mix(in srgb, var(--color-canvas-muted) 55%, transparent);
  color: var(--color-ink-secondary);
}
.settings-dialog-nav-item[aria-current="page"] {
  background: var(--color-canvas-muted);
  color: var(--color-ink);
}

即:悬停是一层淡的面 + 次级墨;选中是实的面 + 主墨。frontend/DESIGN.md「Hierarchy inside the nav comes from ink rank, not hue」一致。

2.3 深色主题必须同样成立。--color-canvas-muted 与两级墨色在深色下都有定义,但 55% 混透明后与深色底的对比要复查;frontend/tests/dark-theme-contract.test.ts 若涉及新增 token 需同步。不得引入新的字面色值。

2.4 键盘可达性不受影响::focus-visible 的描边规则不动。选中态不能只靠颜色——aria-current="page" 已经在 DOM 上,屏幕阅读器不受本改动影响,这一点在 PROGRESS 里写明即可。

2.5 frontend/DESIGN.md 同提交更新:在导航/强调色一节写明「设置弹窗分区菜单不使用强调色条,选中与悬停靠面与墨色等级区分」,并写明左侧会话列表的 2px 色条本轮保留,两处口径暂时不同是已知且授权的。

验收标准(任务 2

  • grep -n "inset 2px 0 0 var(--color-action)\|inset 0 -2px 0 var(--color-action)" frontend/src/app/globals.css.settings-dialog-nav-item 上下文无结果。
  • 新增契约测试:.settings-dialog-nav-item[aria-current="page"] 规则内不含 box-shadow,且 :hover[aria-current="page"] 不再共用同一条声明(两者必须是各自独立的规则块)。
  • 浅色与深色各看一遍,悬停与选中肉眼可区分——浏览器项,写进 docs/testing/

任务 3 · 测试与文档

3.1 开工先量基线:

cd .worktrees/settings-dialog-size-and-nav-20260915/frontend
npm ci
npm test 2>&1 | tail -20      # pass / fail / tests 三个数字

3.2 文档:

  • docs/BUG_HISTORY.md 新增 BUG-698,字段齐全。「复发自」一栏必须写 BUG-554,并在「根因」里写清旧防复发(「必须同时声明 width 与 height」)为何没拦住——它检查的是声明存在性,不是声明是否生效。同时回到 BUG-554 那条记录,在「防复发」末尾补一句指向 BUG-698 的修正。
  • frontend/DESIGN.md:任务 2.5 的内容;另加一条 CSS 规则——凡是 heightdvh 的地方必须先写 vh 回退,并说明为什么(不支持时整条声明作废,固定高度会退化成内容高度)。
  • docs/testing/settings-dialog-20260915.md:把任务 1 与 2 里标了「浏览器项」的条目写成可照做的清单。
  • CHANGELOG.md:一条日期 + 一句话标题 + 要点。
  • docs/tasks/PROGRESS-settings-dialog-size-and-nav-20260915.md

6. 让步顺序

  1. 任务 1.1 若复现不出尺寸变化,investigating 并停在那里,把量到的数字交回产品。不得为了"有交付"而盲改 CSS。
  2. 任务 1.3 的回退契约测试若在全文件范围内误伤了合理写法(例如某处确实只能用 dvh),缩小到 height 属性且排除已注释说明的例外,例外清单写进测试文件头部注释。不得因为难写就退回原来的存在性断言。
  3. 任务 2.2 的具体数值可调,但必须让选中比悬停重一档;调完在浅色与深色下都要能分辨。
  4. 绝不让步:不得让四个分区重新使用不同的类;不得用 font-weight 做选中态;不得引入字面色值;BUG-554 的其余防复发条款不得破坏。

7. 开工前置命令

cd /workspace/Jyotisha
git status -sb | head -1
git fetch origin --prune
git worktree add -b codex/settings-dialog-size-and-nav-20260915 \
  .worktrees/settings-dialog-size-and-nav-20260915 origin/staging
cd .worktrees/settings-dialog-size-and-nav-20260915/frontend
npm ci
npm test 2>&1 | tail -20
./node_modules/.bin/tsc --noEmit
npm run lint

纯前端改动,不要求 scripts/pre_work_check.py

交付:git push origin HEAD:staging,推完核对远端 SHA。


8. 串行与依赖

  • 本单改 frontend/src/app/globals.cssTASK-chat-reading-load-20260915TASK-mobile-touch-and-breakpoints-20260915 的实现已合入 staging8144fca26c748d86),以 6c748d86 为基线即可,无需再等。
  • 与那两轮改的是同一文件的不同区段,但它们已经合入,所以本单不与任何在途轮次并行。开工前仍按 AGENTS.md §3 确认状态板上没有新的「执行中」项在动这个文件。

9. BUG 编号

  • 本单占用 BUG-698(任务 2 是产品决策,不占编号)。
  • origin/staging@6c748d86 的当前最大号是 BUG-697BUG-695~697 由触控与断点那轮占用)。
  • 开工时仍需核对 docs/BUG_HISTORY.md 的当前最大号。