# dsh-right-dock 设计总览 ## 目标 给 DSH Web UI 一个可扩展的右侧工具栏平台: - 右缘常驻图标 rail:容器级入口,打开 dock 不依赖任何 tab 插件的按钮(VS Code activity-bar 形态) - 推挤式(非遮挡)多标签面板:打开时压缩对话区宽度,与官方左侧栏同感 - 窄屏(<1024px)自动转浮层抽屉 + 点击关闭背景 - 插件通过 `rightdock.tab` 坐席挂 tab;`rightdock` client 服务(`ctx.get`)提供 open/openTab/close/toggle/toggleTab/isOpen ## 非目标 - 自身带任何具体功能 tab(纯平台;住户如 workspace-files) - 底部/左侧 dock、tab 拖拽重排、tab 拆窗 - 认证/多用户语义 ## 工作原理 双半结构,同一 npm 包(host 半部极薄,实际逻辑全在浏览器侧): | 文件 | 职责 | | --- | --- | | `src/index.ts` | host 半部:占位(平台无 host 路由) | | `src/client/index.js` | rail + dock 面板 + backdrop、推挤效果、`rightdock` 服务 | | `scripts/build.mjs` | 原子构建 + client bundle loader 门禁(workspace-files 模板同款) | 三个 `shell.overlay` 坐席条目:rail(order 81,常驻)、dock 面板(order 80,声明 `rightdock.tab` list 坐席)、窄屏 backdrop(order 79)。 **Tab 账本**:tab 列表不存储在插件里,直接读 slot ledger(`slots.entries('rightdock.tab')`),`useSyncExternalStore` 订阅版本——tab 插件的装卸实时反映;激活 tab 消失时自动切到首个 tab,最后一个 tab 卸载时自动收起 dock。 **推挤几何**:宽屏下 AppFrame 根元素拿 `margin-right`(grid solver 把亏缺重分配到中间 1fr 轨道,对齐官方详情栏行为)。推挤宽度 = dock 开 ? 面板宽 + 40 : (有 tab ? 40 : 0)——**rail 是布局不是浮层**,对话区始终为它让位。窄屏不推挤(浮层抽屉)。 **入口模型**(ADR-0001 的核心): | 层级 | 入口 | 语义 | | --- | --- | --- | | 容器级 | 右缘图标 rail(本插件提供,常驻) | 点图标 `toggleTab`:非激活 → 打开并定位;激活 → 收起 | | tab 级 | 各 tab 插件自带的快捷按钮(可选) | 如 workspace-files 会话标题栏「文件」按钮,同一 `toggleTab` 语义 | tab 注册 options:`id` / `order`(排序)/ `label`(文字或函数);rail 图标经 `rightdock` 服务的 `setTabIcon(id, 组件)` 声明(slot options 被 ledger 白名单化,带不了自定义字段),未声明时用 label 首字兜底。 ## 安全模型 纯浏览器侧 UI 平台,无 host 路由、无文件/网络能力;tab 内容的安全边界由各住户插件自负(如 workspace-files 的双重围栏)。 ## 边界与限制 - rail 图标要求 tab 插件调 `setTabIcon` 声明;未声明则显示 label 首字 - 窄屏 + dock 打开时 rail 暂隐(抽屉覆盖右缘,抽屉头部自有关闭) - tab 顺序按 `order` 排序,无用户自定义 ## 决策记录 - [0001-activity-rail.md](decisions/0001-activity-rail.md) — 容器级常驻入口选图标 rail(否决:边缘把手 / tab 插件自带按钮)