Skip to content

fix(chat): collapse the history rail when the window crosses the wide breakpoint - #2890

Open
dangzitou wants to merge 1 commit into
TencentCloud:developfrom
dangzitou:fix/chat-sidebar-follow-breakpoint
Open

dangzitou wants to merge 1 commit into
TencentCloud:developfrom
dangzitou:fix/chat-sidebar-follow-breakpoint

Conversation

@dangzitou

Copy link
Copy Markdown
Contributor

Fixes #2784

问题

对话页中间栏(会话历史)的开合状态只在模块加载时根据 window.innerWidth 算一次。宽屏(≥1200px)进入后把窗口拖窄(分屏、拉宽 DevTools 等),248px 的中间栏仍然展开,正文和输入框被挤压;反过来从窄屏拖回宽屏也不会自动展开。

改动

只改 dashboard/src/pages/Chat/hooks/useChatSidebarState.ts:

  • 新增纯函数 resolveChatSidebarOpenOnResize(prevWidth, nextWidth, open):只有跨过 CHAT_SIDEBAR_WIDE_BREAKPOINT(1200)时才改变状态(变宽 → 展开,变窄 → 收起),同侧内的 resize 保持当前状态(包括用户手动开合的结果)。
  • 模块级 resize 监听(passive)调用它,状态变化时通知 useSyncExternalStore 订阅者。
  • 断点触发的变化不写 localStorage,用户手动设置的偏好在下次加载时仍然生效(与 issue 中期望一致)。
  • 把通知订阅者的循环抽成 notifySidebarListeners(),供手动切换和 resize 两处复用;更新了 resolveChatSidebarDefaultOpen 上"Does not react to resize"的过时注释。

不涉及 React 层、样式、后端。

截图(真实运行,本地 octop run + Vite dev server,Playwright 1440 → 1000 → 1440 视口)

中间栏实际宽度([class*=sidebarWrapper] 的 getBoundingClientRect().width):

视口宽度 修复前 修复后
1440 248px 248px
1000(跨过 1200 断点) 248px(仍展开,正文被挤) 0(自动收起)
1440(拖回宽屏) 248px 248px(自动展开)

三个阶段 localStorage["octop:chat-sidebar:open"] 均为 null,即断点变化未写入用户偏好。

1000px 视口 · 修复前:中间栏仍占 248px

before: rail stays open at 1000px

1000px 视口 · 修复后:中间栏自动收起,正文占满

after: rail collapses at 1000px

拖回 1440px · 修复后:中间栏自动重新展开

after: rail reopens at 1440px

测试

新增 dashboard/src/pages/Chat/hooks/chatSidebarResize.test.ts(5 个用例):

  • 纯函数:宽 → 窄收起、窄 → 宽展开、不跨断点保持原状态;
  • 模块集成(jsdom + renderHook(useChatSidebarOpen) + 派发 resize):1440 → 1000 → 1300 依次为 展开 / 收起 / 展开,且 localStorage 未被写入;窄屏下手动展开后在同侧 resize 仍保持展开。

把源码还原为修复前的版本时,其中 3 个用例失败;修复后全部通过。

本地验证:

  • npx vitest run src/pages/Chat/hooks/ → 35 files / 256 tests passed
  • npx tsc -b、eslint(改动文件)→ 通过
  • pre-commit 钩子完整通过:make all(format-all + ruff + mypy --strict + pytest:5441 passed)+ dashboard npm run build

Checklist

  • 📸 已提供 UI 截图/功能演示
  • 🧱 测试用例已添加并通过(回归测试在修复前失败、修复后通过)
  • ✅ CI Workflow 全部通过(等待 CI)
  • 🤖 已与 AI 对齐需求理解:只在跨 1200px 断点时同步开合;同侧 resize 不动;不写 localStorage
  • 🎯 遵循最小修改原则:仅改 1 个 hook 文件 + 1 个测试文件
  • 📝 已询问并处理代码优化建议:抽出纯函数便于测试,复用通知循环,无多余抽象

🤖 Generated with Claude Code

… breakpoint

The chat history rail only resolved its open state once, at module load.
Narrowing the window below 1200px kept the 248px rail open and squeezed the
conversation; widening again did not reopen it.

Listen for window resize at module level and, only when the viewport crosses
CHAT_SIDEBAR_WIDE_BREAKPOINT, open (wide) or close (narrow) the rail. Resizes
that stay on one side keep the current state, including a manual toggle. The
breakpoint-driven change is not written to localStorage, so the stored manual
preference still decides the state on the next page load.

Fixes TencentCloud#2784

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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