Skip to content

Refactor the item shortcut bar and add a new item warehouse management panel.#1600

Open
ErrorAP717 wants to merge 28 commits into
Project-N-E-K-O:mainfrom
ErrorAP717:tools
Open

Refactor the item shortcut bar and add a new item warehouse management panel.#1600
ErrorAP717 wants to merge 28 commits into
Project-N-E-K-O:mainfrom
ErrorAP717:tools

Conversation

@ErrorAP717
Copy link
Copy Markdown
Contributor

@ErrorAP717 ErrorAP717 commented Jun 2, 2026

优化 N.E.K.O 聊天窗口中的道具交互体验。将原有的放射状轮盘布局重构为更清爽的“水平胶囊快捷栏”,并引入了独立的“道具仓库管理面板”,实现了快捷释放与道具配置的逻辑解耦,为后续扩充更多交互道具奠定基础。

Summary by CodeRabbit

  • 新功能

    • 新增头像工具快捷栏与管理器:最多保存 3 个工具,支持拖拽排序、库中添加/移除、点击切换与清除,编辑可打开管理弹层并锚定触发位置。
  • 可访问性

    • 统一入口 aria 文案;管理对话框支持键盘 Tab 循环、焦点保存/回退与可通过按键/按钮关闭。
  • 本地化

    • 为多语言(中/英/日/韩/西/葡/俄等)新增头像工具相关文案。
  • 样式

    • 快捷栏与管理器视觉、响应式、暗色主题与拖拽幽灵优化;紧凑模式锚定与定位调整。
  • 测试

    • 补充交互与回归测试,覆盖快捷栏、管理器、持久化与资源版本化加载行为。
  • 维护

    • 引入专用前端资源版本并在头像工具相关资源 URL 上追加版本查询参数。

ErrorAP717 and others added 11 commits May 29, 2026 13:08
- 解除道具菜单图标在暗色模式下被全局滤镜压暗的问题
- 将 PNG 图标置于气泡高光层之上,并保留原始图像透明度
- 移除额外白色光晕,仅保留暗色气泡上的原始 PNG 呈现
新增头像道具快捷栏与管理器组件,抽离道具配置和图片解析逻辑。\n\n接入紧凑聊天输入轮盘,支持快捷道具选择、取消、保存到本地存储,并在已选道具被移除时清理当前光标状态。
补齐头像快捷栏和道具管理弹窗的明暗主题、移动端与低动效样式。\n\n同步新增 8 个语言包中的头像道具管理文案,保证可访问标签和界面文字都有 locale key。
更新紧凑聊天头像道具相关断言,适配快捷栏替代旧工具气泡的交互。\n\n新增管理弹窗定位和拖动测试,并补充选择、取消与恢复鼠标状态的回归覆盖。
新增项目级交接说明,沉淀长期约束、验证方式、提交边界和常见任务处理原则。\n\n文档与头像道具功能提交分离,方便后续审阅或单独回退。
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 17135c2e-d4d3-4cce-a53a-f462a8eba37d

📥 Commits

Reviewing files that changed from the base of the PR and between 58face7 and 942cb87.

📒 Files selected for processing (1)
  • frontend/react-neko-chat/src/styles.css
💤 Files with no reviewable changes (1)
  • frontend/react-neko-chat/src/styles.css

Walkthrough

在聊天界面新增 Avatar Tools:类型与资源解析、Quickbar、Manager 对话框、App 集成与持久化、样式、八语种 i18n、模板版本化与前端/回归测试覆盖喵。

Changes

头像工具快捷管理系统

Layer / File(s) Summary
头像工具类型系统与资源解析
frontend/react-neko-chat/src/avatarTools.ts
定义类型/常量、AVAILABLE_AVATAR_TOOLS、版本追加、ID 清洗、localStorage 读写、按 CursorVariant 解析图标/光标/菜单视觉(withAvatarToolAssetVersion / resolveAvatarToolImagePaths / resolveAvatarToolMenuIconVisual)。
头像快捷工具栏组件
frontend/react-neko-chat/src/AvatarToolQuickbar.tsx
新增 AvatarToolQuickbar:基于 activeToolIds 渲染图标按钮(ARIA/disabled/active)、空态文案与“编辑”入口,图标使用版本化路径。
头像工具管理器对话框
frontend/react-neko-chat/src/AvatarToolItemManager.tsx
新增 Manager:portal 挂载、anchorRect 定位(向下优先/回退向上)、视口裁剪、draftSlots、拖拽会话(pointer capture、幽灵图)、点击装入与槽位移动/移除、标题栏拖拽与焦点陷阱、保存/取消回调。
App 集成:状态与交互
frontend/react-neko-chat/src/App.tsx
新增 activeAvatarToolIds / avatarToolManagerOpen / avatarToolManagerAnchorRect 状态;实现 quickbar 点击处理、manager 保存(sanitize+persist)、资源上报版本包装;在非紧凑面时自动关闭 manager。
App 集成:渲染与联动
frontend/react-neko-chat/src/App.tsx
isCompactSurface 条件渲染 Quickbar 与 Manager;扩展 compactCursorZoneSelector 命中范围;统一工具入口 aria 文案并调整菜单/扇面联动与外部点击判定。
样式与主题适配
frontend/react-neko-chat/src/styles.css
新增 quickbar 与 manager 全套样式(容器、按钮态、拖拽幽灵、三列网格、响应式 ≤640/380px)、暗色覆盖与 prefers-reduced-motion 支持。
前端测试更新
frontend/react-neko-chat/src/App.test.tsx
更新/新增测试:localStorage 清理、入口从 Emoji 改为 Avatar tools、quickbar/manager 挂载与锚定断言、manager 拖拽定位与焦点陷阱、选择/取消激活断言、version query 校验、overlay 与宿主联动等。
多语言文案
static/locales/*.json(en/es/ja/ko/pt/ru/zh-CN/zh-TW)
在多语言文件中新增 avatar tools 相关键(入口 aria、quickbar 空/编辑、manager 标题/副标题/按钮、槽位提示、装备/移除/保存等)。
模板与版本跟踪
templates/index.html, templates/chat.html, main_routers/pages_router.py, static/app-react-chat-window.js
注入 window.__NEKO_REACT_CHAT_ASSET_VERSION__,将 React Chat 脚本/CSS 的 ?v= 切换至 react_chat_asset_version;将头像图标纳入 react_chat_asset_version 跟踪;compact 几何收集加入 quickbar 按钮并特殊处理 manager dialog。
回归测试
tests/test_agent_rewrite_regression.py
新增两项测试:验证模板使用 react_chat_asset_version,验证 pages_router 将头像工具图标纳入 React Chat 资产版本跟踪。

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~60 分钟

Possibly related PRs:

Sequence Diagram (high-level flow):

sequenceDiagram
  participant User
  participant App
  participant AvatarToolQuickbar
  participant AvatarToolItemManager
  participant LocalStorage
  User->>App: 点击 "Avatar tools" 打开 quickbar / 管理器入口
  App->>AvatarToolQuickbar: 渲染 activeToolIds 与按钮交互绑定
  AvatarToolQuickbar->>App: onEditClick -> 提供 anchorRect 并 open 管理器
  App->>AvatarToolItemManager: open with anchorRect / activeToolIds
  AvatarToolItemManager->>LocalStorage: onSave -> compactSlots -> persistActiveAvatarToolIds()
  AvatarToolItemManager->>App: onSave 回传已保存 ids (关闭 dialog)
Loading

"喵~新工具装上去喵,快捷栏闪闪亮喵,
拖拽换槽像玩具喵,保存记录不会忘喵,
版本带上小尾巴喵,模板也跟着走喵,
八国语言都准备好喵,测试也把路跑通喵,
快去试一试新花样,不要让我等太久喵~"

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 标题准确概括了主要变更:重构道具快捷条与新增道具管理面板,与文件变更内容高度匹配喵。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agent/project-handoff-notes.md:
- Around line 215-216: 当前文档中关于“无需确认直接执行”与“高风险场景需确认/补证据”存在冲突;请把执行策略统一为“默认直执行 +
风险场景强制确认”,并在本段明确添加一条例外白名单和一条优先级说明(例如“当触及高风险场景时,必须遵循强制确认规则并覆盖默认直执行”),同时在文档其他出现同类表述的位置(与本段语义等价的段落)同步替换为同一表述以避免分叉。确保描述包含如何判定“高风险场景”(简短示例或引用标准)和确认流程的最小步骤,以便实现一致行为。
- Around line 224-230: The rule that ".agent 内的文件都不提交" conflicts with this PR;
update .agent/project-handoff-notes.md to add a clear exception: introduce a new
clause (e.g., after rule 1) stating
"项目级基线文档可在明确批准下入库,需单独提交并在提交信息中注明审批单号/批准人",and modify rules 1-3 to reference this
exception (keep default: all other .agent/* not committed). Ensure the exception
requires explicit approval, a separate commit with clear title, and confirmation
that .agent/notes/ remains unstaged before pushing.

In `@frontend/react-neko-chat/src/App.test.tsx`:
- Around line 3219-3298: The tests mutate avatar-tool persistence in
localStorage but the shared beforeEach only clears the export-history key;
update the shared test setup beforeEach to also clear the avatar tool storage
keys by importing the exported key constants from avatarTools.ts (e.g. the
module's exported storage key constants) and calling localStorage.removeItem for
each (and/or localStorage.clear if appropriate) so tests like the default slot
assertions and initial aria-pressed checks are isolated and deterministic.

In `@frontend/react-neko-chat/src/App.tsx`:
- Around line 4468-4475: The AvatarToolItemManager can reopen unexpectedly
because you only gate its open prop with isCompactSurface &&
avatarToolManagerOpen but never reset avatarToolManagerOpen when the host leaves
compact surface; add logic to close/reset the manager whenever isCompactSurface
becomes false (for example in a useEffect that watches isCompactSurface) by
calling setAvatarToolManagerOpen(false) so avatarToolManagerOpen is cleared when
the surface is not compact; update references to AvatarToolItemManager,
isCompactSurface, avatarToolManagerOpen, and setAvatarToolManagerOpen
accordingly.

In `@frontend/react-neko-chat/src/AvatarToolItemManager.tsx`:
- Around line 199-247: When the AvatarToolItemManager dialog opens it does not
take focus and on close it does not restore focus to the trigger, causing
keyboard users to tab into background content; fix this by adding focus
management: inside AvatarToolItemManager create a ref to store the previously
focused element (e.g. prevActiveElementRef), then in an effect that watches open
save document.activeElement into that ref when opening, move focus into the
dialog (use dialogRef.current and focus the first focusable element or the
dialog container), and when open becomes false restore focus to
prevActiveElementRef.current; also add a keydown handler on the dialog (attached
to dialogRef) to trap Tab cycling within dialogRef when open so Tab/Shift+Tab do
not escape to the page. Ensure cleanup removes the keydown listener and does not
run when typeof window === 'undefined'.

In `@frontend/react-neko-chat/src/styles.css`:
- Around line 3855-3864: The CSS sets touch-action: none on the whole draggable
header (.avatar-tool-manager-header) which prevents native vertical scrolling
inside the scrollable panel (.avatar-tool-manager-body); change the approach so
the default CSS uses touch-action: pan-y (or remove touch-action) on the
header/cards and only set touch-action: none when a real drag session starts (or
restrict the drag to a smaller dedicated handle class instead of the entire
header/card); update the styles for .avatar-tool-manager-header and any card
classes and add a short JS toggle in the drag start/stop handlers to
apply/remove a "dragging" class that flips touch-action to none during active
dragging.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: db97845e-93af-4daf-8735-bed48daabaca

📥 Commits

Reviewing files that changed from the base of the PR and between 93c4562 and 45bdb6a.

⛔ Files ignored due to path filters (1)
  • static/icons/edit_tool_unified.png is excluded by !**/*.png
📒 Files selected for processing (15)
  • .agent/project-handoff-notes.md
  • frontend/react-neko-chat/src/App.test.tsx
  • frontend/react-neko-chat/src/App.tsx
  • frontend/react-neko-chat/src/AvatarToolItemManager.tsx
  • frontend/react-neko-chat/src/AvatarToolQuickbar.tsx
  • frontend/react-neko-chat/src/avatarTools.ts
  • frontend/react-neko-chat/src/styles.css
  • static/locales/en.json
  • static/locales/es.json
  • static/locales/ja.json
  • static/locales/ko.json
  • static/locales/pt.json
  • static/locales/ru.json
  • static/locales/zh-CN.json
  • static/locales/zh-TW.json

Comment thread .agent/project-handoff-notes.md Outdated
Comment thread .agent/project-handoff-notes.md Outdated
Comment thread frontend/react-neko-chat/src/App.test.tsx
Comment thread frontend/react-neko-chat/src/App.tsx
Comment thread frontend/react-neko-chat/src/AvatarToolItemManager.tsx
Comment thread frontend/react-neko-chat/src/styles.css
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a2c4410e6f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .agent/project-handoff-notes.md Outdated

## 提交与工作区

1. 用户明确要求:`.agent` 内的文件都不提交。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove committed .agent handoff notes

This commit adds .agent/project-handoff-notes.md to version control even though the added project instructions state that .agent files are working memory and must not be committed. Keeping this file in the feature commit leaks transient workflow notes and violates the repo's own submission boundary, so it should be removed from the commit and left untracked unless explicitly requested separately.

Useful? React with 👍 / 👎.

Comment on lines +86 to +88
<img
className="avatar-tool-quickbar-edit-image"
src="/static/icons/edit_tool_unified.png"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Downscale oversized quickbar edit icon

This quickbar button loads /static/icons/edit_tool_unified.png; I checked the committed PNG and it is 2,282×1,856 pixels and about 3.25 MB, while the CSS displays it at only 52×43 px. Any user who opens the avatar tools pays the download and decode cost for a multi-megabyte image on a tiny button, which is avoidable latency and memory pressure, especially on mobile or slower connections; please replace it with a resized/compressed asset.

Useful? React with 👍 / 👎.

… test isolation, docs)

包含焦点陷阱、touch-action、测试隔离和项目基线文档规则修复。批准人:用户本轮明确要求提交。
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agent/project-handoff-notes.md:
- Line 208: 将高风险判定条目中语句“非代码任务要把产物保存到仓库路径”替换为更通顺的“会把产物保存到仓库路径”;定位该更改在
.agent/project-handoff-notes.md
文件中包含“高风险场景判定:任一命中即视为高风险……”的那一行,直接将原短语替换为“会把产物保存到仓库路径”以消除歧义并保持句子结构一致。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c5c16f24-6a0b-49d8-967c-d0c19d1d5b2c

📥 Commits

Reviewing files that changed from the base of the PR and between 45bdb6a and 6559c88.

📒 Files selected for processing (5)
  • .agent/project-handoff-notes.md
  • frontend/react-neko-chat/src/App.test.tsx
  • frontend/react-neko-chat/src/App.tsx
  • frontend/react-neko-chat/src/AvatarToolItemManager.tsx
  • frontend/react-neko-chat/src/styles.css
🚧 Files skipped from review as they are similar to previous changes (4)
  • frontend/react-neko-chat/src/styles.css
  • frontend/react-neko-chat/src/AvatarToolItemManager.tsx
  • frontend/react-neko-chat/src/App.tsx
  • frontend/react-neko-chat/src/App.test.tsx

Comment thread .agent/project-handoff-notes.md Outdated
解决 App.tsx 清理逻辑冲突,同时保留 setToolMenuOpen(false) 与 compact fan dispatch 清理逻辑。
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 41791ba16f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +502 to +504
return createPortal(
<div
className="avatar-tool-manager-overlay"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop manager clicks from unmounting the opener

Because this manager is portaled to document.body, a real mouse interaction inside the dialog fires mousedown outside both toolMenuRef and compactInputToolFanRef, so App.tsx's outside-click listener closes toolMenuOpen before the dialog's button click runs. That unmounts the quickbar/edit opener, so the cleanup that tries to restore focus to the previous element after Save/Close has no element to focus and leaves focus on the document body; the existing focus-restore test uses fireEvent.click only, so it misses the browser mousedown ordering. Exclude the manager overlay from that outside-click close path or stop the overlay/dialog mousedown from reaching it.

Useful? React with 👍 / 👎.

将高风险判定中的产物保存描述改为更通顺的一致句式。批准人:用户本轮明确要求提交并推送。
Integrate upstream changes: compact preview grapheme animation,
tool popover CSS class refactor, and active-state attribute ordering.
Keep avatar-tool-quickbar IDs from tools branch.
…ement

- Add react_chat_asset_version to template script/css tags for
  cache-busting avatar tool icons independently of static_asset_version
- Register icon assets in _REACT_CHAT_ASSET_VERSION_PATHS
- Expose withAvatarToolAssetVersion() and wire it into active tool
  image path resolution
- Refactor AvatarToolItemManager drag/drop layout and positioning
- Expand test coverage for quickbar and manager interactions
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
static/app-react-chat-window.js (1)

1274-1279: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

avatar-tool-manager-dialog 被反向放行进 compact 几何收集了喵

这里的条件是“根外元素白名单”,当前把 .avatar-tool-manager-dialog 加进了白名单,结果是它会被继续收集,而不是被排除;这和本 PR 的目标(manager dialog 不参与 compact geometry)相反喵。建议显式早退排除它喵。

建议修复(最小改动)
         return elements.reduce(function (items, element) {
             if (
                 !root.contains(element)
                 && !element.classList.contains('compact-input-tool-fan')
-                && !element.classList.contains('compact-chat-choice-anchor')
-                && !element.classList.contains('avatar-tool-manager-dialog')
+                && !element.classList.contains('compact-chat-choice-anchor')
             ) return items;
+            if (element.classList.contains('avatar-tool-manager-dialog')) return items;
             if (!shouldIncludeCompactGeometryElement(element)) return items;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@static/app-react-chat-window.js` around lines 1274 - 1279, The current
whitelist check wrongly allows elements with class 'avatar-tool-manager-dialog'
into the compact geometry collection (the conditional using
root.contains(element) and element.classList.contains(...)), so change the logic
to explicitly exclude that dialog: add an early-return when
element.classList.contains('avatar-tool-manager-dialog') so it returns items
(skipping collection) before the whitelist check; keep other class checks and
the root.contains(element) behavior intact.
🧹 Nitpick comments (4)
frontend/react-neko-chat/src/App.test.tsx (1)

3-7: ⚡ Quick win

让这组回归断言再“脱离实现”一点喵

Line 632-639 和 Line 680-690 直接复用了 computeCompactHistoryEnterDelay/ExitDelay,一旦 helper 自己算错,组件和测试会一起假绿;同时 Line 4158-4175 现在只钉住了 quickbar/manager 的静态图,avatarTools.ts 里同样会走版本包装的激活态 cursor/overlay 路径还没被覆盖到。这里更稳的是:delay 断言改成固定期望值,版本号用例里再激活一个工具,顺手把 overlay 或 tool.cursorImagePath?v= 也一起钉住喵。

Also applies to: 631-639, 680-690, 4158-4175

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/react-neko-chat/src/App.test.tsx` around lines 3 - 7, 当前测试复用
computeCompactHistoryEnterDelay / computeCompactHistoryExitDelay 导致实现与测试耦合且漏掉
avatarTools.ts 的版本化路径;请将对延迟的断言改为使用固定期望值(直接断言组件中使用的毫秒常量,而不是调用
computeCompactHistoryEnterDelay/computeCompactHistoryExitDelay),并在版本号相关用例中激活一个额外工具(通过
quickbar/manager 激活路径)以覆盖 avatarTools.ts 的版本化激活分支,顺便将 overlay 或
tool.cursorImagePath 的 URL 中的 ?v= 查询参数也固定断言(钉住具体期望的版本后缀)以防止假绿。
frontend/react-neko-chat/src/styles.css (3)

3556-3566: ⚖️ Poor tradeoff

emoji 按钮样式覆盖有点多喵?

这里用了三条规则把 .compact-input-tool-fan 里的 emoji 按钮背景都设成透明喵。虽然功能上没问题,但感觉像是在和上游的 .composer-emoji-btn 样式"打架"喵~

可以考虑:

  • 要么在 avatar item 上加个更具体的 class
  • 要么调整一下选择器优先级

不过现在这样写确实很明确,维护起来也清楚喵。就当我随口提一嘴啦~ 😺

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/react-neko-chat/src/styles.css` around lines 3556 - 3566, The CSS
rule overly overrides upstream .composer-emoji-btn styles by blanket-targeting
.compact-input-tool-fan .compact-input-tool-item-avatar > .composer-emoji-btn;
to fix, narrow the scope—either add a dedicated modifier class to the avatar
wrapper (e.g., .compact-input-tool-item-avatar--avatar-override) and change the
rule to target that modifier together with .composer-emoji-btn, or reduce
selector specificity by targeting only the exact state you need (e.g., the
avatar modifier or a more specific descendant) so you stop clobbering global
.composer-emoji-btn styles; update the stylesheet selectors
(.compact-input-tool-fan, .compact-input-tool-item-avatar, .composer-emoji-btn)
accordingly.

2899-2927: ⚖️ Poor tradeoff

呼吸动画滤镜开销可能较高喵~

这里的 compact-history-handle-breathecompact-history-handle-glow-breathe 关键帧用了 drop-shadow()blur() 滤镜配合 infinite 动画循环喵。在一些低端设备上连续跑滤镜动画可能会有点卡顿喵。

如果追求极致性能,可以考虑把滤镜效果烘焙到静态图片里,然后只用 opacity 做呼吸动画喵。不过现在这个视觉效果确实很精致,就看主人你更看重哪边啦喵~ ✨

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/react-neko-chat/src/styles.css` around lines 2899 - 2927, The
keyframe animations compact-history-handle-breathe and
compact-history-handle-glow-breathe animate expensive CSS filters (drop-shadow)
which can cause jank on low-end devices; to fix, remove animated filter usage
and instead bake the glow/shadow into a static asset or a non-animated
pseudo-element (e.g., .compact-history-handle::before) and only animate cheap
properties like opacity and transform in those keyframes, or if you must keep a
dynamic glow, move the heavy filter to a static element and animate an overlaid
element's opacity/scale; also add will-change: opacity, transform to the
animated element and respect prefers-reduced-motion media query to disable the
breathing animation for reduced-motion users.

5145-5152: 💤 Low value

渐变定义可以考虑复用喵?

这里暗色模式的 visibility handle 光晕渐变(Lines 5145-5152)和浅色模式(Lines 2879-2886)的梯度停止点位置完全一样喵(都是 0% / 22% / 50% / 78% / 100%),只是颜色不同喵。

如果想减少重复,可以把这些百分比提取成 CSS 自定义属性喵:

--handle-glow-stops: 0%, 22%, 50%, 78%, 100%;

不过现在这样写也挺清楚的,除非以后要统一调整这些 stop 值,不然改不改都行喵~ 🎨

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/react-neko-chat/src/styles.css` around lines 5145 - 5152, The
gradient stop positions for the visibility-handle glow are duplicated between
dark and light mode; extract the shared stop percentages into a CSS custom
property (e.g., --handle-glow-stops: 0%, 22%, 50%, 78%, 100%) and then use that
variable in both gradient declarations (the current linear-gradient blocks for
the visibility handle in dark and light modes) so only the color RGBA values
differ while the stop positions are reused; update the selectors that define the
glow gradients to reference var(--handle-glow-stops).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@static/app-react-chat-window.js`:
- Around line 1274-1279: The current whitelist check wrongly allows elements
with class 'avatar-tool-manager-dialog' into the compact geometry collection
(the conditional using root.contains(element) and
element.classList.contains(...)), so change the logic to explicitly exclude that
dialog: add an early-return when
element.classList.contains('avatar-tool-manager-dialog') so it returns items
(skipping collection) before the whitelist check; keep other class checks and
the root.contains(element) behavior intact.

---

Nitpick comments:
In `@frontend/react-neko-chat/src/App.test.tsx`:
- Around line 3-7: 当前测试复用 computeCompactHistoryEnterDelay /
computeCompactHistoryExitDelay 导致实现与测试耦合且漏掉 avatarTools.ts
的版本化路径;请将对延迟的断言改为使用固定期望值(直接断言组件中使用的毫秒常量,而不是调用
computeCompactHistoryEnterDelay/computeCompactHistoryExitDelay),并在版本号相关用例中激活一个额外工具(通过
quickbar/manager 激活路径)以覆盖 avatarTools.ts 的版本化激活分支,顺便将 overlay 或
tool.cursorImagePath 的 URL 中的 ?v= 查询参数也固定断言(钉住具体期望的版本后缀)以防止假绿。

In `@frontend/react-neko-chat/src/styles.css`:
- Around line 3556-3566: The CSS rule overly overrides upstream
.composer-emoji-btn styles by blanket-targeting .compact-input-tool-fan
.compact-input-tool-item-avatar > .composer-emoji-btn; to fix, narrow the
scope—either add a dedicated modifier class to the avatar wrapper (e.g.,
.compact-input-tool-item-avatar--avatar-override) and change the rule to target
that modifier together with .composer-emoji-btn, or reduce selector specificity
by targeting only the exact state you need (e.g., the avatar modifier or a more
specific descendant) so you stop clobbering global .composer-emoji-btn styles;
update the stylesheet selectors (.compact-input-tool-fan,
.compact-input-tool-item-avatar, .composer-emoji-btn) accordingly.
- Around line 2899-2927: The keyframe animations compact-history-handle-breathe
and compact-history-handle-glow-breathe animate expensive CSS filters
(drop-shadow) which can cause jank on low-end devices; to fix, remove animated
filter usage and instead bake the glow/shadow into a static asset or a
non-animated pseudo-element (e.g., .compact-history-handle::before) and only
animate cheap properties like opacity and transform in those keyframes, or if
you must keep a dynamic glow, move the heavy filter to a static element and
animate an overlaid element's opacity/scale; also add will-change: opacity,
transform to the animated element and respect prefers-reduced-motion media query
to disable the breathing animation for reduced-motion users.
- Around line 5145-5152: The gradient stop positions for the visibility-handle
glow are duplicated between dark and light mode; extract the shared stop
percentages into a CSS custom property (e.g., --handle-glow-stops: 0%, 22%, 50%,
78%, 100%) and then use that variable in both gradient declarations (the current
linear-gradient blocks for the visibility handle in dark and light modes) so
only the color RGBA values differ while the stop positions are reused; update
the selectors that define the glow gradients to reference
var(--handle-glow-stops).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ab1b700-9b13-4ce9-b88d-60147989619e

📥 Commits

Reviewing files that changed from the base of the PR and between 8640ee8 and 7f543b0.

⛔ Files ignored due to path filters (1)
  • .agent/image/project-handoff-notes/1780475178015.png is excluded by !**/*.png
📒 Files selected for processing (12)
  • .agent/project-handoff-notes.md
  • frontend/react-neko-chat/src/App.test.tsx
  • frontend/react-neko-chat/src/App.tsx
  • frontend/react-neko-chat/src/AvatarToolItemManager.tsx
  • frontend/react-neko-chat/src/AvatarToolQuickbar.tsx
  • frontend/react-neko-chat/src/avatarTools.ts
  • frontend/react-neko-chat/src/styles.css
  • main_routers/pages_router.py
  • static/app-react-chat-window.js
  • templates/chat.html
  • templates/index.html
  • tests/test_agent_rewrite_regression.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • frontend/react-neko-chat/src/AvatarToolQuickbar.tsx
  • frontend/react-neko-chat/src/avatarTools.ts
  • frontend/react-neko-chat/src/AvatarToolItemManager.tsx
  • frontend/react-neko-chat/src/App.tsx

…ollection

The dialog was mistakenly added to the root-external whitelist,
causing it to be included in compact geometry. Move it to an
explicit early-return so it is always skipped regardless of
containment.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f547c120f1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +557 to +558
'.avatar-tool-quickbar',
'.avatar-tool-manager-overlay',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat the manager dialog as a compact cursor zone

When an avatar cursor tool is active and the manager opens in the anchored desktop mode, clicks and pointer moves inside the dialog are not recognized as compact UI: the only new manager selector here is the overlay, but .avatar-tool-manager-overlay.is-desktop has pointer-events: none, so elementsFromPoint/event.target.closest(...) see the dialog/buttons instead. The global cursor-tool handlers then treat manager clicks as avatar-area clicks, which can change variants or emit tool interactions while the user is just saving/removing tools; include .avatar-tool-manager-dialog in this selector as well.

Useful? React with 👍 / 👎.

…guard outside-click

- Remove .agent/project-handoff-notes.md and its image from version
  control (working memory, not meant for commits)
- Downscale edit_tool_unified.png from 2282×1856 / 3.1 MB to
  156×128 / 15 KB (3× retina of the 52×43 display size)
- Exclude avatar-tool-manager overlay/dialog from the compact
  tool-menu outside-click listener so portal interactions no longer
  close the opener and unmount the quickbar
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c622900157

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +285 to +286
if ((window as any).nekoChatWindow?.enableInteraction) {
(window as any).nekoChatWindow.enableInteraction();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Call the actual chat host when restoring interaction

When the manager opens in centered/mobile mode after the host has set document.body.style.pointerEvents = 'none', this branch never restores interaction because the repo exposes the bridge as window.reactChatWindowHost and there is no window.nekoChatWindow/enableInteraction implementation (repo-wide search only finds this reference). As a result the modal can remain non-interactive in that context despite setting the flag; use the real host API or explicitly restore the previous pointer-events value while the dialog is open.

Useful? React with 👍 / 👎.

…ents

- Add .avatar-tool-manager-dialog to compactCursorZoneSelector so
  clicks inside the manager are not misinterpreted as avatar-area
  tool interactions when a cursor tool is active
- Replace dead nekoChatWindow.enableInteraction call with direct
  document.body.style.pointerEvents restore/cleanup for centered
  mobile mode
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5dee50a72b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +109 to +111
if (eventTarget instanceof Element) {
const eventTargetSlotIndex = getDropSlotIndexFromElement(eventTarget);
if (eventTargetSlotIndex !== null) return eventTargetSlotIndex;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Hit-test captured slot drags by coordinates first

When dragging an equipped tool from one slot to another, startDrag captures the pointer on the source slot button, so the pointerup event target remains that source button even if the cursor is over a different slot. This early return therefore resolves the drop back to the original slot before elementsFromPoint() can inspect the actual coordinates, making slot-to-slot reordering a no-op in real pointer-capture interactions; skip the event-target shortcut for captured drags or prefer coordinate hit-testing.

Useful? React with 👍 / 👎.

Pointer capture keeps the pointerup target pinned to the source
slot button, so the event-target shortcut resolved every slot drag
back to its origin. Reorder to try elementsFromPoint first, falling
back to event target only when coordinate hit-test finds nothing.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2c546423b3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


useEffect(() => {
if (!open || typeof window === 'undefined') return undefined;
if (!isPositioned) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore pointer events for anchored manager too

When the manager opens in anchored/desktop mode (dialogPosition !== null, which is the default at desktop widths and in Electron), this branch skips the body pointer-events restore entirely and only dispatches a resize event. If the host has already set document.body.style.pointerEvents = 'none', the portaled dialog remains under a non-interactive body and cannot be clicked; fresh evidence is that the current code only clears/restores pointerEvents inside the !isPositioned branch, while the new test setup in App.test.tsx opens at desktop width with body pointer events disabled.

Useful? React with 👍 / 👎.

Comment on lines +40 to +42
<div
id="composer-avatar-tool-quickbar"
className="avatar-tool-quickbar"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include the quickbar in compact host geometry

In the Electron compact/minimize-ball host, static/app-react-chat-window.js builds native/hit rects for the tool fan from .compact-input-tool-item and the old .composer-icon-popover .composer-icon-button selector. This new quickbar is absolutely positioned outside the fan’s own rect but uses only .avatar-tool-quickbar, so the quick tool and edit buttons no longer contribute native hit regions; in that compact desktop context, the visible controls outside the base fan can be missed by click-through/hit testing unless the host geometry selector is updated or the quickbar keeps a collected selector.

Useful? React with 👍 / 👎.

…ometry

- Move pointer-events save/restore out of the !isPositioned branch
  so the anchored desktop manager also clears body pointer-events
  block while open
- Add .avatar-tool-quickbar .composer-icon-button to compact tool
  fan geometry selector so quickbar buttons contribute native hit
  regions in Electron compact host
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 33c0ca74e4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread static/app-react-chat-window.js Outdated
});
}
return items.concat(Array.prototype.slice.call(element.querySelectorAll('.compact-input-tool-item, .composer-icon-popover .composer-icon-button'))
return items.concat(Array.prototype.slice.call(element.querySelectorAll('.compact-input-tool-item, .composer-icon-popover .composer-icon-button, .avatar-tool-quickbar .composer-icon-button'))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the edit button to compact hit geometry

In the compact Electron/minimize-ball host, I checked collectCompactToolFanGeometryItems and this selector now adds quickbar tool buttons, but it still misses the visible edit button because AvatarToolQuickbar.tsx renders it as .avatar-tool-quickbar-edit without the composer-icon-button class. The edit control is absolutely positioned with the quickbar outside the fan's base rect, so its native/hit region is not reported and clicks on the edit button can still fall through or be ignored in that compact host context; include the edit button selector here as well.

Useful? React with 👍 / 👎.

The edit button uses .avatar-tool-quickbar-edit without the
composer-icon-button class, so the previous selector missed it.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20354616d4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

});
}
return items.concat(Array.prototype.slice.call(element.querySelectorAll('.compact-input-tool-item, .composer-icon-popover .composer-icon-button'))
return items.concat(Array.prototype.slice.call(element.querySelectorAll('.compact-input-tool-item, .composer-icon-popover .composer-icon-button, .avatar-tool-quickbar .composer-icon-button, .avatar-tool-quickbar-edit'))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the edit button from being filtered out

Fresh evidence: although this selector now includes .avatar-tool-quickbar-edit, the code immediately below still sets isAvatarToolChoice only for .composer-icon-button and then drops every non-choice without a data-compact-tool-wheel-slot, so the edit button is still filtered out before a rect is emitted. In the compact Electron/minimize-ball host, clicks on the visible edit control can therefore remain outside the reported hit/native geometry; either mark the edit button as an avatar tool choice or exempt it from the slot filter.

Useful? React with 👍 / 👎.

Comment thread static/app-react-chat-window.js Outdated
});
}
return elements.reduce(function (items, element) {
if (element.classList.contains('avatar-tool-manager-dialog')) return items;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Report the manager dialog in compact geometry

When the avatar tool manager opens in the compact minimize-ball/Electron flow, the React dialog is portaled to document.body with data-compact-geometry-owner="surface", but this early return discards it before its rect can be added to surfaceNativeRects/extraIslandNativeRects. That means the native hit/shape geometry stays tied to the old compact surface and does not include the visible manager, so the dialog can be clipped or non-interactive in the host context that consumes this geometry; include the manager as an extra island instead of skipping it.

Useful? React with 👍 / 👎.

…g as extra island

- Treat .avatar-tool-quickbar-edit as an avatar tool choice so the
  slot filter does not discard it from compact hit geometry
- Report the manager dialog as an extraIsland geometry item instead
  of skipping it entirely, so the compact host includes the dialog
  in its native/hit region
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e9b2d6d70

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

fireEvent.click(editButton);

expect(await screen.findByRole('dialog', { name: 'Manage tools' })).toBeInTheDocument();
expect(document.body.style.pointerEvents).toBe('auto');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fix the pointer-events assertion

This assertion cannot pass against the implementation in AvatarToolItemManager: when the dialog opens with document.body.style.pointerEvents === 'none', it clears the inline style to '', not 'auto'. In a CI run with the React test dependencies installed, this newly added test will fail even though the intended browser behavior may be to restore computed pointer events; either set the inline style to auto while open or assert the computed style instead.

Useful? React with 👍 / 👎.

…interactive flag

- Fix test expecting 'auto' when implementation clears to '' (empty string)
- Remove unused __nekoForceInteractive window flag that no code reads
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b31a2337f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread frontend/react-neko-chat/src/App.tsx Outdated
Comment on lines 1756 to 1757
const emojiButtonAriaLabel = i18n('chat.emojiButtonAriaLabel', 'Emoji');
const toolIconsAriaLabel = i18n('chat.toolIconsAriaLabel', 'Tool icons');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the unused avatar label constants

With noUnusedLocals enabled in frontend/react-neko-chat/tsconfig.app.json, these two constants are now unreferenced after the quickbar refactor removed selectedEmojiButtonAriaLabel and the old tool-icons group label. In any build/typecheck run, TypeScript reports TS6133 for them and blocks the React chat bundle; either delete the constants or wire them into the new UI.

Useful? React with 👍 / 👎.

emojiButtonAriaLabel and toolIconsAriaLabel were left over from the
quickbar refactor and never referenced — TS6133 blocked the build.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 58face790d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread frontend/react-neko-chat/src/styles.css Outdated
Comment on lines +4412 to +4415
.avatar-tool-manager-dialog.is-positioned {
position: relative;
left: auto;
top: auto;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve fixed positioning for Electron tool manager

In the Electron compact chat context with a viewport at or below 640px, resolveAnchoredDialogPosition still returns a non-null position because isElectronDesktopEnvironment() bypasses the mobile fallback, so the dialog gets is-positioned. This media rule then changes that same positioned dialog to normal-flow position: relative and discards the computed left/top; because the portal is appended after the app root, the manager can render below/off the compact window instead of anchored to the edit button. Scope this override to non-Electron/mobile mode or keep the fixed coordinates when is-positioned is used.

Useful? React with 👍 / 👎.

…query

The @media (max-width: 640px) rule forced .is-positioned dialogs to
position:relative, which breaks Electron anchoring at narrow viewports.
Non-Electron already returns null (no is-positioned class) so the rule
never matched there — it was dead code outside Electron and harmful
inside it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant