Explorar el Código

feat(web): deepen composer stroke to l2, widen menu radii to 20px

The composer hairline moves one step up from the menus' l1; the seven
menu-fill dropdown cards grow from 16px to 20px corners. Notes and the
token comment record the new layering.
yx.zhang hace 4 semanas
padre
commit
3ce5604a71

+ 2 - 2
.agents/notes/implemented/feature/2026-09-01-web-elevation-stroke-shadows.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-09-01-web-elevation-stroke-shadows.md
-2026-09-01-web-elevation-stroke-shadows.md: 774c9d996958cbc46cb21daaed928f9386c33421
-2026-09-01-web-elevation-stroke-shadows.zh.md: cb6dd3563952d97725d5e451c56e7fa7a710abaf
+2026-09-01-web-elevation-stroke-shadows.md: d3622271f6656c8f7aef1d0f8681fe3cb2861854
+2026-09-01-web-elevation-stroke-shadows.zh.md: 63f2213a0f8e50fb95d5f1b45507fba8c02d9619

+ 2 - 2
.agents/notes/implemented/feature/2026-09-01-web-elevation-stroke-shadows.md

@@ -12,11 +12,11 @@ Elevated web-client surfaces — menus, popovers, modals, panels, floating butto
 
 `gradient-shadow-text.css` (the ui-theme shadow owner) defines the elevation tokens beside the `--dsw-shadow-lv*` scale:
 
-- `--dsw-elevation-stroke-color` — the hairline color, defaulting to `--dsw-alias-border-l4` (black 16% light, white 20% dark); components rebind it per surface or state, and every menu-fill surface (`--dsw-specific-menu` background) and the composer rebind the lightest `--dsw-alias-border-l1`, both quieter than panels and buttons. The default is declared on `body` alone while the derived tokens below are re-declared on `body, body *`: a custom property computes with `var()` already substituted, so body-only derived tokens would bake in body's color and make every rebind a no-op (the same per-element re-substitution scrollbar.css states for `--dsh-scrollbar-thumb`).
+- `--dsw-elevation-stroke-color` — the hairline color, defaulting to `--dsw-alias-border-l4` (black 16% light, white 20% dark); components rebind it per surface or state: every menu-fill surface (`--dsw-specific-menu` background) rebinds the lightest `--dsw-alias-border-l1` and the composer rebinds `--dsw-alias-border-l2`, both quieter than panels and buttons. The default is declared on `body` alone while the derived tokens below are re-declared on `body, body *`: a custom property computes with `var()` already substituted, so body-only derived tokens would bake in body's color and make every rebind a no-op (the same per-element re-substitution scrollbar.css states for `--dsh-scrollbar-thumb`).
 - `--dsw-elevation-stroke: 0 0 0 0.5px var(--dsw-elevation-stroke-color)` — the stroke alone, used standalone by inline cards that want only an outline (the plugin-inventory card).
 - `--dsw-elevation-panel` / `--dsw-elevation-prominent` — the stroke plus two faint soft layers (3px directional + 16/20px glow at 2–5% black), panel for small floating widgets and cards, prominent for floats, and soft — larger blur at lower alpha — for the composer.
 
-Converted surfaces set `border: 0` and one elevation shadow: every `--dsw-shadow-lv3` float (Menu, Modal, popup selects, model select, usage/context popovers, feedback actions, schedule/job popovers, subagent lineage, settings panel, cordis panel, experimental team panel) takes prominent, and the lv2 surfaces (scroll-to-bottom button, turn-preview card, attachment-rail arrows, question composer, trajectory tooltip) take panel. The composer card takes the soft tier with the l1 stroke rebind, and its workspace-trigger state sets the stroke color `transparent` instead of the former `border-color: transparent`. Dark theme needs no shadow overrides: the soft layers are near-invisible there and the stroke carries the separation, as in Codex.
+Converted surfaces set `border: 0` and one elevation shadow: every `--dsw-shadow-lv3` float (Menu, Modal, popup selects, model select, usage/context popovers, feedback actions, schedule/job popovers, subagent lineage, settings panel, cordis panel, experimental team panel) takes prominent, and the lv2 surfaces (scroll-to-bottom button, turn-preview card, attachment-rail arrows, question composer, trajectory tooltip) take panel. The composer card takes the soft tier with the l2 stroke rebind, and its workspace-trigger state sets the stroke color `transparent` instead of the former `border-color: transparent`. Dark theme needs no shadow overrides: the soft layers are near-invisible there and the stroke carries the separation, as in Codex.
 
 `packages/client/ui-theme/tests/elevation-styles.client.spec.ts` pins the token composition and scans every stylesheet under `packages/`: a rule pairing an lv/elevation `box-shadow` with a `--dsw-alias-border-*` border fails, and every `solid` border on a neutral `--dsw-alias-border-*` token must be `0.5px` wide. Deliberate keeps: Toast and HoverCard (inverted fills where a theme-following stroke is meaningless), ImageLightbox (bare image), and the warn-bordered approval/plan panels, whose state-colored borders stay real borders and pass the scan.
 

+ 2 - 2
.agents/notes/implemented/feature/2026-09-01-web-elevation-stroke-shadows.zh.md

@@ -12,11 +12,11 @@ Web 客户端的高层级表面——菜单、浮层、对话框、面板、悬
 
 `gradient-shadow-text.css`(ui-theme 的阴影归属地)在 `--dsw-shadow-lv*` 阶旁定义 elevation token:
 
-- `--dsw-elevation-stroke-color`——发丝描边颜色,默认 `--dsw-alias-border-l4`(浅色黑 16%、深色白 20%);组件可按表面或状态重绑:所有菜单面(`--dsw-specific-menu` 背景)与输入框重绑最浅的 `--dsw-alias-border-l1`,两者都比面板与按钮安静。默认色只声明在 `body` 上,而下述派生 token 在 `body, body *` 上逐元素重声明:自定义属性的计算值已替换完 `var()`,派生 token 若只在 body 声明会把 body 的颜色固化进去,让所有重绑失效(与 scrollbar.css 对 `--dsh-scrollbar-thumb` 声明的逐元素重替换是同一契约)。
+- `--dsw-elevation-stroke-color`——发丝描边颜色,默认 `--dsw-alias-border-l4`(浅色黑 16%、深色白 20%);组件可按表面或状态重绑:所有菜单面(`--dsw-specific-menu` 背景)重绑最浅的 `--dsw-alias-border-l1`、输入框重绑 `--dsw-alias-border-l2`,两者都比面板与按钮安静。默认色只声明在 `body` 上,而下述派生 token 在 `body, body *` 上逐元素重声明:自定义属性的计算值已替换完 `var()`,派生 token 若只在 body 声明会把 body 的颜色固化进去,让所有重绑失效(与 scrollbar.css 对 `--dsh-scrollbar-thumb` 声明的逐元素重替换是同一契约)。
 - `--dsw-elevation-stroke: 0 0 0 0.5px var(--dsw-elevation-stroke-color)`——单独的描边,供只要轮廓的行内卡片独立使用(插件清单卡片)。
 - `--dsw-elevation-panel` / `--dsw-elevation-prominent`——描边加两层极淡柔光(3px 方向光 + 16/20px 辉光,黑 2–5%),panel 用于小型悬浮部件与卡片,prominent 用于浮层,soft——更大模糊、更低透明度——用于输入框。
 
-被转换的表面设 `border: 0` 加一个 elevation 投影:所有 `--dsw-shadow-lv3` 浮层(Menu、Modal、弹出选择、模型选择、用量/上下文浮层、反馈操作条、日程/任务浮层、子代理谱系、设置面板、cordis 面板、实验性 team 面板)取 prominent;lv2 表面(回到底部按钮、回合预览卡、附件栏箭头、问题 composer、轨迹 tooltip)取 panel。输入框卡片取 soft 档并重绑 l1 描边,其 workspace-trigger 态把描边色设为 `transparent`,替代原先的 `border-color: transparent`。深色主题无需投影覆盖:柔光在深色下几乎不可见,分离由描边承担,与 Codex 相同。
+被转换的表面设 `border: 0` 加一个 elevation 投影:所有 `--dsw-shadow-lv3` 浮层(Menu、Modal、弹出选择、模型选择、用量/上下文浮层、反馈操作条、日程/任务浮层、子代理谱系、设置面板、cordis 面板、实验性 team 面板)取 prominent;lv2 表面(回到底部按钮、回合预览卡、附件栏箭头、问题 composer、轨迹 tooltip)取 panel。输入框卡片取 soft 档并重绑 l2 描边,其 workspace-trigger 态把描边色设为 `transparent`,替代原先的 `border-color: transparent`。深色主题无需投影覆盖:柔光在深色下几乎不可见,分离由描边承担,与 Codex 相同。
 
 `packages/client/ui-theme/tests/elevation-styles.client.spec.ts` 钉住 token 组成并扫描 `packages/` 下全部样式表:lv/elevation `box-shadow` 与 `--dsw-alias-border-*` border 配对的规则即失败;中性 `--dsw-alias-border-*` token 上的每个 `solid` border 必须为 `0.5px` 宽。有意保留:Toast 与 HoverCard(反色填充,跟随主题的描边色在其上无意义)、ImageLightbox(裸图片)、warn 描边的审批/计划面板——状态色 border 保持真 border,扫描放行。
 

+ 1 - 1
packages/client/ui-commands/src/client/PopupSelectView.module.css

@@ -25,7 +25,7 @@
   --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
   --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);
   border: 0;
-  border-radius: 16px;
+  border-radius: 20px;
   background: var(--dsw-specific-menu);
   --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
   box-shadow: var(--dsw-elevation-prominent);

+ 4 - 4
packages/client/ui-conversation/src/client/skeleton/InputBar.module.css

@@ -40,11 +40,11 @@
   width: 100%;
   max-width: var(--dsh-composer-card-max-width);
   padding-top: 10px;
-  /* Input stroke: the lightest neutral (l1), drawn as the elevation hairline
-     so it costs no layout; the shadow is the soft elevation tier. Fill: the
-     input surface token (elevated in dark). */
+  /* Input stroke: the light neutral (l2, one step above the menus' l1),
+     drawn as the elevation hairline so it costs no layout; the shadow is the
+     soft elevation tier. Fill: the input surface token (elevated in dark). */
   border: 0;
-  --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
+  --dsw-elevation-stroke-color: var(--dsw-alias-border-l2);
   border-radius: 22px;
   background: var(--dsw-specific-input-major);
   box-shadow: var(--dsw-elevation-soft);

+ 1 - 1
packages/client/ui-input-trigger/src/client/MenuView.module.css

@@ -18,7 +18,7 @@
   display: flex;
   flex-direction: column;
   border: 0;
-  border-radius: 16px;
+  border-radius: 20px;
   background: var(--dsw-specific-menu);
   --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
   box-shadow: var(--dsw-elevation-prominent);

+ 1 - 1
packages/client/ui-jobs/src/client/JobListAction.module.css

@@ -55,7 +55,7 @@
   overflow: auto;
   list-style: none;
   border: 0;
-  border-radius: 16px;
+  border-radius: 20px;
   background: var(--dsw-specific-menu);
   --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
   --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);

+ 1 - 1
packages/client/ui-model-selection/src/client/ModelSelect.module.css

@@ -83,7 +83,7 @@
   /* Surface tokens match the Menu primitive card (ui-primitives
    * Menu.module.css) so every dropdown reads as the same material. */
   border: 0;
-  border-radius: 16px;
+  border-radius: 20px;
   background: var(--dsw-specific-menu);
   --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
   box-shadow: var(--dsw-elevation-prominent);

+ 1 - 1
packages/client/ui-primitives/src/Menu.module.css

@@ -14,7 +14,7 @@
   flex-direction: column;
   gap: 0;
   border: 0;
-  border-radius: 16px;
+  border-radius: 20px;
   background: var(--dsw-specific-menu);
   --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
   box-shadow: var(--dsw-elevation-prominent);

+ 1 - 1
packages/client/ui-schedule/src/client/ScheduleCatalogAction.module.css

@@ -53,7 +53,7 @@
   overflow: auto;
   list-style: none;
   border: 0;
-  border-radius: 16px;
+  border-radius: 20px;
   background: var(--dsw-specific-menu);
   --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
   --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);

+ 1 - 1
packages/client/ui-subagent/src/client/SubagentHeaderLineage.module.css

@@ -103,7 +103,7 @@
   max-height: min(560px, calc(100vh - 140px));
   padding: 4px;
   overflow: auto;
-  border-radius: 16px;
+  border-radius: 20px;
   background: var(--dsw-specific-menu);
   --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
   --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);

+ 1 - 1
packages/client/ui-theme/src/styles/gradient-shadow-text.css

@@ -10,7 +10,7 @@ body {
   /* Elevation:浮层/面板/面型按钮的描边+投影三件套。0.5px 发丝描边画在
      box-shadow 里(组件配 border: 0,不占布局),叠两层极淡柔光;深色主题下
      柔光几乎不可见,由描边承担分离。描边颜色经 --dsw-elevation-stroke-color
-     间接,组件可重绑(菜单面与输入框重绑最浅的 l1,输入框的
+     间接,组件可重绑(菜单面重绑最浅的 l1、输入框重绑 l2,输入框的
      workspace-trigger 态置 transparent 只保留柔光)。soft 供输入框:更大
      模糊、更低透明度的柔光。默认色只声明在 body 上,让表面的重绑沿继承
      传给真正消费投影的后代。 */