A corner press during a return ended the return at the recorded
rectangle, so the panel jumped without pointer travel. The press now
picks the panel up where it is drawn for a resize as well: the resize
keeps the drawn origin and caps only the corner by the viewport, and the
release records the legal rectangle and springs the origin inside, as a
resize whose viewport shrank past its origin also does. Under reduced
motion a resize draws its legal rectangle and animates nothing.
- Move TabBody to its own module and draw DockSurface's docked bodies
through it too, so divider and tab drags no longer re-render bodies.
- State in TabRenderer when the kit calls renderTab again and reuses a
body.
- A corner press during a return ends it at the recorded rectangle; only
a grip press picks the panel up where it is drawn.
- The resistance and its inverse keep the legal size, a resize origin
stays inside a viewport that shrank mid-gesture, and a Windows root
without a published caption height keeps the 20px floor.
- The Web e2e waits for the resting style before checking the clamp.
- Tests say "does not re-render" and also show that a new renderer
re-renders the bodies.
A float drag and its return update the preview through React state, so
TabLayout re-rendered every TabHost and called renderTab for every
retained body on each frame. Both renderers now draw bodies through
TabBody, memoized on the renderer and the tab record, so such a frame
re-renders only panel frames and headers.
Measured in the Web e2e scaffold under 4x CPU throttling (median of 5,
60-step drag past the corner, then the return): with a 4000-line file
preview floating, drag scripting fell from 592 ms to 100 ms and the
return's from 180 ms to 56 ms; with the default small preview, drag
scripting fell from 121 ms to 95 ms.
The resting .float rule now caps width at 100vw and height at the
viewport below the caption floor, so a stale viewport reading cannot
leave an oversized panel's header controls or resize corner off screen.
Vertical limits use 100dvh, which follows window.innerHeight as the
gesture hook does. The Web e2e publishes a far-off, oversized resting
rectangle and checks that the stylesheet alone draws it over the viewport.
- A release that reaches the press's legal rectangle only raises, so a
click on a panel drawn projected no longer records a move or resize.
- The return starts at the drawn panel's speed, and launchVelocity caps
its outward part so the whole trajectory stays within 120 px.
- A panel larger than the viewport draws at the viewport's size, keeping
its header controls and resize corner reachable.
- A return ends on an undo, dock or close of its panel, and at its target
when another panel is pressed; a gesture uses the bounds of a window
resized mid-gesture; drawn samples outside the velocity window drop.
- Gestures and returns may draw above the top floor; at rest the .float
rule clamps every panel into the viewport and below the caption floor.
- Web e2e drags a Sidebar float past the right and bottom edges.
- The note is renamed to spring-based edge recovery, compressed, and
cross-linked to the docking and retained-layout notes.
Reading scrollLeft in the layout cleanup also captures positions that fire no
scroll event, such as a restore the browser clamps to the current offset.
Refs #7049
Each tab host draws its own strip while selected, so every open, close, or
selection mounted a strip at offset 0 that then glided across the whole row
to the active chip. Record each pane's chip-box offset in TabLayout, jump a
new strip to it, and glide only the remaining distance; a first placement
with no recorded offset jumps.
Refs #7049
The recall watcher now tolerates a short quiet window so a report that arrives before a CSS transition moves anything cannot end the loop on its first unchanged sample, re-arms on a transition or animation that touches a marked row, and re-arms on a child list change in a container holding one. A dock picture withdraws its strip's drag claim while a pane floats, because a float sorted before that row would otherwise sit earlier in the document and lose its own subtraction. The settings panel closes when an onboarding step appears, since the step's overlay marks only #root inert. Prose and the two Agent Notes record the Windows narrowing of the Platform overlay return bar, the collection rule, and the rows' one home in the ui-theme manifest.
Conflict resolutions:
- ui-dockkit TabPanel: keep upstream's reworked tab strip and re-add the row's
`data-window-drag` mark on `css.tabStrip`.
- ui-sidebar-right SidebarRight.tsx/.module.css: keep upstream's retention
rewrite and re-delete its hand-written one-frame app-region pulse; the shell's
window-drag watcher owns recollection.
- ui-settings-general/package.json: keep upstream's `@deepseek-ai/dsh-settings`
dev dependency and this branch's `react-dom`.
- tsconfig.host.json: take upstream's `files: []`; client sources belong to the
client aggregate.
- pnpm-lock.yaml: master's lock plus only the react-dom importer entries.
Route file, terminal, browser, split, fullscreen, close, and refresh commands to the focused panel. Connect native Desktop page and window actions to the same command owners.
Co-authored-by: 神河一号 - 烈焰流光 <[email protected]>
The macOS window's draggable area was a hand-written band: a 52px strip, deepened
to 76px by a marker the Conversation header had to keep in step with its own
height. It drifted from the layout — blank runs inside a chrome row did not drag,
and a control a few pixels away dragged the window instead.
Chrome rows now mark their own element (`data-window-drag`) and the shell declares
the surface once (`html[data-platform='darwin'] [data-window-drag]`), so a row's own
box is its draggable geometry and no fixed band has to match any row's height. The
frame band, its 52/76 figures, the marker, and the per-sheet drag rules are gone;
interactive controls and overlays portal beside `#root` where one rule subtracts
them.
Recollection becomes one shell watcher (`window-drag/recall.ts`): Electron rebuilds
the window's drag rects only when a computed app-region value changes
(electron#32341), so the watcher measures every marked row each frame while the
surface moves, sets `data-window-drag-recall` for the frames whose geometry changed,
and clears it on the frame that finds the geometry settled. The right panel's
hand-written pulse is deleted with it.
Coverage is a contract with executable parts. `window-drag/regions.ts` publishes the
composition rule and the interactive selector that both the sheet and its spec
compare against; the ui-theme gate asserts the package tree declares drag in exactly
two places and pairs every row's mark with its sheet, selector, and authored height;
and the browser lane boots the shipped composition in Chromium with the darwin
marker to assert per-row geometry, a content body under a marked head row, a
covering overlay, and the watcher's pulse. The plugin manager's detail views mark
the head row they share rather than the pane they render in, so their text and form
labels stay content.
Both real machines agree: the macOS matrix ran on a real `hiddenInset` window with
HID-level pointer input and window-frame readback, and the Windows matrix on a
Windows 11 ARM64 VM — chrome rows drag, content and the covering overlay do not,
and the controls keep their clicks.
Refs #4619
Drop the fullscreen panel's whole-box no-drag: it swallowed the strips'
blank-run window drag and made no-drag the steady state, turning the
open/close app-region nudge into a computed-value no-op (electron#32341)
exactly when a hidden panel opens straight into fullscreen. The panel now
declares no steady-state app-region in either presentation, and ui-dockkit
subtracts the one box base.css never matches — the plain-div split divider —
alongside tabs, strip-end chrome, and pane bodies. New specs pin both
contracts against the stylesheets on disk.
Seed sidebar default pages lazily on expansion, scope page-tab dedupe
to the target pane, let a sole tab split its own pane with a factory
backfill, close menus when focus enters a sandboxed iframe, and pin the
code preview copy banner while unifying its background with the pane.
Chip capsules with scroll fades and live titles, drop-zone hint cards, the
canCloseTab control policy with the quiet lone chip and self-dismissing empty
menu, and a room reading that stays independent of hidden split controls.