jiangshirong/dsh-ui-panel-resize ↗★ 0

@dsh/ui-panel-resize

DSH plugin: a vertical resize/collapse grip for the conversation top header of the DeepSeek Harness Web GUI. 适合需要自由调整或折叠会话顶部区域以优化视觉空间的用户。

パッケージ
@dsh/ui-panel-resize
互換性
未検証
バージョン
1.1.0
ライセンス
MIT
最終更新
2026/09/29

インストール

検証済み bundle がないか、互換性チェックに失敗しています。先にリポジトリの説明を読んでください。 README 全文を読む ↗

ドキュメント

README 全文を読む ↗

description: "A vertical resize/collapse grip for the conversation top header: drag to resize, drag past the minimum to collapse."

@dsh/ui-panel-resize

English | 中文

DSH plugin license: MIT

A DSH (DeepSeek Harness) client plugin. Installed into a DSH profile, it adds a draggable bottom border to the Web GUI's conversation header. Topics: dsh · dsh-plugin · deepseek-harness · cordis-plugin · dsh-client-plugin

The gap it fills

The conversation header (session title + subagent / mode / background-job chips + the 对话 / 轨迹 tabs) is sized purely by its content and has no adjustment entry point at all: the cursor does not change at its bottom border, and there is no way to squeeze or hide it. This plugin turns that border into a draggable grip.

The sidebar's "drag past the minimum width to collapse" used to live here too and was removed — see Why not the sidebar.

Interaction

ActionResult
Move the pointer to the header's bottom bordercursor becomes row-resize and a small grip appears
Drag upthe header shrinks, overflowing content is clipped; floor is 44px (title row only)
Drag more than 40px above that floorthe grip turns blue and reads "release to collapse"
Release therethe header collapses to an 8px strip
While collapsed: click the stripexpands back to the previous height (or the natural one)
While collapsed: drag down more than 24pxsame as above
Drag downthe header grows, up to 160px above its natural height
Double-click the gripclears the manual height and returns to the natural one

A pill beside the grip shows the live height (xx px) and switches to the hint text once the collapse threshold is crossed.

Tuning (lib/client.js)

ConstantValueMeaning
HEADER_MIN44lowest visible height (keeps the title row, clips the tabs)
HEADER_COLLAPSE_SLACK40how far below that floor counts as "collapse"
HEADER_COLLAPSED8strip height while collapsed
HEADER_MAX_GROWTH160growth allowed above the natural height
HEADER_DRAG_SLOP3travel that turns a click into a drag
HEADER_RESTORE_TRAVEL24downward travel that expands a collapsed header

Implementation

Only stable DOM hooks are used: no hashed class names, and no React-managed subtree is mutated.

  • The header is located through [data-conversation-header-leading]'s parent (fallback: the widest header[data-window-drag]), marked with the plugin's own data-dsh-panel-resize="header", and sized through the --dsh-panel-resize-header-height custom property (!important, overriding the shipped min-height:76px).
  • The grip is a position: fixed element appended to document.body. Its geometry comes only from the header's own getBoundingClientRect() — deliberately: the header's parent is a slot host that may be display: contents (a zero-size border box), which is how an early build produced an invisible left:0;width:0 grip. The grip straddles the border: about 7px inside the header (inside the tab row's own bottom padding) and about 3px below. When a right panel owns its own track ([data-rightbar-col] wider than 0) the grip is clipped to the track's left edge.
  • The preference lives in localStorage['dsh.ui-panel-resize.header'] = {"height":number|null,"collapsed":boolean}.
  • Every node and listener is owned by ctx.effect(), so disabling or hot-replacing the plugin removes all of it. One `` tag carries the rules.

The plugin injects no service (inject: []); it is pure DOM chrome.

Install

git clone https://github.com/jiangshirong/dsh-ui-panel-resize.git
cd dsh-ui-panel-resize
powershell -ExecutionPolicy Bypass -File install.ps1

(pwsh -File install.ps1 is equivalent when PowerShell 7 is installed.)

The script copies this directory into %USERPROFILE%\.dsh\profiles\desktop\node_modules\@dsh\ui-panel-resize and adds the loader entry to %USERPROFILE%\.dsh\profiles\desktop\cordis.patch.yml (skipped when it is already there). It works from any directory, so an offline copy or an extracted archive is fine too.

Manual install (two steps)

  1. Copy this repository's directory to %USERPROFILE%\.dsh\profiles\desktop\node_modules\@dsh\ui-panel-resize.
  2. Append to %USERPROFILE%\.dsh\profiles\desktop\cordis.patch.yml:
- insert:
    - id: ui-panel-resize
      name: "@dsh/ui-panel-resize"
      disabled: false

insert is required: a row that only names an id and a name overrides an existing entry and is silently discarded when none exists.

The host Loader adds the entry immediately and the browser picks the bundle up through the module graph (HMR), normally without a restart. Edits to lib/client.js also reload on their own; only lib/index.js (the host half) needs a restart.

Uninstall

Remove the insert entry from cordis.patch.yml (or disable the entry in Settings → Plugins) and delete node_modules\@dsh\ui-panel-resize. Every DOM node and style tag goes away with the plugin.

Diagnostics

The browser half appends short codes to its own localStorage ring dsh.ui-panel-resize.trace (reset on every activation) and the host half mirrors it into %USERPROFILE%\.dsh\profiles\ \ui-panel-resize-trace.log. A page-side plugin has no devtools console, so this is its only reporting channel.

MarkerMeaning
A:applyclient half activated
`H:found:
`header located, `
= natural height, followed byanchors=/pos=`
H:handlegrip created
H:detach::live=the host replaced the header node; live=0 means the old one is detached
H:collapsed / `H:height:
/H:restore:*/H:reset`collapsed / sized / restored / reset
D:handle= / D:atHandle=one hit-test sample 1.2s after activation: grip geometry and the topmost element there
E:*an error, with type and message

Why not the sidebar

The first revision also collapsed the left sidebar when its width drag was released past the minimum (the ChatGPT gesture). It was removed because it does not hold up as a feature:

  1. The outcome was already one step away. Ctrl+B and the sidebar's own collapse control both hide the column. The implementation's own fallback path was to synthesize a Ctrl+B keypress — when a gesture's fallback is a single keystroke, the gesture adds no capability.
  2. It had a cost, not just zero benefit. By the shell's contract, collapsing forgets the dragged width and reopening returns to the default 280px. A previously safe action ("drag the width") became a destructive one: overshoot once and the column is gone along with the width you just set.
  3. Narrow-window semantics differ. Below 1024px, toggleSidebar() toggles the narrow "expanded over the centre" state instead, so the gesture and the shortcut are not equivalent.
  4. It was the only part of this plugin that had to fight React's drag lifecycle — intercepting pointerup in the capture phase, stopPropagation to stop the host writing its clamped width back, manually releasing the pointer capture, and re-asserting the collapse at 280/720ms. The riskiest, least maintainable code in the package, serving a duplicate feature.

The header has no equivalent entry point, so it stays.

Known limits

  • The grip is 10px tall and straddles the border: about 7px inside the header (inside the tab row's own bottom padding) and 3px below.
  • While the header is collapsed to its 8px strip the grip hides itself whenever the active main panel is not the conversation (for example the settings panel).
  • The height override re-measures the natural height when the header's class changes (blank session ↔ session); a manual height is re-clamped into the new legal range.