From 3383c13bba9014144fdc5340df9f2d1d5b70c215 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Mon, 5 Oct 2026 00:34:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E8=8F=9C=E5=8D=95=E8=A7=86?= =?UTF-8?q?=E8=A7=89=E9=87=8D=E5=81=9A=EF=BC=9A=E7=85=A7=20Codex=20?= =?UTF-8?q?=E8=A7=82=E6=84=9F=20+=20=E6=88=91=E4=BB=AC=E7=9A=84=E6=9A=96?= =?UTF-8?q?=E8=89=B2=20token=EF=BC=88=E5=A4=8D=E6=A0=B8=E5=8F=8D=E9=A6=88?= =?UTF-8?q?=202=20=E4=B9=8B=E4=BA=8C=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 卡片:圆角 12 → 16px、内边距 12px、描边换成极淡 `--platform-line-soft`、投影改暖色 `rgb(112 57 30 / …)`(不用纯黑);去掉横贯分隔线,强度区与列表之间只用留白分开 - 强度区:标题 `--platform-text-strong` 12/600、右侧「当前:X」`--platform-text-soft` 11px;单列铺满(`minmax(0,1fr)`,否则 `auto` 轨道只按 max-content 定尺、滑块被压回 129px);滑块与档位点包一层相对定位容器,点改绝对定位叠在轨道中线 - 滑块:轨道 6px 圆头,已选段 `--platform-accent`、未选段 `--platform-subpanel-border`(进度由组件写进来的 `--strength-progress` 驱动双色渐变,不写死颜色);圆钮 18 → 20px(`--platform-input-highlight` 底 + `--platform-accent` 2px 描边 + 柔影),hover/active/focus-visible 与 Firefox 伪元素同步 - 档位点:5px 淡点 → 7px 且落在轨道中线上(带输入区底色的 1.5px 描边提对比),`pointer-events: none` 不挡命中 - 模型列表:行高 34px、行圆角 9px、hover `--platform-nav-item-icon-fill`、选中 `--platform-warm-bg` 轻量 pill(覆盖前文那几条 `!important` 同属性规则);`max-height: 170px`(=5×34,不出现半行);滚动条 6px、平时透明,悬停卡片才显形 - 校验:typecheck、4 个 vitest 文件 212 passed / 9 skipped、eslint、prettier、encoding、spacetime-schema、diff-check 全通过;无头 Chromium 夹具(447px / 900px)截图为证(见 PR 正文) --- apps/ai-game-creator-shell/src/styles.css | 201 ++++++++++++++---- .../ComposerControls.tsx | 70 +++--- docs/project-memory/shared-memory/pitfalls.md | 3 + 3 files changed, 203 insertions(+), 71 deletions(-) diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index fdbfe9e32..31fc74cd2 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -13471,11 +13471,11 @@ details.design-agent-reasoning[open] 队列 chip 与提示段落的 `margin` 都写回前文各自那条规则。 */ /* ④ 思维强度**并入模型菜单**:底行只留模型触发钮一颗控件,强度区嵌在菜单顶部。 - 菜单外壳(`.conversation-model-menu-shell`)沿用原来模型菜单的定位 / 描边 / 底色 / - 阴影(向上展开、贴触发钮右缘),强度和模型列表共用同一张卡;强度区里是原生 - ``,自带 `role="slider"`、`aria-valuemin/max/now` 与 - ←/→/Home/End,`aria-valuetext` 报中文档位名,点轨道或拖拽按 `step` 吸附到档位。 - 颜色全部走 `--platform-*`(不引入新色值)。 */ + 菜单外壳(`.conversation-model-menu-shell`)沿用原来模型菜单的锚点与朝向(贴触发钮 + 右缘、向上展开、距输入区 8px),观感按 Codex 参考图重做:大圆角、松内边距、柔和阴影 + + 极淡描边,颜色全部取 `--platform-*` 暖色 token(不引入新色值)。 + 强度区里是原生 ``,自带 `role="slider"`、`aria-valuemin/max/now` + 与 ←/→/Home/End,`aria-valuetext` 报中文档位名,点轨道或拖拽按 `step` 吸附到档位。 */ .game-workbench-chat .project-chat-surface.is-direct-codex .project-chat-composer.is-direct-codex @@ -13484,20 +13484,24 @@ details.design-agent-reasoning[open] right: 0; bottom: calc(100% + 8px); z-index: 20; - display: grid; + display: flex; + flex-direction: column; + gap: 6px; width: max-content; - min-width: 216px; + min-width: 260px; max-width: min(320px, calc(100vw - 24px)); - border: 1px solid var(--platform-surface-border); - border-radius: 12px; + padding: 12px; + border: 1px solid var(--platform-line-soft); + border-radius: 16px; background: var(--platform-input-fill); box-shadow: - 0 14px 30px rgb(31 41 55 / 13%), - 0 2px 6px rgb(31 41 55 / 5%); + 0 18px 40px rgb(112 57 30 / 14%), + 0 2px 8px rgb(112 57 30 / 6%); pointer-events: auto; } -/* 里层菜单回到文档流:外壳已经有位置 / 描边 / 底色,列表只负责滚动与截断。 */ +/* 里层菜单回到文档流:外壳已经有位置 / 描边 / 底色,列表只负责滚动与截断。 + 行高更舒展(34px)、行圆角 9px、滚动条细且平时透明(悬停卡片才显形)。 */ .game-workbench-chat .project-chat-surface.is-direct-codex .project-chat-composer.is-direct-codex @@ -13507,12 +13511,90 @@ details.design-agent-reasoning[open] width: 100%; min-width: 0; max-width: none; - max-height: 260px; + /* 170 = 5 行 × 34px:不会停在半行上;再长就滚动(细滚动条,悬停显形)。 */ + max-height: 170px; overflow: auto; + padding: 0; border: 0; - border-radius: 0; + border-radius: 12px; background: transparent; box-shadow: none; + scrollbar-width: thin; + scrollbar-color: var(--platform-subpanel-border) transparent; +} + +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .conversation-model-menu-shell + .conversation-model-menu::-webkit-scrollbar { + width: 6px; +} + +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .conversation-model-menu-shell + .conversation-model-menu::-webkit-scrollbar-track { + background: transparent; +} + +/* 静止时不画滚动条,鼠标进卡片才显形("细 + 自动隐藏")。 */ +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .conversation-model-menu-shell + .conversation-model-menu::-webkit-scrollbar-thumb { + border-radius: 999px; + background: transparent; +} + +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .conversation-model-menu-shell:hover + .conversation-model-menu::-webkit-scrollbar-thumb { + background: var(--platform-subpanel-border); +} + +/* 行:34px 高、9px 圆角、hover 极淡暖底,选中是轻量 pill(不做重色块)。 + 前文那几条 `!important` 的同属性规则在这里按同一档 `!important` + 更高特异性盖回。 */ +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .conversation-model-menu-shell + .conversation-model-menu + button { + min-height: 34px !important; + padding: 0 10px !important; + border-radius: 9px !important; +} + +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .conversation-model-menu-shell + .conversation-model-menu + button:hover:not(:disabled), +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .conversation-model-menu-shell + .conversation-model-menu + button:focus-visible { + background: var(--platform-nav-item-icon-fill) !important; + color: var(--platform-text-strong) !important; +} + +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .conversation-model-menu-shell + .conversation-model-menu + button[aria-selected='true'] { + background: var(--platform-warm-bg) !important; + color: var(--platform-text-strong) !important; + font-weight: 600 !important; } /* 列表宽度由外壳限定,超长模型名走省略号(原来靠 `width: max-content` 不截断)。 */ @@ -13536,16 +13618,30 @@ details.design-agent-reasoning[open] white-space: nowrap; } -/* 强度区:菜单顶部、与模型列表用一条分隔线分开(分隔线是最后一个子属性的 - `border-bottom`,列表首项自带 padding,不会显得挤)。 */ +/* 强度区:菜单顶部,与列表之间只用留白分开(不画横贯分隔线),标题左右层级分明。 */ .game-workbench-chat .project-chat-surface.is-direct-codex .project-chat-composer.is-direct-codex .project-chat-reasoning-effort.is-section { display: grid; - gap: 6px; - padding: 9px 9px 7px; - border-bottom: 1px solid var(--platform-line-soft); + /* 单列铺满:`auto` 轨道在这里只按 max-content 定尺,滑块会被压回固有宽度。 */ + grid-template-columns: minmax(0, 1fr); + justify-items: stretch; + width: 100%; + align-self: stretch; + gap: 10px; + padding: 4px 6px 2px; +} + +/* 滑块与档位点是一个整体:点绝对定位叠在轨道中线上(不受字号 / 行高变化影响)。 */ +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .project-chat-composer-strength-slider { + position: relative; + display: grid; + grid-template-columns: minmax(0, 1fr); + width: 100%; } .game-workbench-chat @@ -13553,7 +13649,7 @@ details.design-agent-reasoning[open] .project-chat-composer.is-direct-codex .project-chat-composer-strength-head { display: flex; - align-items: center; + align-items: baseline; justify-content: space-between; gap: 8px; min-width: 0; @@ -13563,9 +13659,9 @@ details.design-agent-reasoning[open] .project-chat-surface.is-direct-codex .project-chat-composer.is-direct-codex .project-chat-composer-strength-title { - color: var(--platform-text-base); + color: var(--platform-text-strong); font-size: 12px; - font-weight: 700; + font-weight: 600; } .game-workbench-chat @@ -13573,7 +13669,7 @@ details.design-agent-reasoning[open] .project-chat-composer.is-direct-codex .project-chat-composer-strength-range { width: 100%; - height: 24px; + height: 26px; margin: 0; appearance: none; border: 0; @@ -13587,21 +13683,26 @@ details.design-agent-reasoning[open] .project-chat-composer-strength-range::-webkit-slider-runnable-track { height: 6px; border-radius: 999px; - background: var(--platform-button-ghost-fill); + /* 已选段用主色、未选段用暖灰:进度由组件写进来的 `--strength-progress` 决定。 */ + background: linear-gradient( + to right, + var(--platform-accent) 0 var(--strength-progress, 0%), + var(--platform-subpanel-border) var(--strength-progress, 0%) 100% + ); } .game-workbench-chat .project-chat-surface.is-direct-codex .project-chat-composer.is-direct-codex .project-chat-composer-strength-range::-webkit-slider-thumb { - width: 18px; - height: 18px; - margin-top: -6px; + width: 20px; + height: 20px; + margin-top: -7px; appearance: none; - border: 2px solid var(--platform-button-primary-fill); + border: 2px solid var(--platform-accent); border-radius: 999px; - background: var(--platform-input-fill); - box-shadow: 0 1px 2px rgb(0 0 0 / 18%); + background: var(--platform-input-highlight); + box-shadow: 0 2px 6px rgb(112 57 30 / 22%); } .game-workbench-chat @@ -13651,19 +13752,28 @@ details.design-agent-reasoning[open] .project-chat-composer-strength-range::-moz-range-track { height: 6px; border-radius: 999px; - background: var(--platform-button-ghost-fill); + background: var(--platform-subpanel-border); +} + +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-composer.is-direct-codex + .project-chat-composer-strength-range::-moz-range-progress { + height: 6px; + border-radius: 999px; + background: var(--platform-accent); } .game-workbench-chat .project-chat-surface.is-direct-codex .project-chat-composer.is-direct-codex .project-chat-composer-strength-range::-moz-range-thumb { - width: 18px; - height: 18px; - border: 2px solid var(--platform-button-primary-fill); + width: 20px; + height: 20px; + border: 2px solid var(--platform-accent); border-radius: 999px; - background: var(--platform-input-fill); - box-shadow: 0 1px 2px rgb(0 0 0 / 18%); + background: var(--platform-input-highlight); + box-shadow: 0 2px 6px rgb(112 57 30 / 22%); } /* 档位点:纯装饰(命中与吸附由原生 range 负责),个数跟着档位契约走, @@ -13672,11 +13782,17 @@ details.design-agent-reasoning[open] .project-chat-surface.is-direct-codex .project-chat-composer.is-direct-codex .project-chat-composer-strength-stops { + position: absolute; + top: 50%; + right: 0; + left: 0; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; + align-items: center; justify-items: center; - margin-top: -12px; + height: 6px; + transform: translateY(-50%); pointer-events: none; } @@ -13685,10 +13801,11 @@ details.design-agent-reasoning[open] .project-chat-composer.is-direct-codex .project-chat-composer-strength-stops span { - width: 5px; - height: 5px; + width: 7px; + height: 7px; + border: 1.5px solid var(--platform-input-highlight); border-radius: 999px; - background: var(--platform-surface-border); + background: var(--platform-text-muted); } .game-workbench-chat @@ -13696,7 +13813,7 @@ details.design-agent-reasoning[open] .project-chat-composer.is-direct-codex .project-chat-composer-strength-stops span.is-active { - background: var(--platform-button-primary-fill); + background: var(--platform-accent); } .game-workbench-chat @@ -13704,6 +13821,6 @@ details.design-agent-reasoning[open] .project-chat-composer.is-direct-codex .project-chat-composer-strength-value { color: var(--platform-text-soft); - font-size: 12px; + font-size: 11px; text-align: right; } diff --git a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/ComposerControls.tsx b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/ComposerControls.tsx index ef71def98..31dcecd5a 100644 --- a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/ComposerControls.tsx +++ b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/ComposerControls.tsx @@ -17,7 +17,7 @@ import { Square, X, } from 'lucide-react'; -import type { RefObject } from 'react'; +import type { CSSProperties, RefObject } from 'react'; import { useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; @@ -476,35 +476,47 @@ export function ComposerReasoningEffortSelect({ {`当前:${activeLabel}`} - {/* 原生 range 的 role/值域本来就成立,这里再显式写一遍:`aria-valuetext` 是 - 中文档位名,读屏念的是「最高」而不是「4」。 */} - { - const next = options[Number(event.currentTarget.value)]; - if (next && next.value !== effort) { - selectEffort(next.value); + + {/* 原生 range 的 role/值域本来就成立,这里再显式写一遍:`aria-valuetext` 是 + 中文档位名,读屏念的是「最高」而不是「4」。 */} + -