diff --git a/web/src/components/canvas/canvas-cloud-agent.css b/web/src/components/canvas/canvas-cloud-agent.css index 733ece90a..7b45375bc 100644 --- a/web/src/components/canvas/canvas-cloud-agent.css +++ b/web/src/components/canvas/canvas-cloud-agent.css @@ -388,6 +388,19 @@ scroll-padding-block: var(--space-5); } +/* + * 过程内容的公共轴:模型思考的星标与工具调用的左轨压在同一条竖线上(默认 x = 22px)。 + * 轴由星标几何推导,不是拍出来的数:星标中心 = 思考缩进 + 摘要内边距 + 图标半宽; + * 工具左轨用 `axis - 0.5px` 让 1px 的线居中在轴上。改任一项,两处会一起跟着走。 + */ +.agent-conversation-messages { + --agent-axis: 22px; + --agent-thought-icon: 16px; + --agent-summary-inset: 4px; + --agent-gutter-thought: calc(var(--agent-axis) - var(--agent-thought-icon) / 2 - var(--agent-summary-inset)); + --agent-activity-inset: 8px; +} + .agent-conversation-messages > * + * { margin-top: var(--space-4); } @@ -669,10 +682,10 @@ .agent-context-panel-foot { display: grid; } .agent-welcome-actions button { padding-inline: var(--space-2); } - /* 窄面板先把"外层缩进"收掉,保留左轨:层级靠轨与字色继续成立,不靠吃掉正文宽度。 */ - .agent-reasoning, - .agent-operation-feed { - margin-left: 0; + /* 窄面板把公共轴收细,星标与左轨仍压在同一条线上,不吃正文宽度。 */ + .agent-conversation-messages { + --agent-axis: 16px; + --agent-activity-inset: var(--space-1); } } @@ -922,10 +935,11 @@ */ .agent-operation-feed { --agent-tool-accent: color-mix(in srgb, var(--foreground) 62%, transparent); - /* 层级第二档:缩进一层,用一条左轨把"一连串动作"拢成一条活动流。 */ - margin-left: var(--agent-gutter-activity, 10px); + /* 层级第二档:左轨与星标同轴(见 .agent-conversation-messages 的公共轴), + 轨道把"一连串动作"拢成一条活动流,内容落在轨的右侧。 */ + margin-left: calc(var(--agent-axis, 22px) - 0.5px); border-left: 1px solid color-mix(in srgb, var(--foreground) 12%, transparent); - padding-left: var(--agent-activity-inset, 10px); + padding-left: var(--agent-activity-inset, 8px); min-width: 0; } @@ -1308,7 +1322,8 @@ gap: 9px; cursor: pointer; list-style: none; - padding: 6px 4px; + /* 内边距参与公共轴推导:改它,左轨会跟着一起挪(见 .agent-conversation-messages)。 */ + padding: 6px var(--agent-summary-inset, 4px); color: color-mix(in srgb, var(--foreground) 66%, transparent); user-select: none; } @@ -1324,9 +1339,9 @@ /* 只留那颗星:圆底是上一版的装饰,去掉后与时间线标记同一种"无底图标"语言。 */ .agent-reasoning-icon { display: grid; - width: 16px; - height: 16px; - flex: 0 0 16px; + width: var(--agent-thought-icon, 16px); + height: var(--agent-thought-icon, 16px); + flex: 0 0 var(--agent-thought-icon, 16px); place-items: center; border: 0; border-radius: 0; diff --git a/web/test/agent-operation-feed-view.test.tsx b/web/test/agent-operation-feed-view.test.tsx index 433df9536..8f3fa981a 100644 --- a/web/test/agent-operation-feed-view.test.tsx +++ b/web/test/agent-operation-feed-view.test.tsx @@ -84,17 +84,23 @@ test("style contract: 正文 / 工具调用 / 模型思考 三档靠位置与明 expect(icon).toContain("background: transparent"); expect(icon).not.toContain("border-radius: 50%"); - // ② 工具调用缩进一层并挂左轨(把一连串动作拢成一条活动流) + // ② 公共轴:星标与工具左轨压在同一条竖线上,且轴由星标几何推导 + const axis = block(".agent-conversation-messages"); + expect(axis).toContain("--agent-axis: 22px"); + expect(axis).toContain("--agent-gutter-thought: calc(var(--agent-axis) - var(--agent-thought-icon) / 2 - var(--agent-summary-inset))"); + expect(block(".agent-reasoning-summary")).toContain("padding: 6px var(--agent-summary-inset"); + + // ③ 工具调用缩进到轴上并挂左轨(1px 线居中在轴上) const feed = block(".agent-operation-feed"); - expect(feed).toContain("margin-left: var(--agent-gutter-activity"); + expect(feed).toContain("margin-left: calc(var(--agent-axis, 22px) - 0.5px)"); expect(feed).toContain("border-left: 1px solid"); expect(feed).toContain("padding-left: var(--agent-activity-inset"); - // ③ 模型思考与轨同一缩进线,但不带轨(更轻的那一档) + // ④ 模型思考与轨同轴,但不带轨(更轻的那一档) const reasoning = block(".agent-reasoning"); expect(reasoning).toContain("margin-left: var(--agent-gutter-thought"); expect(reasoning).not.toContain("border-left"); - // ④ 窄面板先收外层缩进,别让层级吃掉正文宽度 - expect(css).toContain(".agent-reasoning,\n .agent-operation-feed {\n margin-left: 0;"); + // ⑤ 窄面板只把轴收细,不让两处错位 + expect(css).toContain("--agent-axis: 16px"); });