Repository navigation
侧边栏导航项增多后,会话/工作区列表被压缩至不可见且无法滚动(官方包 bug,桌面浏览器亦可复现) #12083
Replies: 2 comments
|
(以下是提交时的完整原始缺陷报告,供维护者/接手者完整参考,主帖已概括要点,此处保留全部细节与根因、修复、设计建议。) DSH Web 侧边栏:插件入口增多后,会话/工作区列表被挤出视口且无法滚动
提交目标(先读这一节)应该提到哪:官方 DSH 仓库源码位置: 判断依据:出问题的文件自带元数据,可自行核验: node -p "require('@deepseek-ai/dsh-client-ui-sidebar/package.json').repository"
# → { type: 'git', url: 'git+https://github.com/deepseek-ai/deepseek-harness.git',
# directory: 'packages/client/ui-sidebar' }即: 交叉验证:本问题在桌面浏览器打开 DSH Web 时同样可复现 另一个仓库:DSH Go(社区客户端,非本问题的归属地)
分流表:什么提到哪
通用判断标准:这个 bug 在桌面浏览器的 DSH Web 上会出现吗?
提交时建议附带的一句话若维护者质疑「是否只是某个特殊环境的问题」,可补充:
0. TL;DR
而 用户感知:「插件和文件夹区域固定死、无法缩放、滚轮也没用,会话界面和空间界面消失了」。 1. 环境
触发该问题的插件(各自向
加上内置项(插件 / Agent 中心 / 自动化任务 / 更多),导航列表约 11 项。 2. 复现步骤
对照实验:卸载若干注册导航入口的插件,使导航项降到 6 个以下 → 问题消失。 3. 根因3.1 DOM 结构(已从打包产物确认)
<div className={root}> // flex-direction:column; height:100%
<div className={topStrip} /> // flex:none; height:52px
<div className={logoRow} /> // flex:none; height:60px
<button className={newSession} /> // flex:none; height:38px
<nav className={panelList} /> // ← 问题所在:flex:none
<div className={regionArea}> // flex:1; overflow:hidden
{renderSlot("sidebar.workspaces")} // ← 会话/工作区列表在这里
</div>
<div className={footArea} /> // flex:none
</div>3.2 两处关键 CSS(原始值,来自
|
| 改动 | 作用 |
|---|---|
flex:none → flex:0 1 auto |
允许导航区在空间不足时收缩,把空间让给 regionArea |
min-height:0 |
解除 flex 项的最小内容高度限制,否则仍不会收缩 |
overflow-y:auto |
导航项超出时自己出滚动条,用户能滚动查看全部入口 |
max-height:45vh |
上限约束,避免导航区在超大屏上也无限扩张 |
overscroll-behavior:contain |
防止滚动穿透到外层容器 |
为何选 45vh:这是一个折中值 —— 保证常见高度下导航区一次能看到 8~10 项,
同时始终给会话列表留出 ≥55% 的空间。上游可改为配置项或按实际项数动态计算。
4.4 兼容性与风险
- 纯 CSS 改动,不动 DOM 结构、不动 JS 逻辑
- 仅在导航项超出可用高度时生效;项目少时行为与原来完全一致(
flex:0 1 auto在空间充足时等价于不收缩) - 折叠态(
.hHd-Xa_collapsed)有自己的.hHd-Xa_collapsed .hHd-Xa_panelList{gap:12px;margin-bottom:12px}规则,
未受本次改动影响;轨道模式仍正常 - 已确认目标 CSS 字符串在文件中唯一(
grep -c结果为 1),不会误伤其他规则
4.5 验证结果
| 检查项 | 结果 |
|---|---|
node --check lib/client.js |
✅ 语法通过 |
| 目标字符串唯一性 | ✅ 文件内仅 1 处 |
模块导入 import("./lib/index.js") |
✅ 成功,导出 apply |
| diff 对比备份 | ✅ 仅改动目标 CSS 一处 |
| 运行时加载 | 需用户刷新浏览器验证(见下) |
/api/client/... 返回 401),
本机无法直接抓取 bundle 内容做端到端断言。视觉与滚动行为需人工在浏览器确认。
接手者应补上这一步。
4.6 回滚
cd /opt/dsh/node_modules/@deepseek-ai/dsh-client-ui-sidebar/lib
cp client.js.bak-<timestamp> client.js5. 给上游的建议修法(PR 方向)
请在 TypeScript 源码(packages/client/ui-sidebar/src/** 或对应位置)中修改,
而非直接在 dist 上打补丁。
5.1 最小修复
// sidebar 样式模块中
panelList: {
display: 'flex',
flexDirection: 'column',
flex: '0 1 auto', // 原:flex: 'none'
minHeight: 0,
overflowY: 'auto',
overscrollBehavior: 'contain',
maxHeight: '45vh',
gap: 2,
marginBottom: 8,
}5.2 更健壮的方案(推荐)
a. 让导航区高度自适应,而非硬编码上限
// 用 CSS 变量而非固定 45vh,便于主题/设置覆盖
maxHeight: 'var(--dsh-sidebar-panel-max-height, 45vh)',b. 项目过多时自动折叠进「更多」
现有代码已支持 unpinned 与 PanelMoreMenu:
panels.filter(({ id }) => id === "plugins" || !unpinned.includes(id))可在导航项超过阈值(如 6 项)时,自动把低频项推入 unpinned,
而不是等用户手动「更多」里 pin。这样多数用户不会遇到溢出。
c. regionArea 的 overflow:hidden 复审
该值在当前结构下是危险的:一旦有兄弟节点超出预算,被裁掉的内容将永久不可达。
建议改为 overflow: visible 或在内部显式划分滚动区,并加 min-height 下限(如 120px)保证会话列表始终可用。
d. 可访问性
当前问题下,键盘用户与屏幕阅读器用户同样无法触达被裁的列表;
overflow:hidden 的元素对 focus 顺序与滚动也是陷阱。修复后建议补一次键盘可达性验证。
5.3 需要维护者确认
panelList是否应纳入侧边栏的滚动预算计算?- 是否已有「导航项数量上限」的产品决策?还是无限增长?
regionArea的overflow:hidden是否有意为之(例如防止动画期溢出)?
如果有,需要区分「动画期」与「稳态」两种状态。- 折叠态(
collapsed)与新修复的交互是否需要额外规则?
5.4 更根本的设计建议:插件导航区应可折叠 / 分组
这一节来自用户的直接观察,我认为它比第 5.1 的 CSS 修补更接近问题的本质。
5.4.1 现状的不对称(截图已确认)
同一列侧边栏里,存在两种截然不同的交互模型:
| 区域 | 折叠箭头 | 能否收起 | 溢出处理 |
|---|---|---|---|
| 文件夹(▾ 文件夹) | ✅ 有 | ✅ 可折叠 | — |
| 会话(▾ 会话) | ✅ 有 | ✅ 可折叠 | 内部 overflow-y:auto |
| 插件导航(插件 / Agent 中心 / 自动化任务 / XD Pool / 灵枢 / 上下文洞察 / 记忆 / 学习 / 更多) | ❌ 无 | ❌ 不可折叠 | flex:none + 父级 overflow:hidden |
下半部分能折叠、能滚动,上半部分既不能折叠也不能滚动 —— 这个不对称正是用户困惑的直接来源:
"下面的工作区和会话都可以缩放,为什么上面的插件区固定死?"
也就是说,DSH 已经为列表型区域实现了折叠模式(chevron + arrow 旋转动画 + 分组 state),
却没有把同一套模式用在插件导航上。这不是"缺少技术手段",而是设计上没有对齐。
5.4.2 建议的交互模型
把插件导航从"扁平罗列"改为"分组 + 可折叠":
┌─────────────────────────────┐
│ ▾ 插件 │ ← 分组标题,可折叠
│ · 官方插件市场 │
│ · [已安装的第三方] │
├─────────────────────────────┤
│ ▸ 智能体 / 自动化(收起) │ ← 默认折叠,节省空间
├─────────────────────────────┤
│ ▸ 工具(收起) │
└─────────────────────────────┘
关键设计点:
- 分组标题可点击折叠,与「文件夹」「会话」复用同一套 chevron 组件与动画
- 折叠状态持久化(写入设置或 localStorage),刷新后保持
- 低频组默认折叠:「智能体」「工具」类入口默认收起,只展开主「插件」组
- 一键全部展开 / 收起,便于插件很多的用户快速切换
- 保留「更多」菜单作为兜底:即使分组也不够放,仍可收进菜单
5.4.3 两种方案的关系
| 5.1 CSS 修补 | 5.4 分组折叠 | |
|---|---|---|
| 改动量 | 约 8 行 CSS | 组件 + 状态管理 + 持久化 |
| 解决"看不见" | ✅ | ✅ |
| 解决"项数无上限" | ❌(只是多一条滚动条) | ✅ |
| 用户可控 | ❌(被动滚动) | ✅(主动折叠) |
| 符合现有设计语言 | — | ✅(复用已有 chevron 模式) |
建议两者都做:5.1 作为立即止血的低风险补丁,5.4 作为正确的长期方案。
只做 5.1,用户仍需在一条长滚动条里翻找;只做 5.4,未分组的历史部署可能仍有溢出风险。
5.4.4 可复用的现有实现
不需要从零造:
dsh-client-ui-workspace已有chevron/arrow/sectionHeader的完整实现,
含transition:transform .15s var(--ds-ease-in-out)的展开动画dsh-client-ui-sidebar已有unpinned/setPinned/PanelMoreMenu的 pin 机制
(见lib/client.js中panels.filter(({ id }) => id === "plugins" || !unpinned.includes(id)))- 只需把两者结合:给
panelList增加分组层级与折叠 state
6. 可直接提交的上游 Issue 草稿
## 标题
侧边栏导航项增多后,会话/工作区列表被压缩至不可见且无法滚动
## 环境
- dsh 0.2.1-rc.4
- @deepseek-ai/dsh-client-ui-sidebar 0.2.1-rc.4
- 平台:Android + proot(DSH Go 内「切换到 DSH 网页版」)
- 安装的第三方插件中,有 5 个注册了 sidebar.panellist 入口
(dsh-context / dsh-mnemon / dsh-xdpool / @furongjun1999/dsh-memory / studymate)
## 现象
左侧导航项大约 11 个时:
- 导航区固定占据全部可用高度,不收缩
- 其下方的「文件夹」「会话」区域被压到接近 0 高
- 鼠标滚轮无法滚动到被遮挡内容
- 窗口变矮时,导航项本身也开始被裁切且无法滚动
卸载几个注册入口的插件、把导航项降到 6 个以下 → 现象消失。
## 根因
lib/client.js 中 panelList 与 regionArea 是兄弟节点(都在 .root 下),
两个关键 CSS:
.panelList { flex: none } ← 不收缩
.regionArea { flex: 1; overflow: hidden } ← 溢出被裁,不产生滚动
导航项多时 panelList 独占高度,regionArea 分到的高度趋近 0;
overflow:hidden 又让溢出内容不可滚动。滚轮"失效"是因为没有可滚动容器,
不是事件问题。
## 建议修法
panelList 改为:
flex: 0 1 auto;
min-height: 0;
overflow-y: auto;
max-height: 45vh; /* 或 CSS 变量 */
并复审 regionArea 的 overflow:hidden,给内部列表留最小高度。
## 更进一步的设计建议
同一下方区域的「文件夹」「会话」都有折叠箭头(chevron)且能收起,
但上方的插件导航既不能折叠也不能滚动 —— 这个不对称是困惑的根源。
建议让插件导航也支持分组 + 折叠:
- 复用 workspace 侧已有的 chevron / sectionHeader 实现
- 分组如「插件」「智能体/自动化」「工具」,低频组默认折叠
- 折叠状态持久化,并提供一键全展开/全收起
- 保留「更多」菜单作为兜底
这样既解决"看不见",也解决"插件项无上限增长"的问题;
CSS 修补只能被动滚动,分组折叠才能让用户主动掌控。
## 附
已在本地 dist 上验证该修复的语法与模块加载正确(具体见报告),
视觉与滚动行为需在浏览器中确认。
可提供完整 patch。7. 给接手此事的 AI 的补充说明
7.1 本报告的已知边界
- ❌ 未完成端到端浏览器验证。静态资源带鉴权(
/api/client/*返回 401,
跟随?token=的 303 重定向后取 index 返回 400),无法用脚本断言 bundle 内容。
请接手者在浏览器里实测:导航区是否出现独立滚动条、会话列表是否恢复。 - 未测试极小视口(如 <600px 高)下的表现
- 未测试折叠态(
hHd-Xa_collapsed)与新规则的交互 - 未测试 direct(非 proot)启动方式下的差异 —— 理论上无关,因纯前端 CSS
7.2 一个容易踩的坑
本会话早期我曾误判根因两次,记录下来供借鉴:
- 误判为文件权限问题。测试用
setpriv --clear-caps时该选项不被支持,
命令报错被我当成"读不到文件"。教训:先检查命令本身的退出码与 stderr。 - 误判
panelList是regionArea的子元素。实际读 JSX 渲染代码后确认二者是兄弟节点。
教训:CSS 类名的相似不等于 DOM 嵌套关系,必须看渲染代码。
7.3 复现该问题的快速方法
# 1. 确认当前安装的插件里,有多少注册了导航入口
cd ~/.dsh/profiles/web/node_modules
for d in dsh-* @*/*; do
f="$d/lib/client.js"; [ -f "$f" ] || f="$d/client.js"
[ -f "$f" ] && grep -q "sidebar.panellist" "$f" 2>/dev/null && echo "$d"
done
# 2. 确认 CSS 当前值
grep -o "hHd-Xa_panelList{[^}]*}" \
/opt/dsh/node_modules/@deepseek-ai/dsh-client-ui-sidebar/lib/client.js7.4 重要提醒
本修复改的是 /opt/dsh/node_modules/ 下的编译产物,
任何 dsh 升级都会将其重置。若作为长期方案,必须推动上游在源码层修复。
|
看到把成因追到 panelList 与 regionArea 的 flex 关系,很有帮助。 dsh-panel-control 0.7.x 顺手做了个纯前端的兜底,供参考:给入口列表设 max-height(默认 45vh,可切 35/45/55 或不限)并允许滚动,同时给下方会话/工作区区域留一个最小高度;入口本身也支持命名分组,组标题可以直接折叠,展开状态会记住。 它不修改官方包,只在自己的 DOM 属性上挂 CSS,所以只能缓解症状。真要治本还是得回到 regionArea 的 overflow 和 panelList 的 flex 语义,帖子里那版补丁更根本。 仓库:https://github.com/QIUZAIYOU/dsh-panel-control ;npm:dsh-panel-control |
Uh oh!
There was an error while loading. Please reload this page.
环境
0.2.1-rc.4@deepseek-ai/dsh-client-ui-sidebar@0.2.1-rc.4sidebar.panellist注册导航项的插件,左侧导航项 ≥ 9 个。实测 5 个第三方插件(dsh-context/dsh-mnemon/dsh-xdpool/@furongjun1999/dsh-memory/@yunmiao/studymate)+ 内置项,共约 11 项现象
左侧导航项增多时:
根因(已在打包产物
lib/client.js确认)panelList与regionArea是.root下的兄弟节点,两个关键 CSS:导航项多时
panelList独占高度,regionArea分到的高度趋近 0;overflow:hidden又把溢出内容裁掉。滚轮"失效"是因为没有可滚动容器,不是事件问题。缺陷在于侧边栏假设了导航项数量很少——这是宿主布局健壮性问题。已验证的修复(本地 dist 上语法/加载通过,视觉需浏览器确认)
panelList改为:regionArea的overflow:hidden建议复审,给内部列表留最小高度(如120px),避免任何兄弟节点溢出时内容永久不可达(键盘/屏幕阅读器用户同样无法触达)。更进一步的设计建议
同一下方「文件夹」「会话」都有折叠箭头(chevron)且能收起、能滚动,但上方插件导航既不能折叠也不能滚动——这个不对称是用户困惑的根源("下面的能缩放,上面为什么固定死?")。DSH 已为列表型区域实现了
chevron+ 分组 state,建议让插件导航也支持分组 + 可折叠:dsh-client-ui-workspace已有的chevron/sectionHeader实现与展开动画unpinned/setPinned/PanelMoreMenu的 pin 机制这样既解决"看不见",也解决"插件项无上限增长";纯 CSS 修补只能被动滚动,分组折叠才能让用户主动掌控。建议两者都做:CSS 修补贴作为立即止血的低风险补丁,分组折叠作为正确的长期方案。
为什么提交到这里而不是 DSH Go
决定性证据:出问题的包自带仓库元数据,可自行核验:
@deepseek-ai/dsh-client-ui-sidebar是官方包,侧边栏 HTML/CSS 完全由它提供;DSH Go 只是把官方 Web 嵌进 WebView 显示,并未重写侧边栏。且该问题在桌面浏览器同样可复现,排除了"仅 Android / WebView 特有"的可能。未完成的验证
静态资源带鉴权(
/api/client/*返回 401),无法用脚本做端到端断言;视觉与滚动行为需在浏览器中由维护者确认。可提供完整 patch。上游应修改 TypeScript 源码(packages/client/ui-sidebar/src/**),而非照抄 dist 补丁。All reactions