diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index 8c3b2535d..05f24f2c9 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -11892,7 +11892,10 @@ button.design-workspace-tree__entry:hover, left: 0; margin: 16px; max-height: none; - z-index: 1; + /* 抬到列表里「回到底部」胶囊(z-index: 10)之上:输入盒自己是层叠上下文,模型 / 附件 + 菜单的 z-index 只在盒内有效,盒子不抬高就会被胶囊盖住。30 仍低于拖拽落点(60)与 + 设置弹窗(240)这两个整屏浮层,它们照旧盖在输入盒之上。 */ + z-index: 30; /* 盒内内边距四边同值:文字/光标的左内缩与上内缩必须相等, 否则点进输入框时(`.resource-reference-input:focus-within` 会画出焦点环) 会明显看出文字离左边近、离上边远。 */ @@ -13401,10 +13404,11 @@ button.design-workspace-tree__entry:hover, grid-row: 1 / span 2; } -/* 消息之间的间距:消息列表是块级滚动容器(不是 flex/grid),基础规则里的 `gap: 14px` - 对它无效,而被改写成 `margin-top: 0` 的 `.message + .message` 又让相邻消息贴在一起。 - 这里给列表的相邻子元素统一加间距(消息、工具调用折叠块、思考过程块都适用), - 间距值与消息内部的行距观感一致。 */ +/* 消息之间的间距:消息列表是块级滚动流,基础规则里的 `gap: 14px` 对它无效,而被改写成 + `margin-top: 0` 的 `.message + .message` 又让相邻消息贴在一起。这里给列表的相邻子元素统一 + 加间距(消息、工具调用折叠块、思考过程块都适用),间距值与消息内部的行距观感一致。 + (列表下面被改成 flex 列容器,只是为了给「回到底部」胶囊一个 `margin-top: auto` 的落点; + flex 里 margin 不折叠,这条间距规则仍照常生效。) */ .game-workbench-chat .project-chat-surface.is-direct-codex .project-chat-message-list @@ -13413,6 +13417,37 @@ button.design-workspace-tree__entry:hover, margin-top: 14px; } +/* 「回到底部」胶囊的位置真源:把消息列表做成 **flex 列容器**,胶囊是最后一个 flex 项。 + - 内容不足一屏:`margin-top: auto` 吃掉剩余空间,把胶囊顶到列表可见底边; + - 内容溢出一屏:auto 归零,胶囊落回内容末尾,再由自身的 `sticky bottom-3` 上拉贴底。 + 只有 sticky 是不够的:sticky 只能把元素**上拉**,不能下推——内容不足一屏时胶囊会停在 + 文档流里(表现为悬空,见 `docs/adr/【ADR】DirectProject对话滚动与历史自动加载-2026-10-02.md`)。 + `gap: 0` 必须显式写:上面 `.… .project-chat-message-list { gap: 14px }` 是给 flex 预备的, + 改成 flex 后它会生效,与下面那些 `> * + *` 的 margin 叠成双倍间距。 + `> * { flex: 0 0 auto }` 保证内容溢出一屏时子项不被纵向压缩,列表仍是唯一滚动区; + 子项间距仍由上面那条 `> * + *` 给(flex 里 margin 不折叠,差值与块级最多 2px)。 */ +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-message-list { + display: flex; + flex-direction: column; + gap: 0; +} + +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-message-list + > * { + flex: 0 0 auto; +} + +.game-workbench-chat + .project-chat-surface.is-direct-codex + .project-chat-message-list + > .project-chat-scroll-to-bottom { + margin-top: auto; +} + /* 发送时间与完成后的过程区沿用对话面板的次要信息样式。 */ .message-sent-at { display: block; diff --git a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectScrollToBottomCapsule.tsx b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectScrollToBottomCapsule.tsx index cbf78edf9..6814a56df 100644 --- a/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectScrollToBottomCapsule.tsx +++ b/apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectScrollToBottomCapsule.tsx @@ -3,9 +3,17 @@ import { ArrowDown } from 'lucide-react'; /** * 底部居中的「回到底部」胶囊。 * - * 用 `sticky bottom-*` 而不是浮层:工作台里 `.project-chat-conversation` 是 `display: block` - * 加 `height: 100%` 的几何,在列表外套一层定位容器会把列表的 `height: 100%` 塌成内容高度; - * 粘在列表内部的胶囊零结构改动,两块宿主(工作台侧栏与独立页面)都能拿到。 + * 它是消息列表的**最后一个 flex 项**,贴底靠两件事配合(见 `styles.css` 里 + * `.project-chat-scroll-to-bottom` 那组规则): + * - `margin-top: auto`:内容不足一屏时吃掉剩余空间,把胶囊顶到列表可见底边; + * - `sticky bottom-3`:内容溢出一屏时把胶囊从内容末尾**上拉**贴住可见底边。 + * 只用 `sticky` 不够——它只能上拉、不能下推,内容不足一屏时元素会停在文档流里(悬空)。 + * + * 用列表内的 flex 项而不是浮层:工作台里 `.project-chat-surface.is-direct-codex > + * .project-chat-conversation` 是纵向 flex,`.project-chat-message-list` 是其中 + * `flex: 1 1 auto` 的唯一滚动项;在列表外套一层定位容器会让列表塌成内容高度, + * 改公共类又会连带 `PlanningChatView`。粘在列表内部零结构改动,两块宿主 + * (工作台侧栏与导出面板)都能拿到。 * * 显隐与文案由调用方决定(距底超过阈值才出现;不跟随时来了新回复就换文案),这里只负责表现。 */ @@ -19,7 +27,7 @@ export function DirectProjectScrollToBottomCapsule({ return (