删掉强度滑块的档位圆点;pointercancel 与「松手」同口径提交预览
- 用户口径:「你干脆把圆点删了吧,很丑…要做就做成几乎透明的」→ 按第一选择**删除**(不做半透明备选)
- 标记:`.project-chat-composer-strength-slider` 里那组 `<span class="project-chat-composer-strength-stops">` + 5 个点整体删除
- CSS:`space-between` 排布、`z-index: 2` 抬层、`.is-active{opacity:0}`、点的 `color-mix` 底色、以及只服务点对齐的 `padding: 0 7px` 一并删除;强度区横向内边距 `4px 6px 2px` → `4px 0 2px`(滑块直接铺满卡片内容宽度,填充段与圆钮两端与轨道贴齐,不再留多余空白);滑块容器去掉已无用的 `position: relative`
- 保留:圆钮(实心暖白 + 柔影 + 2px 间隙焦点环)、filled 段铺满轨道高度 6px、`--strength-ratio`、`当前:X`、`aria-valuetext`、←/→/Home/End、点轨道跳档、拖动连续跟手(预览 / 松手提交)
- pointercancel:触屏取消时与「松手」同口径提交当前预览(否则预览值会滞留到下一次提交或卸载 flush)
- 测试:`chatDialogFrameLayout.test.ts` 原来那组「点」断言整段换成**反向守卫**(样式表里不再有 `.project-chat-composer-strength-stops` 规则、组件源码也不再渲染该类名;滑块契约:宽 100% / 高 26 / 圆钮 20×20、强度区左右内边距 0);`home.suite.ts` 首页用例补一条「菜单里不再有那组点」
- 文档:pitfalls 的 D1 条改为现行口径(圆点已删、原因与判据;历史成因「被 6px 轨道盖住 / 与圆钮错位 ±12.2px」只留一句、由 Git 追溯)
Refs #600, PR #607
This commit is contained in:
@@ -11474,7 +11474,9 @@ button.design-workspace-tree__entry:hover,
|
||||
|
||||
/* ---- 强度区(组件自带类名;任何宿主共用同一份,没有宿主分支) ---- */
|
||||
|
||||
/* 强度区:菜单顶部,与列表之间只用留白分开(不画横贯分隔线),标题左右层级分明。 */
|
||||
/* 强度区:菜单顶部,与列表之间只用留白分开(不画横贯分隔线),标题左右层级分明。
|
||||
左右不留内边距:滑块(轨道 + 圆钮)直接铺满卡片内容宽度,填充段与圆钮两端与轨道两端贴齐
|
||||
—— 这条内边距原先只是为档位点排布留位,点删掉后必须归零,否则两端各多 6px 空白。 */
|
||||
.project-chat-reasoning-effort.is-section {
|
||||
display: grid;
|
||||
/* 单列铺满:`auto` 轨道在这里只按 max-content 定尺,滑块会被压回固有宽度。 */
|
||||
@@ -11483,12 +11485,12 @@ button.design-workspace-tree__entry:hover,
|
||||
width: 100%;
|
||||
align-self: stretch;
|
||||
gap: 10px;
|
||||
padding: 4px 6px 2px;
|
||||
padding: 4px 0 2px;
|
||||
}
|
||||
|
||||
/* 滑块与档位点是一个整体:点绝对定位叠在轨道中线上(不受字号 / 行高变化影响)。 */
|
||||
/* 滑块:圆钮(20px)与轨道(6px)叠在一起,命中与按 `step` 吸附由原生 range 负责;
|
||||
档位圆点删掉后这里不再需要相对定位的容器(点是唯一的绝对定位子元素)。 */
|
||||
.project-chat-composer-strength-slider {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
width: 100%;
|
||||
@@ -11634,45 +11636,10 @@ button.design-workspace-tree__entry:hover,
|
||||
0 2px 6px color-mix(in srgb, var(--platform-accent) 24%, transparent);
|
||||
}
|
||||
|
||||
/* 档位点:叠在轨道**之上**(z-index 高于 input),横向跟圆钮用同一套算式——
|
||||
两侧内边距取「圆钮半径 − 半点宽」,`space-between` 让首末点的**中心**正好落在
|
||||
圆钮两端的极限位置,中间各点等距重合;当前档位那一点隐藏(圆钮已经压在那里,
|
||||
再画点就会变成"靶心")。 */
|
||||
.project-chat-composer-strength-stops {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
/* 两侧内边距 = 圆钮半径 10px − 半点宽 3px(点 6px 见下):首末点的**中心**因此正好落在
|
||||
圆钮两端的极限位置,中间各点等距重合。改点宽或钮径时这条与下面的宽高要一起改。 */
|
||||
padding: 0 7px;
|
||||
height: 6px;
|
||||
transform: translateY(-50%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.project-chat-composer-strength-stops span {
|
||||
box-sizing: border-box;
|
||||
/* 变体 A:点直径 == 轨道高度(6px),不再上下各露 0.5px。 */
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 999px;
|
||||
/* 浅暖点:轨道上可见但不抢戏(原来是与圆钮同色的深棕,压在橙色已选段上很跳)。
|
||||
从 `--platform-text-strong` 与轨道色派生,不新造色值;对比度实测见 PR。 */
|
||||
background: color-mix(
|
||||
in srgb,
|
||||
var(--platform-text-strong) 60%,
|
||||
var(--platform-subpanel-border)
|
||||
);
|
||||
}
|
||||
|
||||
.project-chat-composer-strength-stops span.is-active {
|
||||
opacity: 0;
|
||||
}
|
||||
/* 档位圆点已删除(用户口径「很丑」,第一选择就是删):连同 `space-between` 排布、
|
||||
`z-index: 2` 抬层、`.is-active{opacity:0}` 与点的 `color-mix` 底色一起删掉,
|
||||
容器上那条「圆钮半径 − 半点宽」的 `padding: 0 7px` 也随之作废(滑块左右不再留白)。
|
||||
历史成因(点被 6px 轨道盖住、与圆钮两端错位 ±12.2px)由 Git 与 pitfalls 追溯。 */
|
||||
|
||||
.project-chat-composer-strength-value {
|
||||
color: var(--platform-text-soft);
|
||||
|
||||
+5
-12
@@ -624,21 +624,14 @@ export function ComposerReasoningEffortSelect({
|
||||
onInput={previewFromEvent}
|
||||
/* 松手 / 抬键 / 失焦才落盘:拖动中写盘会 disable 控件、原生拖拽当场中断。 */
|
||||
onPointerUp={commitPreview}
|
||||
/* 触屏取消(pointercancel)与"松手"同一口径:一并提交当前预览,
|
||||
否则预览值会滞留到下一次提交或卸载 flush。 */
|
||||
onPointerCancel={commitPreview}
|
||||
onKeyUp={commitPreview}
|
||||
onBlur={commitPreview}
|
||||
/>
|
||||
{/* 档位点叠在轨道上(纯装饰,命中与吸附由原生 range 负责)。 */}
|
||||
<span
|
||||
className="project-chat-composer-strength-stops"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{options.map((option, index) => (
|
||||
<span
|
||||
key={option.value}
|
||||
className={index === activeIndex ? 'is-active' : undefined}
|
||||
/>
|
||||
))}
|
||||
</span>
|
||||
{/* 档位圆点已删除(用户口径「很丑」,第一选择就是删):轨道本身就是刻度,
|
||||
命中与按 `step` 吸附仍由原生 range 负责,`aria-valuetext` 报中文档位名。 */}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -225,6 +225,10 @@ export function registerClientHomeTests() {
|
||||
await waitFor(() =>
|
||||
expect(slider?.getAttribute('aria-valuetext')).toBe('默认'),
|
||||
);
|
||||
// 档位圆点已删除(样式表里与渲染里都不再有那组元素)。
|
||||
expect(
|
||||
document.querySelector('.project-chat-composer-strength-stops'),
|
||||
).toBeNull();
|
||||
|
||||
const rules = parseStyleSheet(
|
||||
readFileSync(
|
||||
|
||||
@@ -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',
|
||||
);
|
||||
/** 同目录的控件实现(推理强度滑块在这里渲染)。 */
|
||||
const CHAT_COMPOSER_CONTROLS_PATH = repoPath(
|
||||
'apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectComposer/ComposerControls.tsx',
|
||||
);
|
||||
|
||||
function lengthPx(rawValue: string, label: string): number {
|
||||
const value = rawValue.trim();
|
||||
@@ -164,14 +168,13 @@ 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 的复核点:点被轨道压住、横向与圆钮错位)。
|
||||
这些规则与卡片一样已经抬到共享样式面(组件自带类名,不带宿主祖先链)。 */
|
||||
/** 强度区与滑块(issue #600 的复核点;档位圆点按用户口径已删除)。
|
||||
这些规则与卡片一样在共享样式面(组件自带类名,不带宿主祖先链)。 */
|
||||
const STRENGTH_SECTION = '.project-chat-reasoning-effort.is-section';
|
||||
const STRENGTH_RANGE = '.project-chat-composer-strength-range';
|
||||
const STRENGTH_THUMB = `${STRENGTH_RANGE}::-webkit-slider-thumb`;
|
||||
/** 已删除的档位点容器:留着它做反向守卫(谁都别把点写回来)。 */
|
||||
const STRENGTH_STOPS = '.project-chat-composer-strength-stops';
|
||||
const STRENGTH_STOPS_DOT = `${STRENGTH_STOPS} span`;
|
||||
const STRENGTH_STOPS_DOT_ACTIVE = `${STRENGTH_STOPS} span.is-active`;
|
||||
const TOPBAR = `${CHAT} .project-chat-topbar`;
|
||||
/** 列表实际会命中的全部选择器:direct-codex 直连与基础规则。 */
|
||||
const LIST_SELECTORS = [MESSAGE_LIST, MESSAGE_LIST_PLAIN];
|
||||
@@ -395,42 +398,37 @@ describe('陶泥儿对话区:Codex 三段式(顶栏 / 唯一滚动区 / 文
|
||||
expect(pixelValue(trigger, 'height')).toBe(30);
|
||||
});
|
||||
|
||||
it('档位点叠在轨道之上、横向与圆钮同一套算式,当前档位那一点留给圆钮(宽屏)', () => {
|
||||
it('档位圆点已删除,滑块契约与「两端贴齐」的强度区内边距仍在(宽屏)', () => {
|
||||
const section = desktopDeclarations(STRENGTH_SECTION);
|
||||
const range = desktopDeclarations(STRENGTH_RANGE);
|
||||
const thumb = desktopDeclarations(STRENGTH_THUMB);
|
||||
const stops = desktopDeclarations(STRENGTH_STOPS);
|
||||
const dot = desktopDeclarations(STRENGTH_STOPS_DOT);
|
||||
const activeDot = desktopDeclarations(STRENGTH_STOPS_DOT_ACTIVE);
|
||||
|
||||
// 点必须画在轨道**之上**:range 自己是 `z-index: 1`,点得比它高才不会被 6px 轨道压掉。
|
||||
expect(declaration(stops, 'position')).toBe('absolute');
|
||||
expect(
|
||||
Number(declaration(stops, 'z-index')),
|
||||
'档位点要在轨道(range 的 z-index)之上',
|
||||
).toBeGreaterThan(Number(declaration(range, 'z-index')));
|
||||
|
||||
// 横向跟圆钮共用一套算式:`space-between` + 两侧「圆钮半径 − 半点宽」的内边距,
|
||||
// 首末点的**中心**落点 = 圆钮两端极限位置(= 轨道两端内缩一个半径)。
|
||||
expect(declaration(stops, 'justify-content')).toBe('space-between');
|
||||
const knobRadius = pixelValue(thumb, 'width') / 2;
|
||||
const dotHalf = pixelValue(dot, 'width') / 2;
|
||||
const stopsPadding = paddingBox(stops);
|
||||
expect(
|
||||
stopsPadding.left,
|
||||
'首点的中心要落在圆钮的左极限位置(改点宽/钮径都要同步这条算式)',
|
||||
).toBe(knobRadius - dotHalf);
|
||||
expect(stopsPadding.right).toBe(knobRadius - dotHalf);
|
||||
|
||||
// 当前档位那一点不画:圆钮已经压在那儿,再画出来就是"靶心"。
|
||||
expect(pixelValue(activeDot, 'opacity')).toBe(0);
|
||||
// 点:直径 == 轨道高度(6px,不再上下各露 0.5px),浅暖色从既有 token 派生(对比度实测见 PR)。
|
||||
expect(pixelValue(dot, 'width')).toBe(6);
|
||||
expect(pixelValue(dot, 'height')).toBe(pixelValue(stops, 'height'));
|
||||
expect(declaration(dot, 'background')).toContain('color-mix');
|
||||
expect(declaration(dot, 'background')).toContain(
|
||||
'var(--platform-subpanel-border)',
|
||||
// 反向守卫①:样式表里**不再有**档位点的规则(谁把点写回来,这条就红)。
|
||||
expect(stops.has('position')).toBe(false);
|
||||
expect(stops.size).toBe(0);
|
||||
// 反向守卫②:组件源码里也不再渲染那组点。
|
||||
const controlsSource = readFileSync(CHAT_COMPOSER_CONTROLS_PATH, 'utf8');
|
||||
expect(controlsSource).not.toContain(
|
||||
'project-chat-composer-strength-stops',
|
||||
);
|
||||
expect(dot.has('border')).toBe(false);
|
||||
|
||||
// 滑块本体契约不变:铺满卡片内容宽度,轨道 6px、圆钮 20px。
|
||||
expect(declaration(range, 'width')).toBe('100%');
|
||||
expect(pixelValue(range, 'height')).toBe(26);
|
||||
expect(pixelValue(thumb, 'width')).toBe(20);
|
||||
expect(pixelValue(thumb, 'height')).toBe(20);
|
||||
|
||||
// 强度区左右不留内边距(那条 padding 原先只服务档位点排布):填充段与圆钮两端与轨道贴齐,
|
||||
// 中间不出现多余留白。上下留白不动(4 / 2)。
|
||||
const sectionPadding = paddingBox(section);
|
||||
expect(
|
||||
sectionPadding.left,
|
||||
'滑块左右不留白:点删掉后这条内边距必须归零',
|
||||
).toBe(0);
|
||||
expect(sectionPadding.right).toBe(0);
|
||||
expect(sectionPadding.top).toBe(4);
|
||||
expect(sectionPadding.bottom).toBe(2);
|
||||
});
|
||||
|
||||
it('窄屏(390px)输入盒仍在文档流、四周有边距,列表底部没有留白', () => {
|
||||
|
||||
Reference in New Issue
Block a user