agent-Specialization/demo/todo_float_window/style.css
JOJO 171833e4d1 feat(quickdock): 新增对话区右侧快捷窗口(待办/子智能体/后台指令/文件记录)
- 四窗口固定顺序占位布局,空时收起到 0 宽;动画区分「运行中新出现」与「切换/加载」
- 文件记录:edit/write 埋点写入对话 metadata.edited_files,预览走既有 /api/file/content
- 详情面板:lastDetail/lastStatus 快照、首次填充静态+瞬间到底、终态四色分类
- 数据通道全部走 REST 轮询(带 conversation_id 对话级隔离),含 demo 与设计文档
2026-07-22 00:52:36 +08:00

277 lines
7.5 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ============================================================
待办事项悬浮窗 Demo 样式
配色暂用经典主题暖色系,正式接入时替换为语义 token
============================================================ */
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--surface-base: #faf9f5;
--surface-float: #ffffff;
--surface-wash: #f5f0e8;
--border-subtle: #ece5d8;
--border-strong: #e2d9c8;
--text-primary: #26241f;
--text-secondary: #6f6a5e;
--text-tertiary: #a9a294;
--accent: #cc785c;
--accent-hover: #c06a4e;
--hover-wash: rgba(38, 36, 31, 0.04);
--shadow-float: 0 1px 2px rgba(38, 36, 31, 0.05), 0 8px 24px rgba(38, 36, 31, 0.10);
--row-h: 36px;
--window-max-w: 300px;
--ease-out: cubic-bezier(0.22, 0.9, 0.28, 1);
--ease-strike: cubic-bezier(0.55, 0.06, 0.35, 1);
}
body {
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
background: var(--surface-base);
color: var(--text-primary);
min-height: 100vh;
}
/* ---------------- 模拟对话区 ---------------- */
.mock-chat {
max-width: 640px;
margin: 0 auto;
padding: 64px 24px 220px;
display: flex;
flex-direction: column;
gap: 14px;
}
.mock-bubble {
max-width: 78%;
padding: 10px 14px;
border-radius: 14px;
font-size: 14px;
line-height: 1.6;
}
.mock-bubble--user { align-self: flex-end; background: #efe9de; }
.mock-bubble--ai { align-self: flex-start; background: #ffffff; border: 1px solid var(--border-subtle); }
/* ---------------- 悬浮窗口栈 ---------------- */
.float-stack {
position: fixed;
top: 20px;
right: 20px;
z-index: 100;
display: flex;
flex-direction: column;
align-items: flex-end; /* 多个窗口右对齐,上下排布 */
gap: 12px;
/* 整体超出屏幕高度时可滚动,滚动条隐藏 */
max-height: calc(100vh - 40px);
overflow-y: auto;
scrollbar-width: none;
-ms-overflow-style: none;
/* padding + 负 margin扩大滚动盒以容纳窗口阴影避免被 overflow 裁剪 */
padding: 24px;
margin: -24px;
}
.float-stack::-webkit-scrollbar { display: none; width: 0; height: 0; }
/* 窗口:圆角矩形 + 固定宽度(最大宽度的 90% + 不透明背景 + 克制阴影 */
.float-window {
flex: none; /* 禁止被栈 flex 压缩,保持固定高度 */
width: calc(var(--window-max-w) * 0.9); /* 300 * 0.9 = 270px */
background: var(--surface-float);
border: 1px solid var(--border-subtle);
border-radius: 12px;
box-shadow: var(--shadow-float);
overflow: hidden;
}
/* 窗口自身出现 / 消失(高度变化由行展开动画带动,这里只做淡入) */
.float-window.window-enter { animation: window-in 0.3s ease-out; }
@keyframes window-in {
from { opacity: 0; transform: translateY(-6px); }
to { opacity: 1; transform: translateY(0); }
}
.float-window.window-leave { animation: window-out 0.22s ease-in forwards; }
@keyframes window-out {
to { opacity: 0; transform: translateY(-4px) scale(0.98); }
}
/* 窗口标题栏 */
.float-window__header {
height: 38px;
display: flex;
align-items: center;
gap: 7px;
padding: 0 12px;
border-bottom: 1px solid var(--border-subtle);
}
.float-window__icon { width: 15px; height: 15px; color: var(--accent); flex: none; }
.float-window__title {
font-size: 12.5px;
font-weight: 600;
color: var(--text-secondary);
letter-spacing: 0.02em;
}
.todo-counter {
margin-left: auto;
font-size: 11.5px;
color: var(--text-tertiary);
font-variant-numeric: tabular-nums;
}
/* ---------------- 待办列表 ---------------- */
/* 窗口高度固定为 5 行,不足留空、超出内部滚动;滚动条完全隐藏。
无上下 padding首行 hover 紧贴标题栏分隔线,末行紧贴窗口底边 */
.todo-list {
list-style: none;
padding: 0;
height: calc(var(--row-h) * 5);
overflow-y: auto;
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* 旧 Edge */
}
.todo-list::-webkit-scrollbar { display: none; width: 0; height: 0; }
/* 每一行直接铺在窗口上:无背景、无边框、无嵌套卡片 */
/* 待办行不可点击,无 hover 效果 */
.todo-item {
height: var(--row-h);
display: flex;
align-items: center;
gap: 9px;
padding: 0 12px;
overflow: hidden; /* 配合移出动画的高度收拢 */
}
/* 状态点 */
.todo-dot {
flex: none;
width: 6px;
height: 6px;
border-radius: 50%;
border: 1.5px solid var(--text-tertiary);
background: transparent;
transition: background 0.2s ease, border-color 0.2s ease;
}
.todo-item.is-done .todo-dot { background: var(--accent); border-color: var(--accent); }
/* 任务文字:固定一行,超长省略 */
.todo-text {
position: relative;
flex: 1;
min-width: 0;
font-size: 13px;
line-height: 1;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition: color 0.22s ease 0.12s; /* 变灰略滞后于划线 */
}
/* 删除线(默认收起) */
.todo-text::after {
content: '';
position: absolute;
left: -1px;
right: -1px;
top: 50%;
height: 1.5px;
margin-top: -0.75px;
background: var(--text-tertiary);
border-radius: 1px;
transform: scaleX(0);
transform-origin: left center;
pointer-events: none;
}
/* 完成态(静态,用于整表渲染时已完成行) */
.todo-item.is-done .todo-text { color: var(--text-tertiary); }
.todo-item.is-done .todo-text::after { transform: scaleX(1); }
/* 完成动作瞬间:横线从左往右划过 + 状态点弹跳 */
.todo-item.just-done .todo-text::after {
animation: strike-in 0.28s var(--ease-strike) forwards;
}
@keyframes strike-in {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
.todo-item.just-done .todo-dot { animation: dot-pop 0.32s var(--ease-out); }
@keyframes dot-pop {
0% { transform: scale(1); }
45% { transform: scale(1.6); }
100% { transform: scale(1); }
}
/* 进入动画:从左向右位移 + 淡入stagger 由 JS 写 animation-delay */
.todo-item.is-entering {
opacity: 0;
animation: todo-in 0.34s var(--ease-out) forwards;
}
@keyframes todo-in {
from { opacity: 0; transform: translateX(-14px); }
to { opacity: 1; transform: translateX(0); }
}
/* 移出动画:从右向左位移 + 淡出,随后高度收拢让下方行平滑上移 */
.todo-item.is-leaving {
animation: todo-out 0.26s ease-in forwards;
}
@keyframes todo-out {
0% { opacity: 1; transform: translateX(0); height: var(--row-h); }
55% { opacity: 0; transform: translateX(-14px); height: var(--row-h); }
100% { opacity: 0; transform: translateX(-14px); height: 0; }
}
/* ---------------- demo 控制台 ---------------- */
.demo-panel {
position: fixed;
left: 20px;
bottom: 20px;
z-index: 100;
}
.demo-panel__hint {
font-size: 12px;
color: var(--text-tertiary);
margin-bottom: 10px;
}
.demo-panel__buttons {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
.demo-btn {
height: 34px;
padding: 0 14px;
border-radius: 8px;
border: 1px solid var(--border-strong);
background: var(--surface-float);
color: var(--text-primary);
font-size: 13px;
cursor: pointer;
transition: background 0.15s ease, border-color 0.15s ease;
}
.demo-btn:hover { background: var(--surface-wash); }
.demo-btn--primary { background: var(--accent); border-color: var(--accent); color: #ffffff; }
.demo-btn--primary:hover { background: var(--accent-hover); }
.demo-btn--ghost { border-style: dashed; color: var(--text-tertiary); }