feat(compact): 历史堆砌区支持顶部 resize bar 调整高度上限#1664
Conversation
compact 紧凑态下历史对话气泡堆叠在 CompactExportHistoryPanel,其高度上限原本写死在 --compact-export-history-region-height(width*1.18 / 63vh),用户只能调宽度(左右 handle)、 无法调高度,想把历史区压矮节约屏幕没有任何入口。 在堆砌区顶部新增一条横向 resize bar(平时透明、hover 半透明显现、拖动中保持可见), 上下拖拽覆盖预留变量 --compact-history-slot-height: - 范围 120px ~ min(width*1.46, 78% 视口/工作区),初始未拖动保持默认高度 - React localStorage 持久化(neko.reactChatWindow.compactHistorySlotHeight) - 拖动复用宿主 neko:compact-interaction-geometry-refresh 让 Electron 窗口重算 bounds / 命中区 / 穿透 - bar 带 data-compact-hit-region + no-drag,Electron 下可点不穿透、不触发拖窗 - compact 单行小胶囊本身不动 补 vitest(bar 渲染/hit-region/is-active)与 pytest static(样式/DOM/storage key/几何事件)断言。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Worried about impact? Review this PR in Change Stack to explore blast radius before you approve or request changes. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Walkthrough在紧凑模式历史面板中加入顶部可拖拽高度调整:常量与类型、localStorage 持久化、跨平台高度计算、App 内拖拽流程与 CSS 变量同步、面板 props 扩展、样式与测试覆盖喵。 Changes紧凑历史区高度拖拽完整功能
Sequence DiagramsequenceDiagram
participant User as 用户 (拖拽)
participant Panel as CompactExportHistoryPanel
participant App as App 组件
participant LocalStorage as localStorage
participant CSS as CSS 变量
User->>Panel: pointerDown 在 resize bar
Panel->>App: onHistoryResizePointerDown
App->>App: 记录起始高度与 pointerId,设置 compactHistoryResizeActive=true
User->>Panel: pointerMove
Panel->>App: onHistoryResizePointerMove
App->>App: 计算并 clamp 新高度
App->>CSS: 更新 --compact-history-slot-height
App->>App: 派发 neko:compact-interaction-geometry-refresh
User->>Panel: pointerUp
Panel->>App: onHistoryResizePointerUp
App->>LocalStorage: 保存最终高度(仅当 moved)
App->>App: 清理拖拽状态,compactHistoryResizeActive=false
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
诗
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a3e08f5e05
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
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 `@frontend/react-neko-chat/src/App.tsx`:
- Around line 2911-2915: The effect currently only writes the CSS var via
applyCompactHistorySlotHeightVar but doesn't clamp or update
compactHistorySlotHeight/state/storage when constraints change, causing a drag
deadzone; modify the useEffect that depends on applyCompactHistorySlotHeightVar,
compactHistorySlotHeight and isCompactSurface to call clampExistingHeight() on
mount and when the compact surface width changes (subscribe to/derive width
changes in the effect), and if clampExistingHeight() returns a different value,
set the new value into the state that holds compactHistorySlotHeight and persist
it to storage (same storage write used elsewhere) before calling
applyCompactHistorySlotHeightVar; apply the same change to the other similar
effect block that mirrors this logic so stored heights are clamped and saved
whenever constraints change.
🪄 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: 06682934-4aa9-467e-b99a-4507bbb5a294
📒 Files selected for processing (5)
frontend/react-neko-chat/src/App.tsxfrontend/react-neko-chat/src/CompactExportHistoryPanel.test.tsxfrontend/react-neko-chat/src/CompactExportHistoryPanel.tsxfrontend/react-neko-chat/src/styles.csstests/unit/test_react_chat_window_static.py
- bar 透明从本体移到 ::after 伪元素:宿主几何收集器(app-react-chat-window.js)按 computed opacity<=0.01 丢弃 hit-region,bar 本体透明会让 Electron 下整条鼠标穿透、永远 hover/点不到、 无法发起拖拽。改后本体保持不透明、只让视觉抓手伪元素平时透明。 - 起拖基准对持久高度 clamp:存量值来自更大屏 / 更宽 surface 时面板已钳到 max,用 stale 大值做 基准会出现「先拖一段没反应」的死区。并新增监听 neko:compact-surface-resize-width-change, 宽度变化后按新约束重写 CSS 变量(刻意不改 state / 不覆盖 storage,保留跨屏 / 跨宽度高度记忆)。 - max 扣掉 scroll 上方 bar + 下方 controls 的固定 chrome(72px),避免拖到上限时 scroll 吃满 anchor、controls / 底部气泡溢出被 Electron 几何裁成非交互。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8d309f93f2
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- choice prompt 压在历史上方(choiceLayerAbove)时,bar 的 hit-region gate 在 !choiceLayerAbove, 并纳入 under-choice 的 pointer-events:none / 淡化列表。原本该态历史区整体惰性,但 bar 仍保持 pointer-events:auto + 上报命中区,会在 Electron 下留一条可拖、不穿透的活条干扰 choice UI。 - resize state 加 moved 标志,finish 只在真正拖动过才 persist:纯点击 bar 不再把响应式 CSS 默认 高度(width*1.18 / 视口比)锁成固定像素值(否则之后视口 / compact 宽度变化不再驱动面板高度)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
frontend/react-neko-chat/src/CompactExportHistoryPanel.test.tsx (1)
65-71: ⚡ Quick win补齐
data-compact-hit-region-kind的断言,避免命中区契约漏测这段只断言了
data-compact-hit-region-id和data-compact-hit-region被移除;建议在 Line 69-70 附近再补一条data-compact-hit-region-kind为null的断言,这样和组件里的同条件三属性行为完全对齐,后续回归更不容易漏掉喵。可参考的最小改动喵
expect(bar).not.toBeNull(); expect(bar?.getAttribute('data-compact-hit-region-id')).toBeNull(); expect(bar?.getAttribute('data-compact-hit-region')).toBeNull(); + expect(bar?.getAttribute('data-compact-hit-region-kind')).toBeNull();🤖 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/CompactExportHistoryPanel.test.tsx` around lines 65 - 71, Add an assertion to the test that the resize bar drops the third hit-region attribute: after locating bar with container.querySelector('.compact-export-history-resize-bar') (in CompactExportHistoryPanel.test.tsx) assert that bar?.getAttribute('data-compact-hit-region-kind') is null, matching the existing checks for data-compact-hit-region-id and data-compact-hit-region so the test covers all three attributes the component clears.
🤖 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.
Nitpick comments:
In `@frontend/react-neko-chat/src/CompactExportHistoryPanel.test.tsx`:
- Around line 65-71: Add an assertion to the test that the resize bar drops the
third hit-region attribute: after locating bar with
container.querySelector('.compact-export-history-resize-bar') (in
CompactExportHistoryPanel.test.tsx) assert that
bar?.getAttribute('data-compact-hit-region-kind') is null, matching the existing
checks for data-compact-hit-region-id and data-compact-hit-region so the test
covers all three attributes the component clears.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 9e5172df-67fc-4f54-b76d-f576a5e91107
📒 Files selected for processing (5)
frontend/react-neko-chat/src/App.tsxfrontend/react-neko-chat/src/CompactExportHistoryPanel.test.tsxfrontend/react-neko-chat/src/CompactExportHistoryPanel.tsxfrontend/react-neko-chat/src/styles.csstests/unit/test_react_chat_window_static.py
🚧 Files skipped from review as they are similar to previous changes (4)
- frontend/react-neko-chat/src/styles.css
- frontend/react-neko-chat/src/CompactExportHistoryPanel.tsx
- tests/unit/test_react_chat_window_static.py
- frontend/react-neko-chat/src/App.tsx
回应 CodeRabbit nitpick:组件三个 hit-region 属性(region / id / kind)同条件 gate 在 !choiceLayerAbove,测试补齐 data-compact-hit-region-kind=null,与已有 id / region 两条对齐, 覆盖完整命中区契约。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
把顶部高度 bar 的浮现触发从「hover 整个历史区」收窄为:鼠标进入左右宽度 handle (.app-shell:has(.compact-chat-resize-handle:hover),与 anchor 同在 app-shell 下,跨子树 :has) 或历史滚动条命中区(.compact-export-history-anchor:has(.compact-export-history-scrollbar-hit:hover)) 时连带显现;bar 本体 hover / 拖动中(is-active)保留。这样只在「调宽 / 滚动」语境里统一提示也能 调高度,平时不再因鼠标划过历史区就亮,less intrusive。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
背景
compact 紧凑态下,历史对话气泡堆叠在
CompactExportHistoryPanel,高度上限原本写死在--compact-export-history-region-height(网页width*1.18 / 63vh、Electronwidth*1.18 / workarea*0.63)。compact 态只有左右两个宽度 handle(CompactSurfaceResizeSide = ''left'' | ''right''),用户只能调宽、无法调高,想把历史区压矮节约屏幕没有任何入口。改动
在堆砌区顶部新增一条横向 resize bar:
is-active)半透明显现;拖动中靠独立 state 保持可见--compact-history-slot-height(此前无人赋值),上拖增高、下拖压矮120px ~ min(width*1.46, 78% 视口/工作区),初始未拖动保持默认高度localStorage持久化(neko.reactChatWindow.compactHistorySlotHeight)neko:compact-interaction-geometry-refresh,让宿主重算 history 命中 rect / Electron 窗口 bounds / 鼠标穿透data-compact-hit-region+data-compact-no-drag,Electron 下可点不穿透、不触发拖窗验证
tsc --noEmittypechecktest_react_chat_window_static.py30 passed(新增样式/DOM/storage key/几何事件断言 + 既有切片未破坏)npm run build完整打包待真机验证(Electron)
Electron compact 是独立窗口、主进程在
lanlan_frd(本仓库不可见)。本 PR 靠触发几何刷新让主进程扩窗,论据是「展开历史」本身已能撑窗、属同类几何变化。需真机确认:上限拖到 78% 时是否超过主进程对 compact 窗口的高度上限而被裁;若被裁需在lanlan_frd侧放宽或读取该上限。🤖 Generated with Claude Code
Summary by CodeRabbit
新功能
样式
测试