Repository navigation
fix(ui): stop collapsible content flashing on collapse, keep transcript focus ring hidden / 修复折叠块收起闪烁与聊天记录焦点框 - #896
Merged
xintaofei merged 4 commits intoOct 9, 2026
Conversation
`tw-animate-css`'s `animate-out` runs with `animation-fill-mode: none`, so the moment the exit animation ends the content snaps back to its resting style (full opacity, no slide). The unmount only landed in a later task, after that frame had painted, so every collapse showed one fully visible frame of the content that was just folded away. Hold the exit's last keyframe (`animation-fill-mode: forwards`) until the node is removed, and remove it synchronously from the `animationend` handler so it is gone before the next paint. A reopen during the exit restores the node's own fill mode. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Clicking the transcript marks the scroll viewport as pointer-focused (`data-focus-origin="pointer"`) so the `focus-visible` ring stays off. Two things dropped that marker while the viewport was still focused, and the ring then appeared around the whole transcript: - the `keydown` listener, so any key — Esc included — brought the ring back (a key press makes the browser match `:focus-visible`); - the `blur` listener, which also fires when the whole window loses focus. The viewport stays the document's active element and the browser re-focuses it when the window returns (e.g. on a resize), now without the marker. Drop the keydown listener, and on blur wait for it to settle and only clear the marker when the viewport is really no longer the active element. Tabbing into the viewport still shows the ring: that focus never sets the marker. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The collapse flash fix unmounted the content with flushSync from its native animationend listener. That removed the node before React dispatched the same event, so a CollapsibleContent onAnimationEnd never saw the exit animation end. Holding the exit's last keyframe (animation-fill-mode: forwards) stops the flash on its own: the frame after animationend paints the held keyframe, and the plain state update unmounts the node in a later task. Radix Presence relies on the same hold. A cancelled exit has no keyframe left to hold, so that path still unmounts synchronously; React has no onAnimationCancel to lose. Cover the fill-mode hold, its restore when the content reopens mid-exit, the onAnimationEnd delivery, and the synchronous unmount on a cancelled exit.
After a click on the transcript, scrolling it from the keyboard (arrow keys, Page Up/Down, Home/End, Space, with any modifier) drops the pointer-origin marker again, so the focus ring returns for keyboard use as WCAG 2.4.7 asks. Other keys keep the marker: Esc, or Ctrl/Cmd+C to copy a selection, no longer ring the whole transcript. Also re-check the marker when the window regains focus. Focus moved by a script while the window was in the background never blurs the viewport a second time, so the marker went stale and Tabbing back into the transcript later showed no ring.
Collaborator
|
codeg work task |
xintaofei
added a commit
that referenced
this pull request
Oct 10, 2026
This one lets agents answer with more than text: turn on Generative UI, and a reply can show cards, tables and other interactive components right in the conversation. The chat column can be widened by dragging its edges, chat animations can be switched off, and a conversation can be maximized while files are open beside it. Claude Code moves up to 0.89.1 and Codex to 2.2.2, along with five more bundled agents. Alongside that: the terminal panel comes back after a page reload, a workspace with many tabs opens much faster, remote workspaces keep reconnecting through outages and reopen even while their server is offline, the Open Folder dialog can create a folder, and a failed turn ends with one line saying why. ## New - **Agents can reply with interactive cards and tables** once you turn on "Generative UI (json-render)" under Settings → Skill Packs → UI: start a message with `/json-render` (`$json-render` in Codex) or just ask to see something as cards or a table, and the reply renders as live components while it streams. - **The chat column can be made wider or narrower** by dragging its left or right edge, or under Settings → Appearance → Chat width, and double-clicking an edge puts it back to the default. (#911, @sumanx) - **Chat animations can be switched off** under Settings → Appearance, so expanding, collapsing, working indicators and scrolling in the conversation happen instantly, while spinners keep turning. (#911, @sumanx) - **A conversation can be maximized while files are open beside it**, from the Maximize button at the right end of its tab strip, and Restore brings the files back just as you left them. - **The Open Folder dialog can create a new folder** and step into it, so a project can start from an empty folder, in the desktop app and the web version alike. (#881, @Jonathan-Asher) - **A remote workspace window can open the local workspace** from Quick actions in the status bar, the macOS Window menu, or the page shown when its connection fails or expires. (#891, @ker2xu) ## Improved - **Updated bundled agents:** Claude Code ACP 0.89.1 (Claude Code 2.1.293), Codex ACP 2.2.2 (Codex CLI 0.160.1), Cline 3.0.70, CodeBuddy 2.164.0, Grok 1.0.51, Qoder 1.1.67, Hermes 0.21.6. - **A failed turn ends with one muted line giving the agent's own error** in Codex, Claude Code, Cline and Qoder conversations, both as it happens and when you reopen the conversation. - **A workspace with many open tabs opens much faster**, because a tab sitting behind another now loads its conversation the first time you switch to it instead of every tab downloading its conversation at once. (#913, @Flyneen) - **Resizing the window is smoother**, as the workspace no longer runs extra full-page layouts on every step. (#898, @sumanx) - **Slash commands show the arguments they take** in the `/` menu, the message box's Add menu and the automation editor. - **Codex answers `/mcp` with the live status of each MCP server**, and `/mcp reconnect` works there too. - **Claude Code's Agent card shows the effort a sub-agent was asked to run at**, next to its model. - **Claude Haiku 5.5 is now the suggested Haiku model** in Claude Code's settings and in the model provider dialogs. - **On phones, the web version tints the browser bar and Android's navigation bar to match your light or dark theme**, and adding it to the home screen installs codeg as an app with a full-bleed icon, even behind a sign-in proxy. (#863, @eyjohn) ## Fixed - **Reloading the page or reconnecting no longer loses the terminal panel**: its tabs come back with their commands still running and their output in place, and a finished command's output stays until you close its tab. (#830, @dawNotPoi; #749 reported by @kekxv) - **Claude Code no longer leaves a conversation spinning for hours** after you send a message during a turn it started on its own, such as after a background task finished, and that message now gets a single reply. (#893 reported by @Luis-WowApps) - **Sending Claude Code a message while it is still writing a tool call no longer fails the turn.** - **Messages you send while a Claude Code turn is running now stay in its history**, and a background task that finished mid-turn shows its result there instead of looking unfinished. - **A Claude Code conversation's title no longer flips back and forth** between its first and its latest message in the sidebar and in a linked chat channel topic when Claude Code can't generate a title, as behind a gateway that refuses the request. - **Replies from turns a custom agent starts on its own**, such as after a background job, now stay in the conversation after a reload instead of only showing live. (#903 reported by @andrehqh) - **A custom agent that runs Claude Code's ACP adapter now takes messages inserted into the current turn directly**, as the built-in Claude Code does, and those messages stay in its history. (#892 reported by @andrehqh) - **A remote workspace keeps reconnecting through network outages** and shows a notice while it does, instead of giving up after three failed attempts and calling the connection expired, which now happens only when the server rejects the token. (#887, #890, @ker2xu) - **Remote workspace windows reopen at launch even while their server is offline**, and pick up in place once it is back. (#887, #890, @ker2xu) - **Clicking the Dock icon on macOS brings up the workspace you used last**, a minimized remote one included, instead of always the local window, and launching codeg again on Windows and Linux does the same. (#887, #889, @ker2xu) - **Custom agents from the ACP registry now install on Windows**, where most binary entries looked for a doubled name like `kilo.exe.exe`, and an agent published as a plain executable rather than an archive can be installed too. (#905 reported by @trueai-org) - **Agents installed with their official installer into `~/.local/bin`, such as Hermes, are now found when codeg isn't started from a terminal**, instead of showing as not installed. (#888, @Sma1lboy; #875 reported by @toptiersnowman) - **An OpenCode 2.x installed on your system now connects**, as codeg no longer passes it the `--port` and `--hostname` options its `acp` command rejects. (#909, @Liang-HZ) - **Effort choices now match the model you picked** under Agent defaults in Settings → Collaboration and in the to-do and automation editors, instead of following the agent's default model. (#910, @Liang-HZ) - **Scrolling up while a reply streams no longer pulls you back to the bottom**, whether you use the wheel over a code block, touch, the keyboard or the scrollbar. (#899, @Adam-Dalloul) - **Reordering conversation tabs no longer leaves a tab's transcript blank** until you scroll it. (#901, @Adam-Dalloul) - **In a sent message, a `/word` or `$word` shows as a command only when the agent actually offers that command or skill**, so paths like `/tmp` stay plain text. (#902, @Adam-Dalloul) - **The tab strip no longer squeezes and springs back when you open or close a side panel.** (#912, @sumanx) - **The sidebar, side panel and terminal panel no longer wobble while you resize the window.** (#897, @sumanx) - **Collapsing a thinking block or tool card no longer flashes its content for a frame**, and after a click in the conversation, pressing Esc, copying or coming back from another window no longer draws a focus outline around it. (#896, @sumanx) - **A conversation that fails to load now retries at growing intervals, up to every 30 seconds**, with the error and Reload button staying in view, instead of re-requesting nonstop while the error flickers. - **A conversation no longer stays stuck loading** when a background sync or a page of older messages arrives while it loads. - **Token usage is counted more accurately**: Codex no longer counts cache writes as fresh input, with existing Codex conversations recounted, and CodeBuddy totals now include requests that end in a tool call. - **Cline history no longer shows the messages Cline marks as internal**, such as compaction summaries, hook context and the prompt it sends itself after you approve switching to Act mode. - **Claude Code conversations reopened from history show a 1M context window for models that have one natively**, such as Opus 4.7 and later, Sonnet 5 and later, Haiku 5.5, Fable and Mythos, instead of 200K. - **Backups now include Codex's conversation names**, and restoring merges Codex's and Kimi's session lists with what is already there instead of skipping or overwriting them, so restored conversations keep their names and folders. - **On macOS, computer use presses return after typing into a Chromium or Electron app when the agent asks to submit**, instead of treating the typing as failed because the field reads back empty. - **The desktop app writes its logs to the same folder however it is started**, and Settings → Runtime Logs opens the folder actually in use and shows each file's current size. (#893 reported by @Luis-WowApps) ## Note - **Codex ACP 2.2 needs Node.js 20.3.0 or later**, as every message fails on Node.js 20.0 through 20.2, and the environment diagnostics now check the full Node.js version each agent needs rather than only the major version. - **With Claude Code ACP 0.88.0 and later, a running Monitor no longer shows in the background task strip**, so it can't be stopped from there. - **Generative UI is off by default**: agents get the json-render skill in conversations started after you turn it on, turning it off removes the skill from every agent, and a json-render skill of your own is never replaced. - **A tab restored behind another shows a brief loading state the first time you switch to it**, while its conversation loads. - **The terminal panel comes back after a page reload but not after codeg itself restarts**, since a restart ends the terminals' processes and their tabs then report the session as unavailable. Thanks to @sumanx, @ker2xu, @Adam-Dalloul, @Liang-HZ, @dawNotPoi, @eyjohn, @Jonathan-Asher, @Sma1lboy and @Flyneen for contributing to this release, and to @kekxv, @toptiersnowman, @andrehqh, @Luis-WowApps and @trueai-org for the reports. ----------------------------- # 发布版本 0.35.0 这一版让智能体的回复不止是文字:打开「生成式界面」后,回复里可以直接出现卡片、表格等可交互的组件。聊天区域可以拖动边缘调宽,动画可以关闭,旁边开着文件时会话也能最大化。Claude Code 升级到 0.89.1,Codex 升级到 2.2.2,另有五个内置智能体更新了版本。 同期还有:刷新页面后终端面板会原样回来,标签页很多的工作区打开快多了,远端工作区断网后会一直重连、服务器离线时也能照常恢复窗口,「打开文件夹」对话框可以新建文件夹,回合失败时末尾会用一行文字说明原因。 ## 新增 - **智能体可以用交互式卡片和表格来回复了**——在「设置 → 技能包 → 界面」里打开「启用 json-render 生成式界面」后,用 `/json-render`(Codex 里是 `$json-render`)开头提问,或者直接让它用卡片、表格来展示,回复就会在输出过程中渲染成可交互的组件。 - **聊天区域的宽度可以调整了**——拖动会话列的左右边缘,或在「设置 → 外观 → 聊天区域宽度」里设置,双击边缘即可恢复默认宽度。(#911,@sumanx) - **聊天区域动画可以关闭了**——在「设置 → 外观」里关掉后,会话里的展开收起、工作状态提示和滚动都会立即完成,只有转圈图标照常转动。(#911,@sumanx) - **旁边开着文件时,会话也能最大化了**——点会话标签栏最右侧的「最大化」,会话就会占满中间区域,点「还原」后文件原样回来。 - **「打开文件夹」对话框里可以新建文件夹了**,建好后直接进入,方便从一个空文件夹开始新项目,桌面版和网页版都支持。(#881,@Jonathan-Asher) - **远端工作区窗口可以直接打开本地工作区了**——入口在状态栏的「快捷操作」、macOS 的 Window 菜单,以及连接失败或过期时显示的页面上。(#891,@ker2xu) ## 改进 - **内置智能体版本更新:** Claude Code ACP 0.89.1(Claude Code 2.1.293)、Codex ACP 2.2.2(Codex CLI 0.160.1)、Cline 3.0.70、CodeBuddy 2.164.0、Grok 1.0.51、Qoder 1.1.67、Hermes 0.21.6。 - **回合失败时,末尾会用一行浅色文字给出智能体自己的报错**,Codex、Claude Code、Cline 和 Qoder 的会话都支持,实时能看到,重新打开会话后也还在。 - **开着很多标签页的工作区打开得快多了**——挡在其他标签页后面的标签页,要等你第一次切过去时才加载会话,不再一打开就把每个标签页的会话都下载一遍。(#913,@Flyneen) - **调整窗口大小更流畅了**,工作区不再在每一步缩放时额外做整页布局。(#898,@sumanx) - **斜杠命令会显示它接受的参数**,`/` 菜单、输入框的「添加」菜单和自动化编辑器里都能看到。 - **Codex 的 `/mcp` 会列出每个 MCP 服务器的实时状态**,`/mcp reconnect` 也能直接在会话里用。 - **Claude Code 的 Agent 卡片会在模型旁边显示子智能体被指定的思考强度。** - **Claude Code 设置和模型供应商对话框里推荐的 Haiku 模型改为 Claude Haiku 5.5。** - **在手机上使用网页版时,浏览器顶栏和 Android 导航栏会跟随浅色或深色主题**,添加到主屏幕会安装成独立应用,图标铺满不带白边,部署在登录代理后面也能正常安装。(#863,@eyjohn) ## 修复 - **刷新页面或重新连接后,终端面板不再丢失**——标签页会带着仍在运行的命令和已有输出回来,命令结束后的输出也会一直保留到你关闭它的标签页。(#830,@dawNotPoi;#749 由 @kekxv 反馈) - **Claude Code 不会再让会话一直转圈好几个小时**——它自己发起回合时(比如后台任务结束后)你发的消息,现在会得到一次回复并正常结束。(#893 由 @Luis-WowApps 反馈) - **Claude Code 还在生成工具调用时发送消息,不会再让回合失败。** - **Claude Code 回合进行中发送的消息会保留在历史记录里**,回合中途完成的后台任务在历史里也会显示结果,不再像是没有完成。 - **Claude Code 会话的标题不会再来回切换了**——Claude Code 生成不了标题时(比如网关拒绝了生成标题的请求),侧栏和消息渠道里绑定的话题以前会在第一条和最新一条消息之间反复变化。 - **自定义智能体自己发起的回合,回复在刷新后也会留在会话里**,比如后台任务完成后它自动开始的回合,不再只在实时显示时才能看到。(#903 由 @andrehqh 反馈) - **运行 Claude Code ACP 适配器的自定义智能体,插入当前回合的消息现在会直接送进回合**,和内置的 Claude Code 一样,这些消息也会保留在历史记录里。(#892 由 @andrehqh 反馈) - **远端工作区断网后会一直尝试重连**,重连期间会给出提示,不再连续失败三次就放弃并把连接显示成已过期,现在只有服务器拒绝令牌时才会显示过期。(#887、#890,@ker2xu) - **服务器离线时,远端工作区窗口在下次启动时也会照常恢复**,等服务器恢复后原地接着用。(#887、#890,@ker2xu) - **在 macOS 上点击程序坞图标,会切到你最近用过的工作区**,最小化的远端工作区也会还原,不再总是拉出本地窗口,Windows 和 Linux 上再次启动 codeg 也是这样。(#887、#889,@ker2xu) - **ACP 注册表里的自定义智能体在 Windows 上能正常安装了**——以前大多数二进制条目会去找 `kilo.exe.exe` 这样多了一层 `.exe` 的文件,直接以可执行文件而非压缩包发布的智能体现在也能安装。(#905 由 @trueai-org 反馈) - **用官方安装器装在 `~/.local/bin` 里的智能体(比如 Hermes),不从终端启动 codeg 时也能被找到**,不再显示为未安装。(#888,@Sma1lboy;#875 由 @toptiersnowman 反馈) - **你自己安装的 OpenCode 2.x 现在能连上了**,codeg 不再给它传 `acp` 命令不接受的 `--port` 和 `--hostname` 参数。(#909,@Liang-HZ) - **Effort 选项现在跟随你选的模型**——「设置 → 协作」的「子智能体配置」以及待办任务和自动化编辑器里都是如此,不再按智能体默认模型列出。(#910,@Liang-HZ) - **回复输出过程中向上滚动,不会再被拽回底部**,无论是在代码块上滚动滚轮,还是用触摸、键盘或拖动滚动条。(#899,@Adam-Dalloul) - **调整会话标签顺序后,标签页的聊天记录不会再一片空白、要滚动一下才出现。**(#901,@Adam-Dalloul) - **已发送消息里的 `/词` 或 `$词`,只有确实是智能体提供的命令或技能时才显示成命令**,`/tmp` 这样的路径会保持普通文字。(#902,@Adam-Dalloul) - **展开或收起侧栏时,顶部标签栏不会再先被挤压再弹回。**(#912,@sumanx) - **调整窗口大小时,侧栏、右侧面板和终端面板不会再来回抖动。**(#897,@sumanx) - **收起思考块或工具卡片时不会再闪现一帧内容**,在会话里点击后按 Esc、复制或从别的窗口切回来,也不会再出现包住整个会话的焦点框。(#896,@sumanx) - **会话加载失败后会按逐渐拉长的间隔自动重试,最长每 30 秒一次**,报错和「重新加载」按钮一直显示,不再不停地重复请求、报错一闪一闪。 - **后台同步或更早的消息恰好在会话加载期间到达时,会话不会再一直停在加载中。** - **Token 用量统计更准确了**——Codex 不再把写入缓存的部分算作新输入,已有的 Codex 会话会重新统计,CodeBuddy 的总量也补上了以工具调用结束的请求。 - **Cline 的历史记录不再显示 Cline 标记为内部的消息**,比如压缩摘要、钩子上下文,以及你批准切换到 Act 模式后它自己发出的提示。 - **从历史记录打开的 Claude Code 会话,原生支持 1M 上下文的模型会显示 1M 上下文窗口**,比如 Opus 4.7 及以后、Sonnet 5 及以后、Haiku 5.5、Fable 和 Mythos,不再显示 200K。 - **备份现在包含 Codex 的会话名称**,恢复时会把 Codex 和 Kimi 的会话列表与现有内容合并,而不是跳过或整个覆盖,恢复的会话能保留名称和所在文件夹。 - **在 macOS 上,智能体在 Chromium 或 Electron 应用里输入文字并要求提交时,电脑操作会在输入后按下回车**,不再因为输入框读回为空而判定输入失败。 - **桌面版无论以什么方式启动,日志都写到同一个文件夹**,「设置 → 运行日志」打开的就是正在写入的文件夹,并显示每个文件的当前大小。(#893 由 @Luis-WowApps 反馈) ## 注意 - **Codex ACP 2.2 需要 Node.js 20.3.0 或更高版本**,在 Node.js 20.0 到 20.2 上每条消息都会失败,环境诊断现在也会按每个智能体要求的完整 Node.js 版本检查,不再只看主版本号。 - **从 Claude Code ACP 0.88.0 起,运行中的 Monitor 不再出现在后台任务条里**,也就无法在那里停止它。 - **生成式界面默认关闭**——打开后新开始的会话才会带上 json-render 技能,关闭时会从所有智能体移除该技能,你自己的同名 json-render 技能不会被替换。 - **挡在其他标签页后面恢复的标签页,第一次切过去时会短暂显示加载中**,等会话内容加载完成。 - **终端面板能在刷新页面后恢复,但 codeg 本身重启后不能**,重启会结束终端里的进程,对应的标签页会显示终端会话不可用。 感谢 @sumanx、@ker2xu、@Adam-Dalloul、@Liang-HZ、@dawNotPoi、@eyjohn、@Jonathan-Asher、@Sma1lboy 和 @Flyneen 为本次发布做出的贡献,也感谢 @kekxv、@toptiersnowman、@andrehqh、@Luis-WowApps 和 @trueai-org 的反馈。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What / 改动内容
Two small, independent UI glitches (one commit each):
fix(ui)– collapsible content flashes on collapse.tw-animate-css'sanimate-outruns withanimation-fill-mode: none, so the moment the exit animation ends the content snaps back to its resting style (full opacity, no slide). The unmount only landed in a later task, after that frame had painted, so every collapse showed one fully visible frame of the content that was just folded away. Now the exit's last keyframe is held (animation-fill-mode: forwards) until the node is removed, and the node is removed synchronously from theanimationendhandler so it is gone before the next paint. A reopen during the exit restores the node's own fill mode. Affects every user ofui/instant-collapsible(reasoning blocks, tool groups, tool cards, …).fix(chat)– transcript focus ring comes back after a click. Follow-up to fix(messages): hide pointer-triggered focus ring #338. Clicking the transcript setsdata-focus-origin="pointer"on the scroll viewport so thefocus-visiblering stays off, but the marker was dropped while the viewport was still focused:keydown, so any key (Esc included) brought the ring back — a key press makes the browser match:focus-visible;blur, which also fires when the whole window loses focus. The viewport stays the document's active element and the browser re-focuses it when the window returns (e.g. when resizing it), now without the marker.The
keydownlistener is gone, and onblurwe wait for it to settle and only clear the marker if the viewport is really no longer the active element. Tabbing into the viewport still shows the ring (that focus never sets the marker).Testing / 测试
pnpm lint .,pnpm test(560 files / 8391 tests) andpnpm buildpass.virtualized-message-thread.test.tsx: the old "keyboard input clears the marker" case now asserts the opposite, plus new cases for "focus really moves away → marker cleared" and "window blur only → marker kept".中文说明
两个互相独立的小问题,各一个提交:
fix(ui):折叠块收起时闪一帧。tw-animate-css的animate-out的animation-fill-mode为none,退出动画一结束,内容就会回到静止样式(完全不透明、无位移),而卸载发生在之后的任务里,那一帧已经绘制出来,所以每次收起都会多显示一帧刚折叠的内容。现在让动画停在最后一帧(forwards),并在animationend里同步卸载节点,保证下一次绘制前内容已被移除;动画途中重新展开时会还原节点自己的 fill-mode。所有使用ui/instant-collapsible的地方(思考块、工具组、工具卡片等)都受益。fix(chat):点击聊天记录后焦点框又出现。 是 fix(messages): hide pointer-triggered focus ring #338 的后续。点击聊天记录会给滚动容器打上data-focus-origin="pointer"来隐藏focus-visible焦点框,但容器仍有焦点时这个标记被清掉了:keydown时清除:任何按键(包括 Esc)都会让浏览器匹配:focus-visible,焦点框随之出现;blur时清除:整个窗口失去焦点(切到别的应用)也会触发 blur,但容器仍是当前焦点元素,窗口回到前台(例如拖动调整窗口大小)时浏览器会把焦点还给它,此时标记已经没了。现在去掉了
keydown监听,blur时等事件稳定后再判断,只有容器确实不再是焦点元素才清除标记。用 Tab 键切入时仍然显示焦点框(那种焦点不会设置标记)。测试:
pnpm lint .、pnpm test(560 个文件 / 8391 个用例)、pnpm build均通过;相关单元测试已更新并新增用例。焦点框问题在浏览器和桌面端手动验证过(点击后按 Esc、点击后切换应用再调整窗口大小);折叠闪烁是依据上述动画分析修复的,没有采集修复前后的逐帧数据。仅在 Linux(GNOME / Wayland、WebKitGTK 桌面版和 Chrome)测试,未在 macOS、Windows 上试过。🤖 Generated with Claude Code