dsh-webchat-anchor-fix
A one-rule fix for a geometry bug in
@jaychang1989/dsh-webchat: after
a fullscreen/windowed toggle the DeepSeek panel can keep the size and position of
the window state it came from, until the guest is reloaded or reopened.
The upstream package is untouched and keeps tracking its own releases. This is a separate package that styles the DSH web surface's own document.
The bug
webchat keeps the guest in a fixed-position overlay and copies the panel's box into it from JavaScript:
syncBounds(host)reads.dsh-wc-host.getBoundingClientRect()and writes inlineleft,top,width,height;- it runs on mount, from a
ResizeObserver, and on windowresize; - the overlay itself is never laid out by the shell, so when a fullscreen transition outruns the copy, the overlay stays at the old numbers.
Because the copy is a JavaScript step, there is a window in which the panel has already moved and the overlay has not. Nothing in the current design closes that window; a missed event leaves it open indefinitely.
The fix
The copy is removed from the loop. One stylesheet:
@supports (anchor-name: --dsh-webchat-anchor) {
.dsh-wc-host {
anchor-name: --dsh-webchat-anchor;
}
body:has(.dsh-wc-host) [data-dsh-webchat-overlay] {
left: anchor(--dsh-webchat-anchor left) !important;
top: anchor(--dsh-webchat-anchor top) !important;
width: anchor-size(--dsh-webchat-anchor width) !important;
height: anchor-size(--dsh-webchat-anchor height) !important;
}
}
The browser resolves those four values on every layout. The overlay follows the
panel through fullscreen, windowed, sidebar and resize changes with no
listeners, no timers, no ResizeObserver and no JavaScript after mount.
!important is not a shortcut: webchat writes the four properties inline, and an
important author declaration is the only declaration in the cascade that
outranks a normal inline one.
body:has(.dsh-wc-host) keeps the geometry rule inert when no panel host exists,
so an overlay left behind for any reason still gets webchat's own inline values.
What it touches
- One
<style>element in the DSH web surface's document. - Nothing inside the DeepSeek page: the webview is never read, written, or
messaged. No
insertCSSinto the guest, noexecuteJavaScript. - No network requests, no cookies, no
localStorage/sessionStorage, no user-agent changes. - No layout mode, paint or stacking overrides: only the four geometry properties and the anchor name.
That boundary matters. The panel bug is a DSH-side layout issue; the DeepSeek page's risk-control conversation is not this package's business.
Contract and failure mode
Two webchat hooks are used, both public-facing:
- the class
.dsh-wc-hoston the panel host div; - the attribute
[data-dsh-webchat-overlay]on the guest overlay div.
If a future release renames either, the rules stop matching and the overlay falls back to webchat's inline geometry — exactly today's behaviour. The fix goes dormant, it does not break the panel.
@supports provides the second failure mode: an engine without CSS anchor
positioning ignores the whole block. The client half logs one console warning
so the dormancy is visible.
Known limit
This aligns the overlay to the panel element that exists. If the panel element itself is laid out at the wrong size (a shell-level layout bug rather than a missed copy), the overlay will faithfully track the wrong box. In that case the bug is upstream in the app shell, not in webchat's sync.
Verify
npm test # stylesheet shape and restraint, plus bundle registration
npm run test:anchor # layout behaviour in headless Edge/Chromium
npm run verify # both
test:anchor builds a fixture shaped like the DSH shell with deliberately stale
inline geometry, then moves the layout three ways, resizes the viewport, hides
and shows the overlay, and removes and re-creates the host — all without calling
into the package. Every step is measured against the host's own rect.
Install
With DSH fully closed:
dsh plugin --profile desktop add https://github.com/dhdkfkfkf/dsh-webchat-anchor-fix/releases/download/v0.1.0/dsh-webchat-anchor-fix-0.1.0.tgz
Restart DSH once so the profile boot picks up the new bundle. Mainland China:
prefix the URL with https://gh-proxy.com/.
Caution: install this only if a fullscreen or window toggle actually leaves the panel at the old bounds. If the panel behaves, the fix has nothing to correct. It is independent of any skin and installs nothing else.
Local development: npm pack, then
dsh plugin --profile desktop add <path-to-tgz>.
Unofficial; not affiliated with DeepSeek or Anthropic.
No comments yet. Be the first to write one.