From 5be195df1876ce5bab91c626c1de77a51fe5aee5 Mon Sep 17 00:00:00 2001 From: laoyh Date: Thu, 20 Aug 2026 12:13:49 +0800 Subject: [PATCH 1/3] fix(mobile): make unavailable sidebar state clear --- README.md | 6 +++++- README_EN.md | 6 +++++- dsh.plugin.json | 2 +- package.json | 2 +- src/client/Sidebar.tsx | 6 ++++-- src/client/service.ts | 2 +- src/client/sidebar.module.css | 6 ++++-- 7 files changed, 21 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a12ae4f..11a33d2 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,10 @@ 添加插件截图 +### v0.14.1 + +- 📱 **手机无会话提示**:没有选中会话时,弱化的侧边栏开关保持不可执行,但可通过点按或键盘聚焦显示“选择一个会话以使用侧边栏”;选中会话后,同一开关打开全宽移动抽屉;抽屉宽度包含边框,不再产生 1px 横向溢出。 + ### v0.14.0 > ⚠️ **本版适配 DSH 0.1.0-rc.8**:全部 `@deepseek-ai/*` peer / devDependencies 升至 `^0.1.0-rc.8`(含传递依赖,lockfile 零 rc.7 残留),`cordis` 同步 `^4.0.0-rc.8`,CI 挂载冒烟钉版 `@deepseek-ai/dsh@0.1.0-rc.8`。**rc.7 及更早的 DSH 环境将无法解析本版依赖,请先升级 DSH**。自 v0.13.1 以来的全部更改: @@ -240,7 +244,7 @@ pnpm watch # tsdown --watch - Office 三件套预览(.docx/.xlsx/.pptx)已移至「推荐插件」(Office 预览插件,见设置页「添加插件」弹窗);未安装时此类文件走代码/下载查看兜底 - 浏览器沙箱无登录态/第三方 Cookie 受限,部分站点登录需走弹窗;被 `X-Frame-Options`/`frame-ancestors` 拒绝嵌入的站点(如 arxiv.org)显示原因面板(含「在浏览器中打开」);iframe 内部跳转不进后退栈 - HTML 预览渲染的是已保存文件(不反映未保存草稿) -- 移动端(<768px)无底部面板:进入窄屏时其标签页一次性并入右侧栏(迁移后回桌面仍保留在右侧栏),桌面端的底部面板只在宽视口下可用;移动端底部首展自动开终端不触发 +- 移动端(<768px)无底部面板:进入窄屏时其标签页一次性并入右侧栏(迁移后回桌面仍保留在右侧栏),桌面端的底部面板只在宽视口下可用;移动端底部首展自动开终端不触发。未选中会话时,点按弱化开关会显示选择会话提示;选中会话后开关打开全宽抽屉 ## 🖥️ 平台支持 diff --git a/README_EN.md b/README_EN.md index dbfd797..c406edc 100644 --- a/README_EN.md +++ b/README_EN.md @@ -41,6 +41,10 @@ Add Plugins screenshot +### v0.14.1 + +- 📱 **No-session feedback on phones**: without a selected session, the subdued sidebar toggle remains unavailable but shows “Select a conversation to use the sidebar” on tap or keyboard focus; after selecting a session, the same toggle opens the full-width mobile drawer, whose border-inclusive width no longer introduces one pixel of horizontal overflow. + ### v0.14.0 > ⚠️ **This release adapts to DSH 0.1.0-rc.8**: every `@deepseek-ai/*` peer/devDependency is raised to `^0.1.0-rc.8` (transitives included — zero rc.7 leftovers in the lockfile), `cordis` to `^4.0.0-rc.8`, and the CI mount lane pins `@deepseek-ai/dsh@0.1.0-rc.8`. **DSH environments on rc.7 or earlier can no longer resolve this release's dependencies — upgrade DSH first.** All changes since v0.13.1: @@ -271,7 +275,7 @@ pnpm watch # tsdown --watch - Office-suite preview (.docx/.xlsx/.pptx) moved to the recommended office plugin (see the "Add plugins" modals in settings); without it these files fall through to the code/download fallbacks - Browser sandbox has no login state / third-party cookies are restricted; some sites need popup login; sites that refuse embedding via `X-Frame-Options`/`frame-ancestors` (e.g. arxiv.org) show a reason panel (with "Open in browser"); in-iframe navigation does not enter the back stack - HTML preview renders the saved file (not unsaved drafts) -- No bottom panel on mobile (<768px): on narrow screens its tabs merge into the right sidebar once (after migrating back to desktop they stay in the right sidebar); the desktop bottom panel is only available on wide viewports; auto-open terminal on first bottom-panel expand does not trigger on mobile +- No bottom panel on mobile (<768px): on narrow screens its tabs merge into the right sidebar once (after migrating back to desktop they stay in the right sidebar); the desktop bottom panel is only available on wide viewports; auto-open terminal on first bottom-panel expand does not trigger on mobile. Without a selected session, tapping the subdued toggle shows the select-session message; with a selected session, it opens the full-width drawer ## 🖥️ Platform Support diff --git a/dsh.plugin.json b/dsh.plugin.json index fe47d4d..64f366b 100644 --- a/dsh.plugin.json +++ b/dsh.plugin.json @@ -1,6 +1,6 @@ { "id": "dsh-external/dsh-better-sidebar", - "version": "0.14.0", + "version": "0.14.1", "main": "./lib/index.js", "description": "VSCode 风格右侧侧边栏:文件资源管理器 / 编辑器 / 终端 / Git / 浏览器,按会话隔离。暴露服务供其他插件注册侧边栏页面和文件预览器", "engines": { diff --git a/package.json b/package.json index c372819..a461367 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dsh-better-sidebar", - "version": "0.14.0", + "version": "0.14.1", "description": "DSH web plugin: a VSCode-like right sidebar (explorer / editor / terminal / git / browser), isolated per conversation session. Exposes a service for other plugins to register sidebar tabs and file viewers.", "type": "module", "repository": { diff --git a/src/client/Sidebar.tsx b/src/client/Sidebar.tsx index 887e3a3..546e282 100644 --- a/src/client/Sidebar.tsx +++ b/src/client/Sidebar.tsx @@ -789,18 +789,20 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { }, [ctx, sessionId, cwd]) if (state === undefined || sessionId === undefined) { + // Keep the unavailable controls focusable: touch users have no hover, so + // focus is the only way the existing Tooltip can explain what is missing. return (
{!narrow && ( - )} - diff --git a/src/client/service.ts b/src/client/service.ts index 13f1934..d932977 100644 --- a/src/client/service.ts +++ b/src/client/service.ts @@ -470,7 +470,7 @@ export function matchUrlTarget(tabs: readonly TabDescriptor[], url: URL): TabDes * The plugin version this service instance reports. Keep in lockstep with * `package.json`'s version — `tests/service.spec.ts` asserts the pair. */ -export const SIDEBAR_SERVICE_VERSION = '0.14.0' +export const SIDEBAR_SERVICE_VERSION = '0.14.1' /** * Monotonic capability list consumers use to gate new API usage (features diff --git a/src/client/sidebar.module.css b/src/client/sidebar.module.css index e53c109..70bd940 100644 --- a/src/client/sidebar.module.css +++ b/src/client/sidebar.module.css @@ -91,17 +91,19 @@ color var(--ds-transition-duration-slow) var(--ds-ease-in-out); } -.toggleButton:hover:not(:disabled) { +.toggleButton:hover:not(:disabled):not([aria-disabled='true']) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); } -.toggleButton:disabled { +.toggleButton:disabled, +.toggleButton[aria-disabled='true'] { opacity: 0.4; cursor: default; } .panel { + box-sizing: border-box; position: absolute; top: 0; right: 0; From ffcd6953ebdac68c2ecf17b52a59ba94c88e743a Mon Sep 17 00:00:00 2001 From: Ch3n4y Date: Thu, 20 Aug 2026 21:11:34 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix(layout):=20=E9=9D=A2=E6=9D=BF=E5=AE=BF?= =?UTF-8?q?=E4=B8=BB=E8=A3=81=E5=89=AA=E8=A7=86=E5=8F=A3=E8=BE=B9=E7=BC=98?= =?UTF-8?q?=EF=BC=8C=E6=94=B6=E8=B5=B7=E7=9A=84=E9=9D=A2=E6=9D=BF=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E6=92=91=E5=87=BA=E6=96=87=E6=A1=A3=E5=8F=8C=E5=90=91?= =?UTF-8?q?=E6=BB=9A=E5=8A=A8=20(#277)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 收起的面板以 transform: translate(102%) 滑出屏幕,但 transform 后的元素仍计入祖先滚动溢出区,导致整个页面可左右/上下拖拽。面板宿主 [data-dsh-panel-host] 是视口尺寸的 fixed 容器,补上 overflow: hidden 后裁剪点恰在视口边缘,开合滑入动画、内部滚动容器与 fixed 弹层均不受影响。e2e 增加回归断言:面板收起时文档 scrollWidth/Height 不得超出视口。 --- src/client/sidebar.module.css | 9 +++++++++ tests/e2e/mount.e2e.ts | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/client/sidebar.module.css b/src/client/sidebar.module.css index 3dcb15c..3459b4f 100644 --- a/src/client/sidebar.module.css +++ b/src/client/sidebar.module.css @@ -34,6 +34,15 @@ inset: 0; z-index: 40; pointer-events: none; + /* Clip at the viewport edge: collapsed panels slide off-screen with + `transform: translate(102%)`, and a transformed element still + contributes to its ancestors' scrollable overflow — without this the + hidden panels extended the document's scrollable area, making the whole + page draggable left-right and up-down while any panel was collapsed. + The host is exactly viewport-sized (inset: 0), so the clip is invisible + until a panel slides in from the edge; internal scroll containers and + the app's fixed overlay stack are unaffected. */ + overflow: hidden; } :global([data-dsh-panel-host][data-dsh-panel-host-degraded]) { diff --git a/tests/e2e/mount.e2e.ts b/tests/e2e/mount.e2e.ts index a7dbf2c..46bc5c9 100644 --- a/tests/e2e/mount.e2e.ts +++ b/tests/e2e/mount.e2e.ts @@ -175,6 +175,26 @@ test('plugin mounts into the DSH shell and survives a built-in tab sweep', async const tabBar = sidebar.locator('[title]') await expect(tabBar.first()).toBeAttached({ timeout: 90_000 }) + // Regression: with the panels still COLLAPSED, the document must not grow + // beyond the viewport. Collapsed panels are slid off-screen with + // `transform: translate(102%)`, and a transformed element still + // contributes to its ancestors' scrollable overflow — unclipped, the + // hidden panels extended the document's scroll area and the whole page + // became draggable left-right and up-down. The panel host clips at the + // viewport edge (overflow: hidden), so scrollWidth/scrollHeight must stay + // within the viewport here. (Assert <= not == : a classic scrollbar + // narrows clientWidth, so scrollWidth may sit slightly under innerWidth.) + await expect + .poll( + () => + page.evaluate(() => ({ + overflowX: document.documentElement.scrollWidth <= window.innerWidth, + overflowY: document.documentElement.scrollHeight <= window.innerHeight, + })), + { timeout: 30_000 }, + ) + .toEqual({ overflowX: true, overflowY: true }) + // openByDefault defaults OFF: a fresh session's panel starts collapsed. // Expand it through the toggle cluster before the layout push can apply. const expandButton = sidebar.getByRole('button', { name: 'Expand sidebar' }) From e24d9bf879a5c95f93576301e9321731952d7609 Mon Sep 17 00:00:00 2001 From: ZgblKylin <13114351+ZgblKylin@users.noreply.github.com> Date: Sat, 22 Aug 2026 19:10:02 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix(sidebar):=20drop=20panel=20host=20below?= =?UTF-8?q?=20DSH=20cordis=20dynamic-plugin=20layer=20(z=2040=E2=86=9225)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ui-cordis CordisPanel is position:fixed at z-index 30; the unified panel host at 40 made the bottom workbench cover the cordis inventory and approval surfaces. Host now sits at 25 (above AppFrame overlay 20, below cordis 30 and the 100+ float stack). Update skin contract docs and add a mount e2e assertion for the layering band. --- AGENTS.md | 4 +- docs/plans/2026-08-15-skin-compat-design.md | 1 + ...9-sidebar-injection-unified-host-design.md | 5 ++- src/client/sidebar.module.css | 41 ++++++++++++------- tests/e2e/mount.e2e.ts | 9 ++++ 5 files changed, 41 insertions(+), 19 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f4ba2c8..e8868ab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -606,7 +606,7 @@ interface OpenTabSeed { - **面板表面**:右/底面板背景 = `var(--dsw-alias-bg-layer-1)`(通用卡片表面)。**绝不消费 `--dsw-specific-sidebar-fill`**——那是宿主左侧导航列专属令牌,皮肤系统按左导航语义覆盖它(dsh-web-ui 皮肤把它做成半透明玻璃或主题色,Aqua 设成 `transparent`),面板消费它会失去填充或与标签令牌冲突。皮肤要整体换面板表面:覆写 `--dsw-alias-bg-layer-1` 即可(dsh-web-ui 10 款皮肤都已覆盖,无需任何额外工作)。 - **终端/编辑器表面**:经 `effectiveTokenValue` 读取 `--dsw-alias-bg-base`——`transparent` 与 alpha < 0.9 的半透明玻璃值(dsh-web-ui 皮肤用 rgba 0.16–0.7)一律回退不透明底色,文字永不叠在皮肤背景画上滚动(issue #90);≥ 0.9 的近不透明值(如皮肤作用域内 0.96 的瓷器玻璃)放行,皮肤仍能控制终端表面。 -- **根锚点**:宿主 div 带 `data-dsh-better-sidebar` 属性(append 到 `document.body`)。其内是**统一面板宿主层** `[data-dsh-panel-host]`(`position:fixed; inset:0; z-index:40; pointer-events:none`,v0.13.1+):面板/开关簇在其内 **absolute** 定位(层 inset:0 即视口坐标),免疫桌面套壳中间层 transform 对 fixed 含块的劫持;页面级 transform(罕见)触发 `data-dsh-panel-host-degraded` 降级同步。皮肤若要做作用域覆盖(deep-whale 的做法),限定在 `[data-dsh-better-sidebar]` 内即可,避免全局改写影响宿主。 +- **根锚点**:宿主 div 带 `data-dsh-better-sidebar` 属性(append 到 `document.body`)。其内是**统一面板宿主层** `[data-dsh-panel-host]`(`position:fixed; inset:0; z-index:25; pointer-events:none`,v0.13.1+):面板/开关簇在其内 **absolute** 定位(层 inset:0 即视口坐标),免疫桌面套壳中间层 transform 对 fixed 含块的劫持;页面级 transform(罕见)触发 `data-dsh-panel-host-degraded` 降级同步。皮肤若要做作用域覆盖(deep-whale 的做法),限定在 `[data-dsh-better-sidebar]` 内即可,避免全局改写影响宿主。 - **布局变量**(写在 `` 上,面板打开时有效):`--dsh-sidebar-width` / `--dsh-sidebar-height`(面板几何;拖拽期间逐帧更新)。宿主推挤 = `#root` 的 `margin-right/width: calc(100% - var)`(v0.13.1+ 防桌面壳加性溢出)与 centerCol 的 `margin-bottom`;推挤锚点是**复合选择器**(同一元素双保险,禁止退回 `nth-child` 位置锚定):`#root [data-dsh-frame] > [data-pane="conversation"]` **与** `#root :has(> [data-slot="conversation"])`(0.1.x 命名 / rc.8 时代命名,live 页面实测同元素;`drag-layout.e2e.ts` 断言两者同元素)。 - **桌面信号与标题栏兼容**(v0.14.1+ 四选项模型,取代旧"win32 advanced 自动 32px"硬编码): - 壳信号(只读报告,不自动触发任何修改):URL `dsh-desktop-mode` / `dsh-desktop-platform`(DSH Desktop 壳注入;preload 另暴露 `__DSH_DESKTOP_FILE_PATH__`);可选契约参数 `dsh-desktop-titlebar-inset`(壳声明自己预留的顶栏像素,0–120,clamp;`parseDesktopEnv().titlebarInset`)。 @@ -616,7 +616,7 @@ interface OpenTabSeed { - **用户空间 CSS**:预设 css(`