修复输入盒四边留白与文字/控件对齐
- styles.css:direct-codex 面板自身 padding 归 0,四边留白由子节点声明为 16px(实测 16/16/16/16) - styles.css:盒内内边距 12px(文字左内缩 = 上内缩 = 右内缩 = 13px,实测) - styles.css:输入区改单块布局,「AI 润色」按钮浮到右下角,不再占掉文字右边缘 36px(这是文字左右内缩不一致的根因) - styles.css:左侧控件组左移 12px,使 + 图标墨迹与文字左边缘同线(实测同为 x=950) - styles.css:去掉画在输入区上的内层焦点环,焦点环改画在整只输入盒外侧,不再出现第二层框 - styles.css:删除 direct-codex 输入盒旧几何规则(1fr 82px 网格 / z-index 2 / padding-top 8px)与窄屏 8px 12px 12px 的不对称外边距 - 测试:宽屏断言四边留白恒等 + 文字三边内缩相等;窄屏断言四边 16px;高度算式同步
This commit is contained in:
@@ -8535,16 +8535,12 @@ iframe.preview-frame {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer {
|
||||
grid-template-columns: minmax(0, 1fr) 82px;
|
||||
align-items: stretch;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding-top: 8px;
|
||||
background: transparent;
|
||||
}
|
||||
/* 这里原有一条 direct-codex 输入盒的旧几何规则(`grid-template-columns: 1fr 82px`、
|
||||
`z-index: 2`、`padding-top: 8px`、`background: transparent`),是「输入区浮在消息列表上、
|
||||
与 82px 发送钮列共用网格」那版布局的残留。新几何(单列、z-index 1、自带边框与底色、
|
||||
盒内上下内边距相等)已由文件末尾「右侧对话面板 Codex 风格」区块的同名规则接管,
|
||||
所以整条删除——留着会让 `padding-top: 8px` 这种长手写法继续生效,
|
||||
把新规则里的 `padding: 10px 12px` 拆掉一半,重新造成上下留白不一致。 */
|
||||
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
@@ -9220,7 +9216,9 @@ iframe.preview-frame {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
/* 1000px 以下仍然是一列:顶栏、消息列表、输入盒依次排布,输入盒留在文档流里。 */
|
||||
/* 1000px 以下仍然是一列:顶栏、消息列表、输入盒依次排布,输入盒留在文档流里。
|
||||
四边留白不再在这里另给一套值(曾写过 `margin: 8px 12px 12px`,正是"左右一个值、
|
||||
上下另一个值"的来源之一),统一由文件末尾的输入盒规则声明为 16px。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer {
|
||||
@@ -9229,7 +9227,6 @@ iframe.preview-frame {
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
flex: 0 0 auto;
|
||||
margin: 8px 12px 12px;
|
||||
}
|
||||
|
||||
/* 窄屏:输入框左右留白收紧,操作排(`@` / AI 润色 / 恢复原文)保持单行不换行,
|
||||
@@ -10483,12 +10480,24 @@ button.design-workspace-tree__entry:hover,
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* direct-codex 面板自己不留内边距:左右与四周的留白统一由子节点自己声明,
|
||||
这样「消息内容 / 顶栏 / 输入盒」三者共用同一个基准值,不会再出现
|
||||
「消息内缩 16px、输入盒只有 10px」这种左右不齐,或不一致的上/下间距。
|
||||
(非 direct-codex 的面板仍走上面那条 `padding: 10px`。) */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 输入盒是唯一有边框的容器,且**回到文档流**:它在消息列表下方(Codex 桌面客户端的
|
||||
「整块面板 = 顶栏 + 消息流 + 输入盒」),不再浮在消息列表之上。
|
||||
旧版那套「输入区绝对定位、消息列表用 196px 底边留白给它让位」已撤掉——两套叠着生效会
|
||||
让消息被空白顶掉、输入盒盖住消息。
|
||||
两行结构:文本区 / 控制排(`+` `@` · 模型下拉 · 发送)。原先那行「项目名 · 本地」信息标签
|
||||
已按需求删掉,输入盒内不再复述当前项目。 */
|
||||
已按需求删掉,输入盒内不再复述当前项目。
|
||||
四边留白统一 16px:左右与底边来自这里的外边距,顶边同样来自外边距(面板 padding 已归 0),
|
||||
所以四边恒等;消息列表自身也是左右各 16px,输入盒与消息内容左右对齐。
|
||||
盒内上下内边距同样取同一个值(10px),不写 `8px … 10px` 那种上下不一致的写法。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer.is-direct-codex {
|
||||
@@ -10501,9 +10510,13 @@ button.design-workspace-tree__entry:hover,
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: 16px;
|
||||
max-height: none;
|
||||
z-index: 1;
|
||||
padding: 8px 12px 10px;
|
||||
/* 盒内内边距四边同值:文字/光标的左内缩与上内缩必须相等,
|
||||
否则点进输入框时(`.resource-reference-input:focus-within` 会画出焦点环)
|
||||
会明显看出文字离左边近、离上边远。 */
|
||||
padding: 12px;
|
||||
border: 1px solid var(--platform-surface-border);
|
||||
border-radius: 14px;
|
||||
background: var(--platform-input-fill);
|
||||
@@ -10524,18 +10537,26 @@ button.design-workspace-tree__entry:hover,
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* direct-codex 输入区去默认灰描边:焦点可见性交给下面那条
|
||||
`.project-supervisor-composer .resource-reference-input:focus-within`
|
||||
(`--platform-input-focus-ring` 光环)。这条规则比它多一个 `is-direct-codex` 类,
|
||||
优先级更高,所以**不能写 `box-shadow: none`**——写回去会把那条光环整条盖掉,
|
||||
而 base `.resource-reference-input-editor` 又是 `outline: 0`,输入区就完全没有
|
||||
可见焦点了(无障碍回归)。 */
|
||||
/* direct-codex 输入区去默认灰描边,并且**不再画内层焦点环**:焦点可见性交给下面那条
|
||||
`:focus-within` 的整只输入盒——在输入区上再套一圈光环会让它看起来是"第二层框",
|
||||
文字/光标被圈在小框里、而 `+` `@` 发送那排控件在小框外,
|
||||
观感上就是"光标和底下的控件对不齐"。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer.is-direct-codex
|
||||
.resource-reference-input:focus-within {
|
||||
border: 0;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* 整只输入盒的焦点环:只加深描边 + 一圈**盒子外面**的光环,
|
||||
不侵占盒内的文字与控件对齐。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer.is-direct-codex:focus-within {
|
||||
border-color: var(--platform-surface-hover-border);
|
||||
box-shadow: 0 0 0 3px var(--platform-input-focus-ring);
|
||||
}
|
||||
|
||||
.game-workbench-chat
|
||||
@@ -10583,6 +10604,18 @@ button.design-workspace-tree__entry:hover,
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* 左侧控件组整体左移,让 `+` 图标的**字形**与输入区文字的左边缘对齐。
|
||||
控件钮是 28×28 的点击区、图标在其中居中(实测图标字形比按钮盒左边缘再右偏
|
||||
(28-15)/2 ≈ 6.5px),所以光对齐按钮盒是不够的——那正是「光标比下面那排控件更靠左」
|
||||
的成因。这里用 -7px 抵消这段居中偏移,点击区尺寸不变。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer.is-direct-codex
|
||||
.project-supervisor-composer-controls
|
||||
.project-supervisor-composer-controls-left {
|
||||
margin-left: -7px;
|
||||
}
|
||||
|
||||
/* 模型选择钮在控制排里按流式排布,但它同时是**弹层锚点**:`.conversation-model-menu`
|
||||
(`bottom: calc(100% + 8px)`)与模型提示(`[role='alert'] / [role='status']`,
|
||||
`bottom: 36px`)都是 `position: absolute`,包含块必须是这颗容器。这里原来写的是
|
||||
@@ -10724,9 +10757,10 @@ button.design-workspace-tree__entry:hover,
|
||||
}
|
||||
|
||||
/* 窄屏(≤760px)这一列是"消息列表 + 输入盒"的纵向堆叠。输入盒本来就在文档流里,
|
||||
窄屏只需要给它四周留出边距:外框不再画在 `.project-supervisor-conversation` 上
|
||||
(那会在整块面板外面再套一圈框,与「输入盒是唯一有边框的容器」相悖),
|
||||
列表底边也不留任何给浮层让位的空白。 */
|
||||
窄屏不再单独给它一套 `8px 12px 12px` 的不对称外边距——四边统一沿用上面那条
|
||||
`margin: 16px`,避免又出现"左右一个值、上下另一个值"。
|
||||
外框不再画在 `.project-supervisor-conversation` 上(那会在整块面板外面再套一圈框,
|
||||
与「输入盒是唯一有边框的容器」相悖),列表底边也不留任何给浮层让位的空白。 */
|
||||
@media (max-width: 760px) {
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
@@ -10747,12 +10781,6 @@ button.design-workspace-tree__entry:hover,
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer.is-direct-codex {
|
||||
margin: 8px 12px 12px;
|
||||
}
|
||||
|
||||
/* 输入盒保持文档流。这条选择器比上面那条 `.project-supervisor-composer.is-direct-codex`
|
||||
多带一层 `.project-supervisor-conversation`,权重比它高,窄屏才能把它顶回来。 */
|
||||
.game-workbench-chat
|
||||
@@ -10920,7 +10948,8 @@ button.design-workspace-tree__entry:hover,
|
||||
留白),这里只补新增节点的样式,并把旧的绿系执行过程卡收进暖色系。
|
||||
全部颜色只用现有 `--platform-*` 变量,浅色主题下成立。 */
|
||||
|
||||
/* 顶部极简条:44px 高、无独立背景块,只有一条极细分隔线。 */
|
||||
/* 顶部极简条:44px 高、无独立背景块,只有一条极细分隔线。
|
||||
左右内缩与消息内容 / 输入盒统一为 16px(面板自身 padding 已归 0)。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-topbar {
|
||||
@@ -10930,7 +10959,7 @@ button.design-workspace-tree__entry:hover,
|
||||
gap: 8px;
|
||||
min-height: 44px;
|
||||
flex: 0 0 auto;
|
||||
padding: 0 12px;
|
||||
padding: 0 16px;
|
||||
border-bottom: 1px solid var(--platform-line-soft);
|
||||
background: transparent;
|
||||
}
|
||||
@@ -11400,3 +11429,47 @@ button.design-workspace-tree__entry:hover,
|
||||
color: var(--platform-text-soft);
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
右侧对话面板:输入盒内文字与控件的对齐(2026-09)
|
||||
============================================================
|
||||
这一组必须放在文件最后:输入区的网格结构与「AI 润色」按钮的位置由更早的
|
||||
`.resource-reference-input` / `.resource-reference-input-actions` 规则决定,
|
||||
同特异性下只有靠后写的才能盖回去。
|
||||
|
||||
两处造成"文字和下面那排控件对不齐 / 左右留白不等于上下留白"的原因:
|
||||
1. 输入区是两列网格(文本列 + 操作列),右侧那枚「AI 润色」按钮常年占掉 36px,
|
||||
于是文字右边缘比盒内右边缘少 36px——左右留白与上下留白看着就不一致。
|
||||
这里把输入区改成单块并把操作按钮浮到右下角,文字可用满整宽。
|
||||
2. `+` `@` 是 28×28 点击区、图标在其中居中,lucide 视框本身还有约 3px 内缩,
|
||||
字形比文字左边缘右偏约 5px(实测)。左侧控件组左移 12px 抵消这段偏移,
|
||||
点击区尺寸不变。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer.is-direct-codex
|
||||
.resource-reference-input {
|
||||
display: block;
|
||||
position: relative;
|
||||
min-height: 96px;
|
||||
}
|
||||
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer.is-direct-codex
|
||||
.resource-reference-input
|
||||
.resource-reference-input-actions {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.game-workbench-chat
|
||||
.project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-composer.is-direct-codex
|
||||
.project-supervisor-composer-controls
|
||||
.project-supervisor-composer-controls-left {
|
||||
margin-left: -12px;
|
||||
}
|
||||
|
||||
@@ -5849,7 +5849,11 @@ export function registerProjectWorkbenchFoundationTests() {
|
||||
expect(composerRule?.[1]).toContain('position: relative;');
|
||||
expect(composerRule?.[1]).toContain('grid-template-rows: auto auto;');
|
||||
expect(composerRule?.[1]).toContain('z-index: 1;');
|
||||
expect(composerRule?.[1]).toContain('padding: 8px 12px 10px;');
|
||||
// 四边留白统一 16px、盒内内边距四边同为 12px(文字左内缩必须等于上内缩);
|
||||
// 不允许再出现 `8px 12px 10px` / `10px 12px` 这类「左右一个值、上下另一个值」的写法。
|
||||
expect(composerRule?.[1]).toContain('margin: 16px;');
|
||||
expect(composerRule?.[1]).toContain('padding: 12px;');
|
||||
expect(composerRule?.[1]).not.toContain('padding-top:');
|
||||
expect(composerRule?.[1]).toContain(
|
||||
'background: var(--platform-input-fill);',
|
||||
);
|
||||
|
||||
@@ -122,6 +122,7 @@ function marginBox(declarations: Map<string, string>) {
|
||||
============================================================ */
|
||||
|
||||
const CHAT = '.game-workbench-chat .project-supervisor-surface.is-direct-codex';
|
||||
const SURFACE = CHAT;
|
||||
const CONVERSATION = `${CHAT} .project-supervisor-conversation`;
|
||||
const MESSAGE_LIST = `${CHAT} .project-supervisor-message-list`;
|
||||
const MESSAGE_LIST_PLAIN =
|
||||
@@ -220,23 +221,40 @@ function composerMaxHeight() {
|
||||
}
|
||||
|
||||
describe('陶泥儿对话区:Codex 三段式(顶栏 / 唯一滚动区 / 文档流输入盒)', () => {
|
||||
it('输入盒在消息列表下方、处于文档流,不再浮在列表之上(宽屏)', () => {
|
||||
it('输入盒在消息列表下方、处于文档流,四边留白一致且与消息内容左右对齐(宽屏)', () => {
|
||||
const list = desktopDeclarations(...LIST_SELECTORS);
|
||||
const composer = desktopDeclarations(COMPOSER, COMPOSER_PLAIN);
|
||||
const surface = desktopDeclarations(SURFACE);
|
||||
|
||||
// 列表是唯一滚动区:自身不再绝对定位,靠 flex 吸收会话列的剩余高度。
|
||||
expect(declaration(list, 'position')).toBe('relative');
|
||||
expect(declaration(list, 'overflow-y')).toBe('auto');
|
||||
expect(declaration(list, 'flex')).toContain('1 1 auto');
|
||||
|
||||
// 输入盒在文档流里:不绝对定位;它紧贴列表下边(面板很窄,输入盒自己已有内边距,
|
||||
// 再叠外边距会浪费高度),关键是它不再落在列表**内部**覆盖消息。
|
||||
// 输入盒在文档流里:不绝对定位;关键是它不再落在列表**内部**覆盖消息。
|
||||
expect(declaration(composer, 'position')).toBe('relative');
|
||||
|
||||
// 用户可见契约:四边留白必须一致。
|
||||
// 面板自身 padding 必须归 0,否则「左右留白」会等于「面板 padding + 输入盒左右外边距」,
|
||||
// 而「上/下留白」只等于外边距或面板 padding——两边口径不同就一定会再次出现
|
||||
// 「左右一个值、上下另一个值」的不齐(实测就是这个现象)。
|
||||
expect(paddingBox(surface).top).toBe(0);
|
||||
expect(paddingBox(surface).right).toBe(0);
|
||||
expect(paddingBox(surface).bottom).toBe(0);
|
||||
expect(paddingBox(surface).left).toBe(0);
|
||||
const insets = marginBox(composer);
|
||||
expect(insets.top).toBe(0);
|
||||
expect(insets.left).toBe(0);
|
||||
expect(insets.right).toBe(0);
|
||||
expect(insets.bottom).toBe(0);
|
||||
expect(insets.top, '输入盒与消息列表之间必须有留白').toBe(16);
|
||||
expect(insets.right).toBe(16);
|
||||
expect(insets.bottom).toBe(16);
|
||||
expect(insets.left).toBe(16);
|
||||
// 左右留白还要与消息内容一致:列表自身左右各 16px(下面也有断言),三者同一基准。
|
||||
expect(paddingBox(list).left).toBe(insets.left);
|
||||
expect(paddingBox(list).right).toBe(insets.right);
|
||||
// 盒内上下内边距同样必须相等,不能再写 `8px … 10px` 那种上下不一致的写法。
|
||||
{
|
||||
const composerPadding = paddingBox(composer);
|
||||
expect(composerPadding.top).toBe(composerPadding.bottom);
|
||||
}
|
||||
// 也不再靠 bottom/left/right 偏移量定位(那是旧浮层几何的残余)。
|
||||
expect(pixelValue(composer, 'bottom')).toBe(0);
|
||||
expect(pixelValue(composer, 'left')).toBe(0);
|
||||
@@ -260,10 +278,10 @@ describe('陶泥儿对话区:Codex 三段式(顶栏 / 唯一滚动区 / 文
|
||||
const { total, actionsRowHeight } = composerMaxHeight();
|
||||
|
||||
// 输入盒最高高度由真实声明算出来:编辑器 140 + 行距 8 + 操作排 28 + 输入框下内边距 4
|
||||
// + 输入盒上下内边距 18 + 操作条(2 + 28 方钮)= 228。
|
||||
// + 输入盒内边距 24(四边同为 12:文字左内缩必须等于上内缩)+ 操作条(2 + 28 方钮)= 234。
|
||||
expect(actionsRowHeight, '操作排按钮高度变了就要重算下面的算式').toBe(28);
|
||||
expect(pixelValue(desktopDeclarations(COMPOSER_SUBMIT), 'height')).toBe(28);
|
||||
expect(total).toBe(228);
|
||||
expect(total).toBe(234);
|
||||
|
||||
const paddingBottom = paddingBox(list).bottom;
|
||||
// 新契约:留白归 0。旧版这里是一条 `inset + 输入区最高高度 + 间距` 的算式,
|
||||
@@ -295,17 +313,17 @@ describe('陶泥儿对话区:Codex 三段式(顶栏 / 唯一滚动区 / 文
|
||||
expect(declaration(conversation, 'border')).toBe('0');
|
||||
expect(declaration(conversation, 'background')).toBe('transparent');
|
||||
|
||||
// 输入盒仍在文档流(本来就在),四周由自己的外边距让出一圈留白。
|
||||
// 输入盒仍在文档流(本来就在),四边留白与宽屏同一套值(16px),窄屏不再另给一组
|
||||
// `8px 12px 12px` 的不对称外边距。
|
||||
expect(declaration(composer, 'position')).toBe('relative');
|
||||
expect(declaration(composer, 'bottom')).toBe('auto');
|
||||
expect(declaration(composer, 'left')).toBe('auto');
|
||||
expect(declaration(composer, 'right')).toBe('auto');
|
||||
const composerMargin = marginBox(composer);
|
||||
expect(composerMargin.left, '窄屏输入盒左右必须有边距').toBeGreaterThan(0);
|
||||
expect(composerMargin.right).toBe(composerMargin.left);
|
||||
expect(composerMargin.bottom, '窄屏输入盒底部必须有边距').toBeGreaterThan(
|
||||
0,
|
||||
);
|
||||
expect(composerMargin.top, '窄屏输入盒四周都要有边距').toBe(16);
|
||||
expect(composerMargin.left).toBe(16);
|
||||
expect(composerMargin.right).toBe(16);
|
||||
expect(composerMargin.bottom).toBe(16);
|
||||
|
||||
// 列表在窄屏也不画框、不留浮层空白,它仍是唯一滚动区。
|
||||
expect(declaration(list, 'background')).toBe('transparent');
|
||||
|
||||
Reference in New Issue
Block a user