Skip to content

feat: Windows 11-like snap behavior for Window component - #9

Merged
MegaBlackLabel merged 2 commits into
mainfrom
feature/window-snap-behavior
Jun 9, 2026
Merged

MegaBlackLabel merged 2 commits into
mainfrom
feature/window-snap-behavior

Conversation

@MegaBlackLabel

Copy link
Copy Markdown
Owner

Summary

Implement Windows 11-like drag snapping for the Window component with 8 snap zones and blue preview overlay.

Changes

  • New: Snap geometry module (src/hooks/snap.ts) with 8 zones
  • New: Snap lifecycle in useDraggable (preview, commit, cleanup)
  • New: Snap props snapEnabled (default: true) and snapThreshold (default: 20)
  • New: Blue semi-transparent preview overlay during drag
  • New: z-index management for multi-window scenarios
  • New: Snap release when dragging away from edge
  • New: pointercancel and unmount cleanup handlers
  • Fix: 1px jitter on odd viewport sizes
  • Tests: 262 passing tests
  • Docs: Storybook snap scenarios

Supported Snap Zones

  • Left/Right half (50% width)
  • Top/Bottom half (50% height)
  • Four corners (25% each)

Checklist

  • Tests pass (262/262)
  • Build passes
  • Library build passes
  • Storybook builds
  • No scope leaks

Copilot Review

Waiting for Copilot review. Please do not merge until review is complete and approved.

- Add snap geometry module (src/hooks/snap.ts) with 8 zones
- Extend useDraggable with snap lifecycle (preview, commit, cleanup)
- Add snap props to Window (snapEnabled, snapThreshold)
- Render blue semi-transparent preview overlay during drag
- Implement z-index management for multi-window scenarios
- Add snap release when dragging away from edge
- Add pointercancel and unmount cleanup handlers
- Fix 1px jitter on odd viewport sizes
- Add comprehensive tests (262 passing)
- Add Storybook snap scenarios

Supported snap zones: left, right, top, bottom, top-left,
top-right, bottom-left, bottom-right

Closes window snap behavior feature
Copilot AI review requested due to automatic review settings June 9, 2026 13:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Windows 11-style drag snapping to the Window component, including 8 snap zones (halves + corners), a blue preview overlay during drag, and lifecycle hooks in useDraggable to preview/commit/cleanup snapping.

Changes:

  • Introduces snap-zone geometry (getSnapTarget) with min-size gating and odd-viewport split handling.
  • Extends useDraggable and Window to support snap preview (snapTarget) and snap commit (position + size).
  • Updates Storybook and tests to cover snap preview/commit/cancel/unmount cleanup scenarios.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/hooks/useResizable.ts Exposes setSize in the hook result so Window can programmatically apply snapped dimensions.
src/hooks/useDraggable.ts Adds snap state (snapTarget), snap detection on pointermove, commit on pointerup, and cancel/unmount cleanup.
src/hooks/useDraggable.test.ts Adds unit tests for pointer capture, snap targeting, commit behavior, pointercancel, and unmount cleanup.
src/hooks/snap.ts Implements snap-zone detection + target rectangle calculation for 8 zones.
src/hooks/snap.test.ts Adds unit tests validating zones, thresholds, min size gating, and odd viewport splits.
src/components/window/Window.wiring.test.tsx Verifies Window wires snap options and commits snap target to size/position.
src/components/window/Window.tsx Adds snapEnabled/snapThreshold, snap commit handling, snap preview overlay, and local z-index raising on drag start.
src/components/window/Window.test.tsx Adds integration tests for preview rendering, snap commit outcomes, z-index raising, and drag-from-snapped restore behavior.
src/components/window/Window.stories.tsx Adds Storybook snap playground/scenarios and documents supported snap scope.
src/components/window/Window.module.css Adds styling for the blue snap preview overlay.
src/components/window/TitleBar.test.tsx Adds test asserting Restore renders as a button when maximized.
.storybook/main.ts Adjusts Vite config via viteFinal (disables CSS minification for Storybook build).

Comment thread src/hooks/useDraggable.ts
Comment thread src/components/window/Window.tsx
Comment thread src/components/window/Window.tsx
Comment thread src/components/window/Window.tsx
Comment thread src/components/window/Window.tsx
Comment thread src/hooks/useResizable.ts
Comment thread src/hooks/useDraggable.ts
- Fix listenersRef stale closure pattern in useDraggable
- Simplify setSizeConstrained to only enforce minWidth/minHeight
- Remove viewport clamping from setSize that caused position override issues
- Clean up duplicate code remnants from previous edits
@MegaBlackLabel

Copy link
Copy Markdown
Owner Author

@copilot レビューお願いします。前回のフィードバックを修正しました。

Copilot AI commented Jun 9, 2026

Copy link
Copy Markdown

@copilot レビューお願いします。前回のフィードバックを修正しました。

確認しました。前回の指摘はまだすべては解消されていません。少なくとも useDraggable では releasePointerCapture のガードが未追加で、flushSync 後も最新のリスナーではなく当該レンダー時点の onPointerMove / onPointerUp / onPointerCancel を登録しています。加えて WindowactiveZIndex は依然として各インスタンスのローカル state のままで、親からの zIndex 更新や複数ウィンドウ間の前面化は解決していません。

@MegaBlackLabel
MegaBlackLabel merged commit 658fb37 into main Jun 9, 2026
1 check passed
@MegaBlackLabel
MegaBlackLabel deleted the feature/window-snap-behavior branch June 9, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants