fix(ui): 目标横幅在队列/skill菜单展开时收起为圆点且不顶高布局
目标模式就绪横幅原为流内元素,撑高 stadium-input-wrapper,使锚定其顶部的 消息队列与 skill 菜单被顶起,且其高度被计入聊天区预留高度,进而抬高可滚动范围。 - 收起态切为 absolute 脱离文档流,锚定输入框上方,圆点位置不变、文字收拢 - collectComposerVisualHeight 排除收起态横幅,不再计入预留高度 - 新增 watch(goalBannerCollapsed) 在 skill 菜单开关时重新上报高度 队列为空且无 skill 选择时自动展开恢复原样。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5693c50d3a
commit
1702ccacd2
@ -8,8 +8,10 @@
|
||||
:class="{
|
||||
'goal-mode-banner--running': goalRunning,
|
||||
'goal-mode-banner--done': goalCompleted && !goalRunning,
|
||||
'goal-mode-banner--clickable': goalRunning || goalCompleted
|
||||
'goal-mode-banner--clickable': goalRunning || goalCompleted,
|
||||
'goal-mode-banner--collapsed': goalBannerCollapsed
|
||||
}"
|
||||
:title="goalBannerCollapsed ? goalBannerTitle : undefined"
|
||||
@click.stop="goalRunning || goalCompleted ? $emit('open-goal-dialog') : null"
|
||||
>
|
||||
<span class="goal-mode-banner__dot" aria-hidden="true"></span>
|
||||
@ -1040,6 +1042,18 @@ const hasRuntimeLayoutExpansion = computed(() => {
|
||||
|
||||
const goalCompleted = computed(() => String(props.goalProgress?.status || '').toLowerCase() === 'done');
|
||||
|
||||
// 当消息队列非空或 skill 选择菜单展开时,把目标横幅收起为仅圆点,
|
||||
// 让队列/菜单紧贴输入框,不再被横幅顶高。队列清空且无 skill 选择时自动恢复。
|
||||
const goalBannerCollapsed = computed(
|
||||
() => runtimeQueuedMessagesForRender.value.length > 0 || skillSlashMenuOpen.value
|
||||
);
|
||||
|
||||
const goalBannerTitle = computed(() => {
|
||||
if (props.goalRunning) return '目标模式运行中';
|
||||
if (goalCompleted.value) return '目标模式完成';
|
||||
return '目标模式已就绪';
|
||||
});
|
||||
|
||||
const collectComposerVisualHeight = () => {
|
||||
const root = inputAreaRoot.value;
|
||||
const shell = compactInputShell.value;
|
||||
@ -1049,7 +1063,9 @@ const collectComposerVisualHeight = () => {
|
||||
const shellRect = shell.getBoundingClientRect();
|
||||
let top = shellRect.top;
|
||||
let bottom = shellRect.bottom;
|
||||
const nodes = root.querySelectorAll('.runtime-queue-list:not(.runtime-queue-list--empty), .skill-slash-menu, .goal-mode-banner');
|
||||
// 收起态横幅是脱离流、浮在角上的小圆点,不应计入为聊天区预留的高度,
|
||||
// 否则会把消息区可滚动范围顶高。故排除 .goal-mode-banner--collapsed。
|
||||
const nodes = root.querySelectorAll('.runtime-queue-list:not(.runtime-queue-list--empty), .skill-slash-menu, .goal-mode-banner:not(.goal-mode-banner--collapsed)');
|
||||
nodes.forEach((node) => {
|
||||
if (!(node instanceof HTMLElement)) return;
|
||||
const rect = node.getBoundingClientRect();
|
||||
@ -1258,6 +1274,13 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
// skill 菜单开关会切换目标横幅收起/展开态,需重新上报高度,
|
||||
// 否则展开回来时聊天区预留高度不会同步恢复。
|
||||
watch(goalBannerCollapsed, async () => {
|
||||
await nextTick();
|
||||
emitComposerHeight();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (hasSkillMarkdownLink.value) {
|
||||
renderRichEditor();
|
||||
@ -1321,6 +1344,30 @@ onBeforeUnmount(() => {
|
||||
background: color-mix(in srgb, var(--theme-surface-soft, #fffaf0) 92%, var(--claude-text-tertiary, #a59a86) 8%);
|
||||
border: 1px solid var(--theme-chip-border, rgba(118, 103, 84, 0.2));
|
||||
user-select: none;
|
||||
transition: gap 0.2s ease, padding 0.2s ease;
|
||||
}
|
||||
/* 收起态:仅保留圆点与外圈,文字消失、右侧收拢,圆点位置(左侧 padding)不变。
|
||||
关键:切到 absolute 脱离文档流,避免横幅占用一行流高度把队列/skill 菜单顶起来;
|
||||
锚定在输入框上方 6px、左 4px,与展开时的视觉位置一致,圆点位置不变。 */
|
||||
.goal-mode-banner--collapsed {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
bottom: calc(100% + 6px);
|
||||
z-index: 2;
|
||||
margin: 0;
|
||||
gap: 0;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.goal-mode-banner__text {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
max-width: 200px;
|
||||
opacity: 1;
|
||||
transition: max-width 0.2s ease, opacity 0.18s ease;
|
||||
}
|
||||
.goal-mode-banner--collapsed .goal-mode-banner__text {
|
||||
max-width: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
.goal-mode-banner--running {
|
||||
color: var(--claude-accent, #da7756);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user