style: give teacher shortcuts distinct text colors

This commit is contained in:
鲨鱼辣椒
2026-09-30 00:07:20 +08:00
parent 83a19fb19f
commit b934945f26
4 changed files with 31 additions and 10 deletions

View File

@@ -20,7 +20,7 @@
## Outcome
- Configured teacher shortcuts sit outside and directly above the composer. Latest approved styling uses 13px/600 green text with a subtle text shadow, no fill/border/box shadow, a small chevron and hover underline. The target-to-composer gap is 8px; wrapping/overflow/keyboard focus supported.
- Configured teacher shortcuts sit outside and directly above the composer. Latest approved styling uses one shortcut per row, eight distinct 13px/600 text colors with matching subtle shadows, no fill/border/box shadow, a small chevron and hover underline. The target-to-composer gap is 8px; wrapping/overflow/keyboard focus supported.
- Adapted product/tests dependency from main 53d5b6b (bb96941); original source task record remains in its source commit, excluded from this feature boundary. Explicit empty arrays hide prompts; absent historical field retains approved fallback. Published label and prompt are unchanged.
- Trial Renderer updated in place in PID 32583; Main and empty-work preview overlay remain intact. Live Alice cloud v53 supplies “继续看看咯”.
@@ -37,7 +37,7 @@
## Promotion Candidates
- Target: integrated classroom UI documentation. Proposal: configured prompts live 8px above the composer as transparent 13px/600 clickable text with a subtle text shadow and hover underline; exact cloud labels/prompts, absent/empty compatibility and send guards retained. Evidence: user approval, 75 unit / 23 browser tests and live trial comparison. No product-policy conflict; canonical promotion belongs to integration.
- Target: integrated classroom UI documentation. Proposal: configured prompts live 8px above the composer as transparent 13px/600 clickable text, one shortcut per row with distinct readable colors, matching text shadows and hover underline; exact cloud labels/prompts, absent/empty compatibility and send guards retained. Evidence: user approval, 75 unit / 23 browser tests and live trial comparison. No product-policy conflict; canonical promotion belongs to integration.
## Project Context Loaded
@@ -107,3 +107,13 @@
- Verification: four existing browser scenarios at 319/508px passed, including exact shortcut sends, long-label overflow and focus/hover/pressed behavior. Browser screenshot inspected. Typecheck, full lint (0 errors / 8 existing warnings), source and composite production builds passed.
- Trial: copied the latest sidebar-groups composite and changed only shortcut CSS. Built stylesheet index-DLG7JTx3.css was activated in PID 32583 without Renderer reload or Main restart; installed composite assets for later normal reload. Read-only verification confirmed 13px/600 and rgba(83,105,73,0.25) text shadow. Route, storage, drafts, 14 operation messages and teacher contents are unchanged; focused=false before/after. Inspector closed. No live prompts, cloud publication or main merge/push.
- Evidence: /tmp/teacher-text-depth-{browser,typecheck,lint,build,trial-build}.log, /tmp/teacher-text-depth-results and temporary trial teacher-text-depth-a682d30f/verification.json. Task-aware docs and whitespace checks passed before commit.
## Colored Text Follow-up
- Resumed the same task at 83a19fb, verified matching feature/branch/worktree ownership and reread peer scope records. Existing planning/design context unchanged; sidebar grouping remains unrelated. Teacher composer-files peer has no concrete dependency on shortcut colors; preserve its work and any newer trial overlays. Gate passed.
- User wants a different text color per row. Plan: one configured shortcut per row, with eight distinct readable colors, matching subtle text shadows and darker hover/pressed variants. Keep 13px/600, transparent background, 30px target and 8px composer spacing; no prompt or sending changes. Adapt existing browser checks, verify builds and update trial CSS without reload or native focus.
- Completed: eight distinct blue/purple/ochre/teal/rose/indigo/terracotta/green colors, one shortcut per row, with matched text shadow and darker hover/pressed colors. Base text contrast on the pane is at least 4.85:1. Prevent flex shrinking from compressing wrapped lines inside the bounded scrolling area.
- Verification: four existing browser cases passed at 319/508px, including eight distinct row colors, no overlapping/clipped wrapped text, exact sends, focus and 8px composer gap. Inspected narrow screenshot after correcting the wrap compression found visually. Typecheck, lint (0 errors / 8 existing warnings), source and latest-composite production builds passed.
- Trial stylesheet index-D03AC39p.css activated in PID 32583 without reload, restart or native focus. Preserved latest composite overlays; next-load assets prepared. Read-only verification confirms transparent background, no box shadow, 600 weight and color-based text shadow. Local storage and route stayed identical; app stayed unfocused. Conversation hydration progressed from 0 to 14 operation messages during verification, so messages/inputs are not claimed byte-identical. No writes to history/drafts or model requests were made. Inspector was already open on the verified trial PID and is left as found.
- Evidence: /tmp/teacher-text-colors-{browser,typecheck,lint,build,trial-build}.log, /tmp/teacher-text-colors-results and temporary trial teacher-text-colors-a682d30f/verification.json. No main merge/push or cloud publication. Task-aware docs and whitespace checks passed.

View File

@@ -183,7 +183,7 @@ Pi 正式包必须继续运行 `pnpm run verify:artifact:pi`、`pnpm run smoke:p
- 咨询正文支持 Markdown 标题、列表、表格、代码围栏、HTTP(S) 链接/图片和数学公式,长代码与表格在栏内横向滚动,不执行 HTML。云端正文维持 string 合同,未知对象不会猜测转成回答。工具活动只从云端主线程的类型化工具事件及 Main 本地读取过程获得,按本次问题/工具调用身份合并名称和状态,跨云端暂停、续接仍只计一次;暂停读取不算失败,状态以实际读取结果或问题终态为准,单独折叠显示;参数、结果原文和内部错误不混入回复,思考内容不作为正文。客户端仅保存自己实际收到的工具状态,不能补回旧历史或断线期间已经过期的事件。
- 云端咨询在 local_context 声明 read_protocol=2;需先部署配套 Yuxi API 和 worker,再升级客户端。云端持久累计读取字节及批次,每轮告知模型剩余额度;预算耗尽后消费最后一批结果,并以 tool_choice=none 要求根据现有证据形成答案和说明缺口。Main 限制实际返回量并拒绝第十三批读取,区分读取达到上限、上下文失效及格式无效。服务端对未声明协议的已安装旧客户端保留原工具参数与六批边界。
- 智能体人设、职责、提示词和 Skills 由发布配置决定。Main 不追加固定教学基线、不生成“小麦”、不清空所选智能体的 Skills,只添加真实工具能力、上下文边界和本轮界面协议。智能体名称叫“老师”“朋友”或“代码顾问”不改变调用路径或权限。
- 输入框为空时,在输入框外上方显示当前老师已发布的快捷提示;采用 13px 半粗字重和轻微文字阴影,显示为无底色、无边框、无块状阴影的绿色可点击文字与小箭头,入口距输入框 8px;悬停时文字加深并显示下划线,键盘聚焦有清晰轮廓,保留 30px 点击高度,横向排列并自动换行。按 Yuxi 中配置的顺序展示文案,点击直接发送该项实际提示词。Yuxi“编辑 → 快捷提示”支持最多 8 项,每项文案最多 40 字、提示词最多 6000 字;保存并发布后,目录更新即可生效,历史和未发送草稿保留。明确发布空列表隐藏全部按钮;缺少字段的历史版本保留“帮我整体看🧠”。多个长文案在限定高度内滚动,运行中禁止重复发送。上线需先更新 WS 登记接口,再更新 Yuxi 和客户端。
- 输入框为空时,在输入框外上方显示当前老师已发布的快捷提示;采用 13px 半粗字重,每条独立一行、按顺序使用不同的彩色文字和同色轻微文字阴影,搭配小箭头;无底色、无边框、无块状阴影,入口距输入框 8px;悬停时文字加深并显示下划线,键盘聚焦有清晰轮廓,保留 30px 点击高度,长文案自动换行。按 Yuxi 中配置的顺序展示文案,点击直接发送该项实际提示词。Yuxi“编辑 → 快捷提示”支持最多 8 项,每项文案最多 40 字、提示词最多 6000 字;保存并发布后,目录更新即可生效,历史和未发送草稿保留。明确发布空列表隐藏全部按钮;缺少字段的历史版本保留“帮我整体看🧠”。多个长文案在限定高度内滚动,运行中禁止重复发送。上线需先更新 WS 登记接口,再更新 Yuxi 和客户端。
- `reply.ts` 只声明正文与快捷回复的输出格式,语言、长度、前缀与表达风格由所选智能体的云端配置决定。客户端不再发送选择、生成、转换或维护展示组件的指令。旧话题内的组件状态、快照和解析诊断作为不透明历史数据原样保留,不校验删除、不恢复交互;旧组件修改路由已移除。
- 当前输入是按预算截取的所选操作对话已完成分支文本、明确引用、咨询正文和快捷回复,并支持上述只读原文恢复;旧组件状态、快照和未解析原文不加入模型上下文或咨询历史读取结果。没有跨全部操作会话自动读取,也未向操作 Agent 注入咨询共识。提示词不声称看过未提供的画面或试玩过作品。Yuxi 话题经云端原生执行,旧版本地智能体由 Main 调用计费网关;均不创建本地 Pi 编程 worker。
- 智能体输入裁剪区分两种计量:本地模型以约每 2 个 UTF-8 字节估算 1 Token,并计入工具与读取预留;这不是精确分词或扣费依据,模型上限与实际 usage 仍由服务端拥有。云端沿用 query 字节上限,以完整 JSON 转义后的大小裁剪来源节选。智能体指令、当前问题和明确引用不会被静默裁掉;固定配置或回复协议超限时明确提示调整配置,避免让学生反复缩短短问题或新建话题。完整来源仍可由只读工具按需读取。

View File

@@ -52,11 +52,18 @@
.consultation-retry { display: inline-flex; align-items: center; justify-content: center; align-self: flex-start; min-height: 44px; max-width: 100%; padding: 8px 16px; border: 1.5px solid #e3ce8f; border-radius: 16px 16px 16px 6px; background: #fff2c9; color: #6f5127; box-shadow: 0 3px 0 #e7d7a6, inset 0 1px 0 #fff9e8; font-size: 14px; font-weight: 600; line-height: 24px; cursor: pointer; transition: background-color 160ms ease, border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; }
.consultation-retry:hover:not(:disabled) { background: #ffe9a9; border-color: #d6b76f; }
.consultation-retry:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 #e7d7a6, inset 0 1px 0 #fff9e8; }
.consultation-shortcuts { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 4px 16px; max-height: min(192px, 24vh); overflow-y: auto; margin-bottom: 2px; padding: 3px 4px 6px; }
.consultation-hint { display: inline-flex; align-items: center; gap: 7px; max-width: 100%; min-height: 30px; padding: 4px 2px; border: 0; border-radius: 4px; background: transparent; box-shadow: none; color: #536949; font-size: 13px; font-weight: 600; text-shadow: 0 1px 1px #53694940; line-height: 22px; text-align: left; white-space: normal; overflow-wrap: anywhere; text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: 1px; text-underline-offset: 4px; cursor: pointer; transition: color 150ms ease, text-decoration-color 150ms ease; }
.consultation-shortcuts { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; max-height: min(192px, 24vh); overflow-y: auto; margin-bottom: 2px; padding: 3px 4px 6px; }
.consultation-hint { --hint-color: #37679d; --hint-hover: #284f7b; --hint-active: #203f63; display: inline-flex; flex-shrink: 0; align-items: center; gap: 7px; max-width: 100%; min-height: 30px; padding: 4px 2px; border: 0; border-radius: 4px; background: transparent; box-shadow: none; color: var(--hint-color); font-size: 13px; font-weight: 600; text-shadow: 0 1px 1px color-mix(in srgb, currentColor 25%, transparent); line-height: 22px; text-align: left; white-space: normal; overflow-wrap: anywhere; text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: 1px; text-underline-offset: 4px; cursor: pointer; transition: color 150ms ease, text-decoration-color 150ms ease; }
.consultation-hint:nth-child(8n + 2) { --hint-color: #8061a0; --hint-hover: #664a83; --hint-active: #503865; }
.consultation-hint:nth-child(8n + 3) { --hint-color: #91631d; --hint-hover: #744d12; --hint-active: #5a3b0d; }
.consultation-hint:nth-child(8n + 4) { --hint-color: #34786c; --hint-hover: #265e54; --hint-active: #1c4941; }
.consultation-hint:nth-child(8n + 5) { --hint-color: #a35470; --hint-hover: #854059; --hint-active: #693046; }
.consultation-hint:nth-child(8n + 6) { --hint-color: #626ba0; --hint-hover: #4d5684; --hint-active: #3c4369; }
.consultation-hint:nth-child(8n + 7) { --hint-color: #a85c3d; --hint-hover: #87472d; --hint-active: #6b3621; }
.consultation-hint:nth-child(8n + 8) { --hint-color: #617735; --hint-hover: #4b5f27; --hint-active: #3a4a1c; }
.consultation-hint::after { content: ''; width: 5px; height: 5px; flex-shrink: 0; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(-45deg); opacity: 0.7; }
.consultation-hint:hover:not(:disabled) { color: #304631; text-decoration-color: currentColor; }
.consultation-hint:active:not(:disabled) { color: #243727; }
.consultation-hint:hover:not(:disabled) { color: var(--hint-hover); text-decoration-color: currentColor; }
.consultation-hint:active:not(:disabled) { color: var(--hint-active); }
.consultation-hint:focus-visible { outline: 2px solid #71845f; outline-offset: 3px; text-decoration-color: currentColor; }
.consultation-hint:disabled, .consultation-retry:disabled { cursor: not-allowed; opacity: 0.5; }
@media (prefers-reduced-motion: reduce) { .consultation-hint, .consultation-retry { transition: none; } .consultation-retry:active:not(:disabled) { transform: none; } }

View File

@@ -66,15 +66,19 @@ for (const width of [319, 508]) {
await expect(shortcuts.first()).toHaveCSS('box-shadow', 'none');
await expect(shortcuts.first()).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
expect((await row.boundingBox())!.y + (await row.boundingBox())!.height).toBeLessThan((await composer.boundingBox())!.y);
const shortcutRows = await shortcuts.evaluateAll(elements => elements.map(el => ({ color: getComputedStyle(el).color, top: el.getBoundingClientRect().top, bottom: el.getBoundingClientRect().bottom })));
expect(new Set(shortcutRows.map(row => row.color)).size).toBe(8);
expect(await shortcuts.evaluateAll(elements => elements.every(el => el.scrollHeight <= el.clientHeight))).toBe(true);
expect(shortcutRows.every((row, index) => index === 0 || row.top >= shortcutRows[index - 1].bottom)).toBe(true);
await shortcuts.first().focus();
await expect(shortcuts.first()).toHaveCSS('outline-style', 'solid');
await expect(shortcuts.first()).toHaveCSS('cursor', 'pointer');
await shortcuts.first().hover();
await expect(shortcuts.first()).toHaveCSS('color', 'rgb(48, 70, 49)');
await expect(shortcuts.first()).toHaveCSS('text-decoration-color', 'rgb(48, 70, 49)');
await expect(shortcuts.first()).toHaveCSS('color', 'rgb(40, 79, 123)');
await expect(shortcuts.first()).toHaveCSS('text-decoration-color', 'rgb(40, 79, 123)');
await expect(shortcuts.first()).toHaveCSS('transform', 'none');
await page.mouse.down();
await expect(shortcuts.first()).toHaveCSS('color', 'rgb(36, 55, 39)');
await expect(shortcuts.first()).toHaveCSS('color', 'rgb(32, 63, 99)');
await expect(shortcuts.first()).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
await expect(shortcuts.first()).toHaveCSS('transform', 'none');
await page.mouse.move(0, 0);