Appearance
功能规格说明:桌面端布局
本规格描述侧边栏这一列:怎么收起、收起状态存到哪、会话多了谁滚动谁固定。聊天区内部怎么切成多个分屏见 desktop-split-pane.md;右侧面板见 desktop-right-panel.md。
用户场景与测试
用户故事:侧边栏收起/展开(优先级:P1)
作为用户,我希望点击侧边栏顶部标题旁的收起按钮把侧边栏完全收起(聊天区占满整个宽度),需要时再通过对话顶栏最左侧的展开按钮恢复,以便在专注对话内容时获得最大横向空间(与 Claude Code Desktop 的侧边栏收起体验一致)。
为什么是这个优先级:侧边栏固定宽度常驻占位,对话内容多时挤占阅读与预览空间;收起/展开是桌面端基础布局能力,且状态需跨会话/重启保持。
独立测试:点侧边栏收起按钮验证侧边栏完全收起(不渲染、不预留空位、不遮挡内容)且聊天区占满;点对话顶栏最左侧展开按钮验证恢复;双分屏下验证收起/展开全局同步、展开按钮只在最左侧 pane 顶栏出现;重启应用验证状态保持。
验收场景:
- 假设应用以 desktop 宿主运行,当用户点击侧边栏顶部标题旁的收起按钮,则侧边栏完全收起——不渲染、不预留左侧空位、不遮挡内容,聊天区占满整个宽度。
- 假设侧边栏已收起,当用户查看对话顶栏最左侧,则显示展开按钮(悬停提示「展开侧边栏」),点击后侧边栏恢复显示。
- 假设侧边栏已收起且账户卡片菜单(已登录为点击个人信息行热区弹出的纯功能菜单、未登录为「更多」按钮菜单)处于展开态,当收起生效,则菜单随侧边栏一并消失,不残留弹出菜单。
- 假设桌面端存在多个分屏(pane),当任一分屏中收起/展开侧边栏,则状态全局同步(所有 pane 一致收起或展开)。
- 假设桌面端存在多个分屏,当侧边栏已收起,则展开按钮只出现在最左侧 pane 的顶栏,右侧 pane 不重复渲染。
- 假设用户收起侧边栏后切换会话,当切换完成,则收起状态保持。
- 假设用户收起侧边栏后重启应用,当应用重新加载,则收起状态保持(持久化保存)。
用户故事:会话列表滚动、入口固定(优先级:P1)
作为用户,我希望左侧会话多到一屏放不下时只有「会话列表」这一块滚动,「新对话」「插件市场」入口与底部账户卡片始终固定可见,以便我随时能新建对话、进入插件市场或查看套餐用量,而不必先把列表滚回顶部。
为什么是这个优先级:会话条目长期累积,很容易超过一屏;入口一旦随列表滚走,用户就同时失去新建对话与插件市场这两个最主要的动作入口,而这两个入口在内容态下同样高频使用。
独立测试:造一棵远超一屏的会话树(多分组、多条目),滚动列表到底部,验证「新对话」「插件市场」入口与底部账户卡片的位置在整个滚动过程中不变且始终可点、侧边栏自身滚动位置恒为 0(内容不被整体滚走);把窗口高度压缩到很矮后重复验证固定入口与账户卡片仍完整可见、压缩由会话列表承担。
验收场景:
- 假设侧边栏会话树内容高度超过可视高度,当用户滚动会话列表,则只有会话列表区域滚动(滚动条只出现在该区域内),侧边栏本身不滚动——顶部窗口行/品牌行、「新对话」「插件市场」入口在整个滚动过程中位置不变、始终可点。
- 假设侧边栏会话树内容高度超过可视高度,当查看侧边栏底部,则账户卡片(套餐用量 / API 余额 / 账号)必须完整可见并贴住侧边栏底部,既不被会话列表顶出可视区,也不随列表滚动移动。
- 假设会话列表已滚动到末尾(或回到顶部),当用户继续滚动,则滚动停在该列表的边界,不得把侧边栏其余部分或整页一起带走;列表内条目不越界渲染到固定入口/账户卡片区域之上。
- 假设窗口高度被压缩到很矮(会话列表可视高度随之变小),当用户查看侧边栏,则固定入口与账户卡片必须保持自身完整高度、互不挤压,高度压缩全部由会话列表区域承担(其可滚动高度相应变小,列表照常可滚动到底)。
- 假设侧边栏处于无会话/空会话状态(列表内容不足一屏),当用户查看侧边栏,则布局与固定入口位置不变,不出现多余滚动条或元素位移。
- 假设会话列表已滚动到中间位置,当用户点击固定入口(「新对话」/「插件市场」)或切换主题,则入口行为与列表未滚动时一致,列表滚动位置不影响入口可用性与视觉。
边界情况
- 会话列表与固定入口的高度竞争:侧边栏可视高度不足时,压缩只由会话列表区域承担(其可滚动高度随之变小,极端情况下逼近 0 仍可滚动),固定入口与账户卡片保持自身完整高度;不得出现固定入口被压扁、账户卡片被顶出可视区,或换成整条侧边栏一起滚动。
非目标(明确排除)
- 侧边栏折叠成图标栏(rail):不做。收起即完全隐藏——不渲染、不预留空位,没有「只剩一列图标」的中间态。
- 侧边栏宽度拖拽调整:不做,宽度固定(240px)。横向留白只由「收起/展开」控制,不提供分隔条。