dsh-width-tiers
Chat content-width tiers for the DeepSeek Harness Web GUI.
English | 中文
Tiers
| Tier | Content width | Sidebar |
|---|
| Standard 标准 | App default: max(680px, min(column × 0.64, 920px)) | unchanged |
| Medium 中等 | 1120px | unchanged |
| Wide 宽 | 1280px | unchanged |
| Ultra 超宽 | 1400px | unchanged |
| Full 全宽 | max(640px, column − 176px) | collapsed to icon rail |
| Custom 自定义 | width recorded from a native drag | unchanged |
Fixed and custom widths are clamped by the app to
max(640px, column − 176px); the standard tier follows the app default
(680–920px). On a narrow window a wider fixed tier therefore behaves like
full, and the menu shows the reachable maximum for fixed tiers (1280px
reads 640px on an 800px column).
Features
- Uses the app's native width axis (
--dsh-chat-user-width and
dsh.conversation.contentWidth), so the built-in drag handles keep working.
- Persists the selected tier and restores it on the next visit.
- Follows Settings → Language (中文 / English / 日本語 / Español / Français / Deutsch / Русский / Português), including the Settings plugin card's title and summary (
locale/<lang>.json).
- Menu supports ArrowUp/Down, Home/End, Escape and Tab, with focus restoration.
- Tier changes sync across tabs.
- Respects
prefers-reduced-motion.
- Never touches the right panel. Only
full collapses the left sidebar, and
you can expand it again at any time.
Install
dsh plugin --profile web add dsh-width-tiers
Restart dsh web, then hard-refresh the page. A six-bar picker appears at the
bottom-right.
For a local checkout:
dsh plugin --profile web add link:/path/to/dsh-width-tiers
Usage
- Click the picker and choose a tier.
- Picking
Custom before the first drag opens a guide at the right edge; drag
a native handle to record a width.
- Dragging any native handle switches to
Custom; the plugin steps aside while
you drag.
Standard clears the width preference and returns to the app default.
Full collapses the left sidebar; the icon rail stays available.
How it works
- Mounts the picker into the frame-wide
shell.overlay slot; the plugin fiber
owns the controller lifetime, so no listeners or timers outlive it.
- The controller publishes an immutable snapshot (tier, menu, guide); the React
picker renders it and dispatches actions, so the view can remount without
rebuilding observers.
- Locates the conversation body that declares
--dsh-chat-content-width
(prefers [data-conversation-content], skips the right sidebar's embedded
conversation), then writes --dsh-chat-user-width on its parent.
- Stores the configured target in the app preference; only the inline width is
clamped to
max(640px, column − 176px).
- Watches the column with
ResizeObserver so full follows sidebar, rightbar
and window changes.
- Drives panels through
ctx.layout and registers copy through ctx.locale.
Compatibility
- DSH Web 0.2.x with a
web profile (shell.overlay slot and slots service).
- Width axis checked against DSH 0.2.2-alpha.3: 640px floor, 176px handle
budget,
--dsh-chat-* variables, data-width-handle, layout/locale services.
- Narrow screens: the picker hides while alpha.3's sidebar drawer
(
data-sidebar-drawer) is open and follows the on-screen keyboard.
Development
pnpm install
pnpm build # src/ -> lib/ (host entry + loader-wrapped client bundle)
pnpm typecheck
pnpm test # vitest: controller (jsdom) + picker component suites
pnpm verify:client
The sources live in src/ (src/index.ts is the no-op host entry, the
feature lives in src/client/); lib/ is the built, published payload. The
vitest suites import the sources directly: the controller runs under jsdom and
the picker is rendered with Testing Library, so no live DSH instance is
required. verify:client checks the built bundle contract. Development needs
Node 22+ and pnpm.
Notes
- Wider fixed tiers are clamped on narrow windows.
- A custom width dragged on a narrow window is clamped by the app before it is
recorded.
License
MIT — see LICENSE. Copyright (c) 2026 aaronlei.