refactor(outline): extract resize-handle into a sibling module - #306
Merged
Conversation
Carve the runtime window-splitter resize concern out of OutlinePanel into a self-contained createResizeHandle() factory (resize-handle.ts), mirroring the settings-popover.ts / build-outline.ts extractions. The handle owns its drag state, width-clamp math, persisted-width restore/seed, and every --quoll-outline-sidebar-width write; it reaches back into the panel only through a small typed deps set (hover-close scheduling, focus-out dismiss, Escape-close) and exposes el + isResizing() + destroy(). No behaviour change — the full outline test suite stays green. outline-panel.ts drops ~200 lines.
Add a behaviour test asserting a boundary pointerleave during an active (unpinned) drag does not close the overlay — pinning the new isResizing() cross-module seam (scheduleClose's mid-drag guard). Verified non-vacuous: stripping the isResizing() term from scheduleClose turns this test red.
The extracted module restated the same facts in its file header and two in-body blocks. Trim the in-body restatements to their location-specific content; the file header is the single authoritative description. No code change.
…ess arrow wrappers) The module's own pointer/keydown handlers are free functions that never touch `this`, so the `(e) => fn(e)` forwarding wrappers (a carryover from the class form) are pure indirection. Bind the named functions directly. No behaviour change; the deps-callback listeners stay as explicit arrows by intent.
…Index The comment de-dup over-trimmed and dropped the one non-duplicated fact explaining why el.tabIndex=0 is a safe permanent tab stop: CSS display:none evicts the closed handle from the tab order, mirroring the inert sidebar.
…anel-keyboard-resize
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Extracts the outline sidebar's runtime resize concern out of
OutlinePanelinto a self-contained sibling module,src/webview/cm/outline/resize-handle.ts, mirroring the existingsettings-popover.ts/build-outline.ts/icons.ts/update-config-sink.tsextractions.Addresses the "Split
outline-panel.ts" cleanup TODO (from PR #245 review). The TODO named two blocks — keyboard-tree nav and the resize handle; this PR ships the resize handle and defers the keyboard-tree block as a designed follow-up (see below).Why the resize handle, not both
resizing/resizePointerId/resizeMoved), the--quoll-outline-sidebar-widthwrites, and the persisted-width restore/seed are touched by resize methods only. It reaches back into the panel through a small typeddepsset (hover-close scheduling, focus-out dismiss, Escape-close) and exposesel+isResizing()+destroy().rows,collapsedFroms,tabbableFrom,pendingFocusedFrom— withrenderList/updateActive/toggleCollapse/rebuild/update(). A clean extraction needs a designed ownership boundary for that shared state, not a naive method-move; that belongs in its own PR (follow-up TODO added).Residual size
outline-panel.tswas 1470 lines (the TODO's cited 1049 predated later a11y work), so neither block — nor both — gets it "meaningfully under 500". The Done-when's "documented rationale for the residual size" is the operative branch. This PR takes it from 1470 → 1266 (−204); new module is 291 lines.Notable
While wiring, found a fifth panel↔resize coupling point the initial analysis missed:
scheduleClose()reads the drag state to no-op mid-drag (live in happy-dom, wheresetPointerCaptureis a no-op so pointer boundary events still fire during a drag). Preserved it behaviour-identically via a read-onlyisResizing()on the handle rather than dropping the guard.Verification
DEFAULT_WIDTH_PXis re-exported fromoutline-panel.ts(a styles.css parity contract test imports it there).pnpm compile(4 tsconfigs) ✅pnpm build✅pnpm lint(changed files) ✅pnpm test:unit✅ 4154 passedpnpm test:browser✅ 35 passed (incl. real-Chromium resize-drag geometry)🤖 Generated with Claude Code