From 73792a81b14298a9c0567b674b5f3b41bb2b3a01 Mon Sep 17 00:00:00 2001 From: Yichen Jiang Date: Fri, 21 Aug 2026 17:09:07 +0800 Subject: [PATCH] fix(ui-conversation): restore the folder glyph on composer folder references The old backdrop overpainted a folder reference's trigger character with IconFolderClose16; the Lexical rewrite kept the data-ref-appearance attribute but nothing consumed it, so the composer showed a bare blue token while the sent bubble carried the icon. A Lexical text node cannot split out its trigger character for overpainting, so the glyph renders as an icon prefix instead: a currentcolor mask of the same asset before the intact literal token. The Lexical note's behavior line follows. --- ...26-08-20-web-composer-lexical-editor.i18n.yaml | 4 ++-- .../2026-08-20-web-composer-lexical-editor.md | 2 +- .../2026-08-20-web-composer-lexical-editor.zh.md | 2 +- .../input/editor/composer-editor.module.css | 15 +++++++++++++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.i18n.yaml index c27cfafcd9..3c47eef5c6 100644 --- a/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.md -2026-08-20-web-composer-lexical-editor.md: ddb04fd97a653dac9e1cbef83e432875b1e40280 -2026-08-20-web-composer-lexical-editor.zh.md: f4435ed0ec3f9b9acf6acd72b0d7a9c6bfc3f28a +2026-08-20-web-composer-lexical-editor.md: bc1f2f55c894ef547454d59977c70d696c071529 +2026-08-20-web-composer-lexical-editor.zh.md: 2ba7e495a7eb80877a096251f0982686016470d6 diff --git a/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.md b/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.md index ddb04fd97a..bc1f2f55c8 100644 --- a/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.md +++ b/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.md @@ -30,7 +30,7 @@ The mirror/backdrop layers and their CSS coupling rules; the Safari soft-wrap re - Claimed command args now reach the source in clipboard form (references as canonical text, not display labels) — the parseable form. - `InputState.draft` is the clipboard projection (was display text). Cross-package readers consume phase/queue-level fields; the occurrence table had zero external readers. - Chip deletion follows the engine's native decorator gesture; jsdom lacks `Selection.modify`, so the keyboard path is asserted in the browser lane only. -- Folder text-refs keep the `@` glyph beside the folder appearance attribute instead of overpainting the trigger character. +- Folder text-refs render the folder glyph as an icon prefix before the intact literal token (a currentcolor mask of the bubble's asset); the old backdrop overpainted the trigger character instead, which a Lexical text node cannot express. - The composer's accessible name is an explicit `aria-label` mirroring the placeholder (a div's `data-placeholder` does not name it the way a textarea's placeholder did) — caught by the reference-composer aria golden. - Caret-only commits publish nothing: the shell advances `draftRev` and re-publishes `InputState` only when the projection's content changes. Caret motion still feeds menu tracking, but it neither invalidates snapshot-built CAS spans (apply.ts builds spans from the published `draftRev`) nor re-renders subscribers. The first cut re-published on every commit; review caught the drift from the old machine's text-only revision. - A paste is its own undo boundary: the custom PASTE_COMMAND handler consumes the event before `@lexical/plain-text` could tag the update, so the shell attaches `PASTE_TAG` itself (via `$addUpdateTag` — the dispatch path always runs nested inside the command update). Without it, history merged a paste with typing inside the 1s window and one undo removed both. diff --git a/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.zh.md b/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.zh.md index f4435ed0ec..2ba7e495a7 100644 --- a/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.zh.md +++ b/.agents/notes/implemented/architecture/2026-08-20-web-composer-lexical-editor.zh.md @@ -30,7 +30,7 @@ mirror/backdrop 层及其 CSS 耦合规则;Safari 软换行修复(2026-08-13 - 已认领命令的 args 现以剪贴板形式到达 source(引用为规范文本而非展示标签)——可解析的那种形式。 - `InputState.draft` 是剪贴板投影(原为展示文本)。跨包读方只消费 phase/queue 级字段;occurrence 表的外部读方为零。 - chip 删除遵循引擎的原生 decorator 手势;jsdom 缺 `Selection.modify`,键盘路径只在浏览器 lane 断言。 -- 文件夹纯文本引用保留 `@` 字形并携带 appearance 属性,不再覆盖 trigger 字符。 +- 文件夹纯文本引用在完整字面 token 前渲染文件夹图标前缀(气泡同款资产的 currentcolor mask);旧 backdrop 是覆盖绘制 trigger 字符,而 Lexical 文本节点无法表达这种覆盖。 - 输入框的可访问名称改为显式 `aria-label` 镜像 placeholder(div 的 `data-placeholder` 不像 textarea 的 placeholder 那样参与命名)——由 reference-composer 的 aria golden 逮出。 - 纯光标 commit 不发布任何东西:shell 只在投影内容变化时推进 `draftRev` 并重发布 `InputState`。光标移动仍然喂给菜单 tracking,但既不会使快照构造的 CAS span 失效(apply.ts 用已发布的 `draftRev` 构造 span),也不会触发订阅者重渲染。第一版每次 commit 都重发布;review 逮出了与旧机器「仅文本推进版本号」语义的漂移。 - 粘贴是独立的 undo 边界:自定义 PASTE_COMMAND handler 在 `@lexical/plain-text` 有机会打 tag 之前就消费了事件,因此 shell 自己补上 `PASTE_TAG`(经 `$addUpdateTag`——dispatch 路径必然嵌套在命令 update 内部执行)。没有它,history 会把粘贴与 1 秒窗内的输入合并,一次 undo 同时撤销两者。 diff --git a/packages/client/ui-conversation/src/client/input/editor/composer-editor.module.css b/packages/client/ui-conversation/src/client/input/editor/composer-editor.module.css index 3e97afb3fb..40f6f2d075 100644 --- a/packages/client/ui-conversation/src/client/input/editor/composer-editor.module.css +++ b/packages/client/ui-conversation/src/client/input/editor/composer-editor.module.css @@ -9,3 +9,18 @@ box-decoration-break: clone; -webkit-box-decoration-break: clone; } + +/* Folder references carry the domain glyph as an icon prefix (the bubble's + IconFolderClose16 asset as a currentcolor mask). The literal token text — + trigger character included — stays intact: a Lexical text node cannot + split out its trigger character the way the old backdrop overpainted it. */ +.textRef[data-ref-appearance='folder']::before { + display: inline-block; + width: 14px; + height: 14px; + margin-right: 2px; + vertical-align: -2px; + background-color: currentcolor; + content: ''; + mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20transform%3D%22translate(1.5%202.429)%22%20d%3D%22M5.05582%200.518756L4.50669%200.86654L5.05582%200.518756ZM13%209.4837L13.65%209.4837L13.65%203.53962L13%203.53962L12.35%203.53962L12.35%209.4837L13%209.4837ZM11.3264%201.86603L11.3264%201.21603L6.52313%201.21603L6.52313%201.86603L6.52313%202.51603L11.3264%202.51603L11.3264%201.86603ZM5.58054%201.34727L6.12968%200.999489L5.60495%200.170972L5.05582%200.518756L4.50669%200.86654L5.03141%201.69506L5.58054%201.34727ZM4.11323%201.23058e-13L4.11323%20-0.65L1.67359%20-0.65L1.67359%205.00699e-14L1.67359%200.65L4.11323%200.65L4.11323%201.23058e-13ZM0%201.67359L-0.65%201.67359L-0.65%209.4837L0%209.4837L0.65%209.4837L0.65%201.67359L0%201.67359ZM11.3264%2011.1573L11.3264%2010.5073L1.67359%2010.5073L1.67359%2011.1573L1.67359%2011.8073L11.3264%2011.8073L11.3264%2011.1573ZM0%209.4837L-0.65%209.4837C-0.65%2010.767%200.390308%2011.8073%201.67359%2011.8073L1.67359%2011.1573L1.67359%2010.5073C1.10828%2010.5073%200.65%2010.049%200.65%209.4837L0%209.4837ZM1.67359%205.00699e-14L1.67359%20-0.65C0.390307%20-0.65%20-0.65%200.390309%20-0.65%201.67359L0%201.67359L0.65%201.67359C0.65%201.10828%201.10828%200.65%201.67359%200.65L1.67359%205.00699e-14ZM5.05582%200.518756L5.60495%200.170972C5.28121%20-0.340193%204.71829%20-0.65%204.11323%20-0.65L4.11323%201.23058e-13L4.11323%200.65C4.27282%200.65%204.4213%200.731715%204.50669%200.86654L5.05582%200.518756ZM6.52313%201.86603L6.52313%201.21603C6.36354%201.21603%206.21507%201.13431%206.12968%200.999489L5.58054%201.34727L5.03141%201.69506C5.35515%202.20622%205.91808%202.51603%206.52313%202.51603L6.52313%201.86603ZM13%203.53962L13.65%203.53962C13.65%202.25634%2012.6097%201.21603%2011.3264%201.21603L11.3264%201.86603L11.3264%202.51603C11.8917%202.51603%2012.35%202.97431%2012.35%203.53962L13%203.53962ZM13%209.4837L12.35%209.4837C12.35%2010.049%2011.8917%2010.5073%2011.3264%2010.5073L11.3264%2011.1573L11.3264%2011.8073C12.6097%2011.8073%2013.65%2010.767%2013.65%209.4837L13%209.4837Z%22%20fill%3D%22black%22%2F%3E%3C%2Fsvg%3E") center / contain no-repeat; +}