diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index 941dd5e10..eb03ad61e 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -12558,8 +12558,9 @@ button.design-workspace-tree__entry:hover, grid-column: 1; align-self: center; min-width: 0; + /* 状态行自带 6px 上间距(输入盒的 `gap` row 分量为 0:没内容时不留幻影行距, + 有内容时由这里给间距)。不要把 `margin-top: 0` 写回来——它会盖掉这一条。 */ margin-top: 6px; - margin-top: 0; } /* direct-codex 的 `@` 触发钮是下面控制排里的 `.project-chat-reference-trigger`, @@ -13240,7 +13241,8 @@ button.design-workspace-tree__entry:hover, grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto; align-content: start; - /* 行间距归 0:状态层没有内容时第二行高度为 0,不留幻影行距(间距给状态元素自己)。 */ + /* 行间距归 0:状态层没有内容时第二行高度为 0,不留幻影行距;有内容时由状态元素 + 自带的 6px 上间距提供间隔(见 `.resource-reference-input-status` 那两条规则)。 */ gap: 0 8px; } @@ -13266,8 +13268,8 @@ button.design-workspace-tree__entry:hover, grid-column: 1; align-self: center; min-width: 0; + /* 状态行自带 6px 上间距(输入盒的 `gap` row 分量为 0)。 */ margin-top: 6px; - margin-top: 0; overflow-wrap: anywhere; } diff --git a/apps/ai-game-creator-shell/tests/chatDialogFrameLayout.test.ts b/apps/ai-game-creator-shell/tests/chatDialogFrameLayout.test.ts index 60c771f17..fa761e8e6 100644 --- a/apps/ai-game-creator-shell/tests/chatDialogFrameLayout.test.ts +++ b/apps/ai-game-creator-shell/tests/chatDialogFrameLayout.test.ts @@ -20,6 +20,10 @@ const CHAT_CONVERSATION_PATH = repoPath( const CHAT_COMPOSER_PATH = repoPath( 'apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/DirectProjectComposer.tsx', ); +/** 共享输入区实现(「AI 润色 / 恢复原文」与状态行都在这里渲染)。 */ +const INPUT_SOURCE_PATH = repoPath( + 'apps/ai-game-creator-shell/src/features/project-workspace/ResourceReferenceInput.tsx', +); /** 同目录的控件实现(推理强度滑块在这里渲染)。 */ const CHAT_COMPOSER_CONTROLS_PATH = repoPath( 'apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/ComposerControls.tsx', @@ -255,7 +259,19 @@ function composerMaxHeight() { pixelValue(editor, 'min-height'), '编辑器最小高度是输入盒高度的下界,改了要同步改这里的算式', ).toBe(72); - // 输入盒第二行的润色状态行没内容时为 0 高(`gap` 的 row 分量已归 0,状态自己带 6px 上间距)。 + // 输入盒第二行是**条件渲染**的润色状态行:`ResourceReferenceInput` 只在 + // `polishing || polishError || polishNotice` 时才渲染它,空态这一行高度为 0(`gap` 的 + // row 分量已归 0,有内容时由状态元素自带的 6px 上间距提供间隔)。这里断言那条条件 + // 还在(谁把它改成常驻渲染,这条就红),所以 `statusRowHeight = 0` 是真实依据而不是写死。 + const inputSource = readFileSync(INPUT_SOURCE_PATH, 'utf8'); + expect( + inputSource, + '润色状态行必须是条件渲染(空态不occupy第二行)', + ).toContain('polishing || polishError || polishNotice'); + const statusRule = desktopDeclarations( + `${COMPOSER_INPUT} .resource-reference-input-status`, + ); + expect(pixelValue(statusRule, 'margin-top')).toBe(6); const statusRowHeight = 0; return {