模型菜单观感抬成组件自带的共享样式面:首页那颗复用同一套卡片与列表
Project CI / AI game creator shell Rust crates (pull_request) Successful in 6m13s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 7m10s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m54s
Project CI / Backend tests (pull_request) Successful in 8m50s
Project CI / Frontend tests (pull_request) Successful in 3m39s
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Successful in 6m13s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 7m10s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m54s
Project CI / Backend tests (pull_request) Successful in 8m50s
Project CI / Frontend tests (pull_request) Successful in 3m39s
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
- 成因:#600 那轮把卡片/列表的新观感挂在 `.game-workbench-chat .project-chat-surface.is-direct-codex .project-chat-composer.is-direct-codex …` 这条宿主祖先链上,同一个 `ConversationModelSelect` 换到首页(`className=home-input-model-select`)就退回基础规则:161px 窄卡、10px 圆角、5px 内边距、32px 行高、旧灰投影 - 改法:卡片/列表/行/hover/选中 pill/细滚动条抬到**组件自带类名**的共享样式面(`.conversation-model-select .conversation-model-menu-shell`、`.conversation-model-select .conversation-model-menu`、`… .conversation-model-menu button…`),不带任何宿主祖先链;合并形态(有外壳)与独立形态(首页/策划/画布)同一套值:16px 圆角 / 12px 内边距 / `--platform-line-soft` 描边 / `--platform-desktop-hover-shadow`,行 34px、圆角 9px、hover `--platform-nav-item-icon-fill`、选中 `--platform-warm-bg` + 600 - 宿主专属的东西留在工作台作用域:输入区锚点(`position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 20`)、与工具栏的几何关系、强度区布局;独立形态的卡片自己就是滚动区(`max-height: 194 = 170 + 上下各 12`),外壳形态列表 `max-height: 170`(5×34,不出现半行),外壳 `max-height: none`(高度由内容决定,避免把列表挤矮) - 首页**不加**强度区:首页那颗没有 effort 的 state/props(`view/home/index.tsx` 只传 `className` 与 `disabled`),就保持这一点 - 基础规则里那几条同属性 `!important` 由共享面按同一档 `!important` 覆盖;工作台那条「抵消宿主通用按钮样式」的规则只留几何(position/display/width/margin/border/shadow/字号),不再抄一份观感 - 测试:`home.suite.ts` 新增「首页模型菜单复用同一套共享样式面」——首页实例的菜单祖先链里没有 `.game-workbench-chat`,只靠 `.conversation-model-select …` 就能解析出 16px 圆角/12px 内边距/34px 行;`chatDialogFrameLayout.test.ts` 的外壳用例按新选择器集合更新(锚点仍来自工作台链、卡片观感来自共享面),并补上 `max-height`/`border-radius`/`background` 断言 - 真机实测(无头 Chromium 同一夹具同一裁剪框):首页那颗 161×309 / 10px / 5px / 32px → 260×194 / 16px / 12px / 34px;工作台那颗外壳 260×262.5、内层列表 234×170、行 34/9px 前后逐值不变(无视觉回退) - 校验:相关 vitest 221 passed / 9 skipped、typecheck、eslint、prettier、encoding 5268 files、spacetime-schema 91 tables、diff-check;对照图见 PR #607 Refs #600, PR #607
This commit is contained in:
@@ -11350,29 +11350,139 @@ button.design-workspace-tree__entry:hover,
|
||||
color: var(--platform-text-soft, #6b7280);
|
||||
font-size: 12px;
|
||||
}
|
||||
/* ============================================================
|
||||
模型菜单的**共享样式面**(任何宿主都拿同一套观感)
|
||||
============================================================
|
||||
选择器只用组件自带类名(`.conversation-model-select` 一族),不带宿主祖先链:工作台输入区、
|
||||
首页输入区等**任何** `ConversationModelSelect` 实例都得到同一套浮层观感(#600 复核后的口径)。
|
||||
宿主专属的东西——工作台输入区的锚点、与工具栏的几何关系、强度区布局——留在各自作用域;
|
||||
这里只放卡片与列表本身,两边不各抄一份。
|
||||
观感:卡片 16px 圆角 / 12px 内边距 / 极淡描边 / 既有暖色投影 token;列表行 34px、行圆角 9px、
|
||||
hover 极淡暖底、选中是轻量 pill;滚动条 6px 且平时透明(悬停控件才显形)。
|
||||
颜色全部取 `--platform-*` token,不引入新色值。 */
|
||||
|
||||
/* 卡片:合并形态(带强度区)用外壳当卡片,独立形态菜单自己就是卡片——两处同一套值。
|
||||
独立形态的锚点沿用上面那条基础规则(`position: absolute; right: 0; bottom: calc(100% + 8px)`),
|
||||
不在这里重复。 */
|
||||
.conversation-model-select .conversation-model-menu-shell,
|
||||
.conversation-model-select .conversation-model-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: max-content;
|
||||
min-width: min(260px, calc(100vw - 24px));
|
||||
max-width: min(320px, calc(100vw - 24px));
|
||||
/* 独立形态:卡片自己就是滚动区,194 = 170 行高 + 上下各 12 内边距,与合并形态同高。 */
|
||||
max-height: min(194px, calc(100vh - 24px));
|
||||
padding: 12px;
|
||||
border: 1px solid var(--platform-line-soft);
|
||||
border-radius: 16px;
|
||||
background: var(--platform-input-fill);
|
||||
box-shadow: var(--platform-desktop-hover-shadow);
|
||||
overflow: auto;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--platform-subpanel-border) transparent;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* 外壳里:强度区与列表之间只留 6px;列表只负责滚动与截断,卡片观感归外壳。
|
||||
里层这几条必须带 `!important`:基础规则里那条 `.conversation-model-menu` 用
|
||||
`background: … !important` 声明了菜单底色(它服务的是"菜单自己就是卡片"的旧形态)。 */
|
||||
.conversation-model-select .conversation-model-menu-shell {
|
||||
gap: 6px;
|
||||
/* 合并形态的高度由内容决定(强度区 + 列表各自的上下界已经定死),
|
||||
不再套用上面那条"卡片自己就是滚动区"的 194px 上限——那会把列表挤矮。 */
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.conversation-model-select
|
||||
.conversation-model-menu-shell
|
||||
.conversation-model-menu {
|
||||
position: static !important;
|
||||
width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
max-width: none !important;
|
||||
/* 170 = 5 行 × 34px:不会停在半行上;再长就滚动(细滚动条,悬停显形)。 */
|
||||
max-height: 170px !important;
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
border-radius: 12px !important;
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* 行:34px 高、9px 圆角、hover 极淡暖底,选中是轻量 pill(不做重色块)。
|
||||
基础规则里同属性的旧值用 `!important` 声明,这里按同一档 `!important` 覆盖。 */
|
||||
.conversation-model-select .conversation-model-menu button {
|
||||
min-height: 34px !important;
|
||||
padding: 0 10px !important;
|
||||
border-radius: 9px !important;
|
||||
}
|
||||
|
||||
.conversation-model-select .conversation-model-menu button:hover:not(:disabled),
|
||||
.conversation-model-select .conversation-model-menu button:focus-visible {
|
||||
background: var(--platform-nav-item-icon-fill) !important;
|
||||
color: var(--platform-text-strong) !important;
|
||||
}
|
||||
|
||||
.conversation-model-select
|
||||
.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` 不截断)。 */
|
||||
.conversation-model-select .conversation-model-menu-option-main {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.conversation-model-select .conversation-model-menu-option-main > span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.conversation-model-select .conversation-model-menu::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.conversation-model-select .conversation-model-menu::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* 静止时不画滚动条,鼠标进控件(或键盘焦点在控件内)才显形。 */
|
||||
.conversation-model-select .conversation-model-menu::-webkit-scrollbar-thumb {
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.conversation-model-select:hover
|
||||
.conversation-model-menu::-webkit-scrollbar-thumb,
|
||||
.conversation-model-select
|
||||
.conversation-model-menu:focus-within::-webkit-scrollbar-thumb {
|
||||
background: var(--platform-subpanel-border);
|
||||
}
|
||||
|
||||
.game-workbench-chat
|
||||
.project-chat-surface.is-direct-codex
|
||||
.project-chat-composer
|
||||
.conversation-model-select
|
||||
.conversation-model-menu
|
||||
button {
|
||||
/* 只保留"抵消宿主通用按钮样式"的几何:工作台输入区的 `button` 有 28px 方块一族规则,
|
||||
尺寸 / 圆角 / 配色交给上面的共享样式面,避免宿主再抄一份观感。 */
|
||||
position: static !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: space-between !important;
|
||||
width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
min-height: 32px !important;
|
||||
height: 32px !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 9px !important;
|
||||
border: 0 !important;
|
||||
border-radius: 6px !important;
|
||||
background: transparent !important;
|
||||
color: var(--platform-text-base, #374151) !important;
|
||||
box-shadow: none !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 500 !important;
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
.game-workbench-chat
|
||||
@@ -11393,8 +11503,6 @@ button.design-workspace-tree__entry:hover,
|
||||
.conversation-model-select
|
||||
.conversation-model-menu
|
||||
button[aria-selected='true'] {
|
||||
background: #f3f1ee !important;
|
||||
color: var(--platform-text-strong, #1f2937) !important;
|
||||
outline: none !important;
|
||||
}
|
||||
.conversation-model-menu-divider {
|
||||
@@ -13487,9 +13595,11 @@ details.design-agent-reasoning[open]
|
||||
队列 chip 与提示段落的 `margin` 都写回前文各自那条规则。 */
|
||||
|
||||
/* ④ 思维强度**并入模型菜单**:底行只留模型触发钮一颗控件,强度区嵌在菜单顶部。
|
||||
菜单外壳(`.conversation-model-menu-shell`)沿用原来模型菜单的锚点与朝向(贴触发钮
|
||||
右缘、向上展开、距输入区 8px),观感按 Codex 参考图重做:大圆角、松内边距、柔和阴影 +
|
||||
极淡描边,颜色全部取 `--platform-*` 暖色 token(不引入新色值)。
|
||||
外壳(`.conversation-model-menu-shell`)沿用原来模型菜单的锚点与朝向(贴触发钮右缘、
|
||||
向上展开、距输入区 8px)——这是**宿主专属的几何**,留在工作台作用域。
|
||||
卡片 / 列表的观感(圆角、内边距、阴影、描边、行高 34px、hover、选中 pill、细滚动条)已抬到
|
||||
文件上方「模型菜单的共享样式面」一节(选择器只用 `.conversation-model-select` 一族),
|
||||
首页等宿主共用同一份,这里不再抄第二遍。
|
||||
强度区里是原生 `<input type="range">`,自带 `role="slider"`、`aria-valuemin/max/now`
|
||||
与 ←/→/Home/End,`aria-valuetext` 报中文档位名,点轨道或拖拽按 `step` 吸附到档位。 */
|
||||
.game-workbench-chat
|
||||
@@ -13500,137 +13610,6 @@ details.design-agent-reasoning[open]
|
||||
right: 0;
|
||||
bottom: calc(100% + 8px);
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
width: max-content;
|
||||
min-width: 260px;
|
||||
max-width: min(320px, calc(100vw - 24px));
|
||||
padding: 12px;
|
||||
border: 1px solid var(--platform-line-soft);
|
||||
border-radius: 16px;
|
||||
background: var(--platform-input-fill);
|
||||
/* 卡片阴影用既有 token(同族暖色),不新造色值。 */
|
||||
box-shadow: var(--platform-desktop-hover-shadow);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* 里层菜单回到文档流:外壳已经有位置 / 描边 / 底色,列表只负责滚动与截断。
|
||||
行高更舒展(34px)、行圆角 9px、滚动条细且平时透明(悬停卡片才显形)。 */
|
||||
.game-workbench-chat
|
||||
.project-chat-surface.is-direct-codex
|
||||
.project-chat-composer.is-direct-codex
|
||||
.conversation-model-menu-shell
|
||||
.conversation-model-menu {
|
||||
position: static;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: none;
|
||||
/* 170 = 5 行 × 34px:不会停在半行上;再长就滚动(细滚动条,悬停显形)。 */
|
||||
max-height: 170px;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
border: 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` 不截断)。 */
|
||||
.game-workbench-chat
|
||||
.project-chat-surface.is-direct-codex
|
||||
.project-chat-composer.is-direct-codex
|
||||
.conversation-model-menu-shell
|
||||
.conversation-model-menu-option-main {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.game-workbench-chat
|
||||
.project-chat-surface.is-direct-codex
|
||||
.project-chat-composer.is-direct-codex
|
||||
.conversation-model-menu-shell
|
||||
.conversation-model-menu-option-main
|
||||
> span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 强度区:菜单顶部,与列表之间只用留白分开(不画横贯分隔线),标题左右层级分明。 */
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
import { HOME_CREATION_AFTER_PROJECT_FAILURE } from '../../src/features/app-shell/homeCreationFailure';
|
||||
import type { ProjectChatComponentProps } from '../../src/features/app-shell/model';
|
||||
import { WorkspaceLauncherShell } from '../../src/features/app-shell/WorkspaceLauncher';
|
||||
import { repoPath } from '../repoPath';
|
||||
import {
|
||||
declaration,
|
||||
parseStyleSheet,
|
||||
resolveDeclarations,
|
||||
} from '../styleCascade';
|
||||
import {
|
||||
act,
|
||||
App,
|
||||
@@ -164,6 +172,78 @@ export function registerClientHomeTests() {
|
||||
expect(createButton).toHaveProperty('disabled', false);
|
||||
});
|
||||
|
||||
it('首页模型菜单复用同一套共享样式面(卡片与列表观感与工作台一致)', async () => {
|
||||
// 样式面抬升前,首页这颗只命中基础规则(10px 圆角 / 5px 内边距 / 32px 行),
|
||||
// 工作台那套(16px 圆角 / 12px 内边距 / 34px 行)挂在 `.game-workbench-chat …` 祖先链上。
|
||||
// 这条用例钉住"任何 ConversationModelSelect 实例都拿到同一份":断言只靠组件自带类名
|
||||
// (`.conversation-model-select …`)就能解析出卡片与列表的观感。
|
||||
const invoke = vi.fn(async (command: string) => {
|
||||
if (command === 'read_game_creator_app_config') {
|
||||
return { config: { selectedModelId: 'quality' } };
|
||||
}
|
||||
if (command === 'load_game_creator_llm_models') {
|
||||
return {
|
||||
defaultModelId: 'quality',
|
||||
models: [
|
||||
{ id: 'quality', displayName: '高质量' },
|
||||
{ id: 'fast', displayName: '快速' },
|
||||
],
|
||||
revision: 1,
|
||||
};
|
||||
}
|
||||
throw new Error(`unexpected invoke ${command}`);
|
||||
});
|
||||
installTauriRuntime({ core: { invoke } });
|
||||
renderLauncherAt('/?launcher');
|
||||
|
||||
const modelTrigger = await screen.findByRole('button', {
|
||||
name: '对话模型',
|
||||
});
|
||||
fireEvent.click(modelTrigger);
|
||||
const menu = await waitFor(() => {
|
||||
const element = document.querySelector<HTMLElement>(
|
||||
'.home-input-model-select .conversation-model-menu',
|
||||
);
|
||||
expect(element).not.toBeNull();
|
||||
return element as HTMLElement;
|
||||
});
|
||||
|
||||
// 组件自带类名在场:共享样式面的选择器就靠它,不需要任何宿主祖先链。
|
||||
expect(menu.classList.contains('conversation-model-menu')).toBe(true);
|
||||
expect(menu.closest('.conversation-model-select')).not.toBeNull();
|
||||
expect(menu.closest('.game-workbench-chat')).toBeNull();
|
||||
|
||||
const rules = parseStyleSheet(
|
||||
readFileSync(
|
||||
repoPath('apps/ai-game-creator-shell/src/styles.css'),
|
||||
'utf8',
|
||||
),
|
||||
);
|
||||
// 共享样式面按 `!important` 声明(要压过基础规则里同属性的旧值),断言只看最终值。
|
||||
const value = (declarations: Map<string, string>, property: string) =>
|
||||
declaration(declarations, property).replace(/ !important$/u, '');
|
||||
const sharedCard = '.conversation-model-select .conversation-model-menu';
|
||||
const card = resolveDeclarations(rules, [sharedCard], 1440);
|
||||
expect(value(card, 'border-radius')).toBe('16px');
|
||||
expect(value(card, 'padding')).toBe('12px');
|
||||
expect(value(card, 'border')).toContain('var(--platform-line-soft)');
|
||||
expect(value(card, 'box-shadow')).toContain(
|
||||
'var(--platform-desktop-hover-shadow)',
|
||||
);
|
||||
|
||||
const row = resolveDeclarations(rules, [`${sharedCard} button`], 1440);
|
||||
expect(value(row, 'min-height')).toBe('34px');
|
||||
expect(value(row, 'padding')).toBe('0 10px');
|
||||
expect(value(row, 'border-radius')).toBe('9px');
|
||||
|
||||
const selected = resolveDeclarations(
|
||||
rules,
|
||||
[`${sharedCard} button[aria-selected='true']`],
|
||||
1440,
|
||||
);
|
||||
expect(value(selected, 'background')).toContain('var(--platform-warm-bg)');
|
||||
});
|
||||
|
||||
it('anchors the empty home input placeholder to the editor while the page scrolls', () => {
|
||||
renderLauncherAt('/?launcher');
|
||||
|
||||
|
||||
@@ -159,6 +159,11 @@ const COMPOSER_TRIGGER_BASE =
|
||||
'.project-chat-surface.is-direct-codex .project-chat-composer .conversation-model-trigger';
|
||||
const INPUT_ACTIONS = `${COMPOSER_INPUT} .resource-reference-input-actions`;
|
||||
const INPUT_ACTIONS_PLAIN = `${COMPOSER} .resource-reference-input-actions`;
|
||||
/** 模型菜单的共享样式面(选择器只用组件自带类名,不带宿主祖先链;首页与工作台共用)。 */
|
||||
const SHARED_CARD = '.conversation-model-select .conversation-model-menu';
|
||||
const SHARED_SHELL =
|
||||
'.conversation-model-select .conversation-model-menu-shell';
|
||||
const SHARED_CARD_IN_SHELL = `${SHARED_SHELL} .conversation-model-menu`;
|
||||
/** 强度滑块与它那排装饰档位点(issue #600 的复核点:点被轨道压住、横向与圆钮错位)。 */
|
||||
const STRENGTH_RANGE = `${COMPOSER} .project-chat-composer-strength-range`;
|
||||
const STRENGTH_THUMB = `${STRENGTH_RANGE}::-webkit-slider-thumb`;
|
||||
@@ -345,11 +350,16 @@ describe('陶泥儿对话区:Codex 三段式(顶栏 / 唯一滚动区 / 文
|
||||
const select = desktopDeclarations(
|
||||
`${COMPOSER_CONTROLS} .conversation-model-select`,
|
||||
);
|
||||
// 外壳:锚点是工作台专属几何;卡片观感来自共享样式面(见下面的 `sharedCard`),
|
||||
// 所以这里把"这个元素会命中的全部选择器"都传进去——只传工作台那条会漏掉搬家后的声明。
|
||||
const shell = desktopDeclarations(
|
||||
`${COMPOSER} .conversation-model-menu-shell`,
|
||||
SHARED_SHELL,
|
||||
);
|
||||
const menuInShell = desktopDeclarations(
|
||||
`${COMPOSER} .conversation-model-menu-shell .conversation-model-menu`,
|
||||
SHARED_CARD,
|
||||
SHARED_CARD_IN_SHELL,
|
||||
);
|
||||
const section = desktopDeclarations(
|
||||
`${COMPOSER} .project-chat-reasoning-effort.is-section`,
|
||||
@@ -357,14 +367,30 @@ describe('陶泥儿对话区:Codex 三段式(顶栏 / 唯一滚动区 / 文
|
||||
const range = desktopDeclarations(
|
||||
`${COMPOSER} .project-chat-composer-strength-range`,
|
||||
);
|
||||
/**
|
||||
* 共享样式面为了压过基础规则里那几条 `!important`,自己也是按 `!important` 声明的;
|
||||
* 断言时只看最终值,去掉后缀。
|
||||
*/
|
||||
const value = (declarations: Map<string, string>, property: string) =>
|
||||
declaration(declarations, property).replace(/ !important$/u, '');
|
||||
|
||||
// 弹层锚在模型控件上、从工具条上方展开(与原来的模型菜单同一朝向,不盖输入框)。
|
||||
expect(declaration(select, 'position')).toContain('relative');
|
||||
expect(declaration(shell, 'position')).toBe('absolute');
|
||||
expect(declaration(shell, 'bottom')).toBe('calc(100% + 8px)');
|
||||
expect(declaration(shell, 'right')).toBe('0');
|
||||
// 卡片观感由共享样式面提供(与首页那颗同一份规则)。
|
||||
expect(pixelValue(shell, 'border-radius')).toBe(16);
|
||||
expect(paddingBox(shell).top).toBe(12);
|
||||
expect(declaration(shell, 'box-shadow')).toContain(
|
||||
'var(--platform-desktop-hover-shadow)',
|
||||
);
|
||||
expect(declaration(shell, 'max-height')).toBe('none');
|
||||
// 里层菜单回到文档流(位置 / 描边 / 底色归外壳),强度区是菜单顶部的一块网格,滑块占满宽度。
|
||||
expect(declaration(menuInShell, 'position')).toBe('static');
|
||||
expect(value(menuInShell, 'position')).toBe('static');
|
||||
expect(value(menuInShell, 'max-height')).toBe('170px');
|
||||
expect(value(menuInShell, 'background')).toBe('transparent');
|
||||
expect(value(menuInShell, 'border-radius')).toBe('12px');
|
||||
expect(declaration(section, 'display')).toBe('grid');
|
||||
expect(declaration(range, 'width')).toBe('100%');
|
||||
// 底行没有第二颗强度控件:那一排的高度仍由模型触发钮(30px)决定,见上面的算式。
|
||||
|
||||
Reference in New Issue
Block a user