Repository navigation
feat(floating-workspace): add a dedicated titlebar grab handle - #46
Merged
Merged
Conversation
The floating workspace titlebar doubles as its move target, but once enough tabs fill the strip every press lands on a sortable tab — a no-drag target — so there is nowhere left to grab and the panel cannot be moved. Reserve a fixed-width handle at the far left of the titlebar, outside the tab strip, so it stays pressable no matter how many tabs are open. It relies on pointer events bubbling to the existing titlebar drag handlers, stays a plain div because `button` is a no-drag selector, and draws the same right border as the inter-tab dividers so the strip reads as one set of separators. Covered by unit tests for the handle's drag-target classification and a hidden renderer E2E that opens the panel with more tabs than fit, drags the handle, and asserts the panel moves.
nplez1
added a commit
that referenced
this pull request
Oct 1, 2026
The floating workspace titlebar doubles as its move target, but once enough tabs fill the strip every press lands on a sortable tab — a no-drag target — so there is nowhere left to grab and the panel cannot be moved. Reserve a fixed-width handle at the far left of the titlebar, outside the tab strip, so it stays pressable no matter how many tabs are open. It relies on pointer events bubbling to the existing titlebar drag handlers, stays a plain div because `button` is a no-drag selector, and draws the same right border as the inter-tab dividers so the strip reads as one set of separators. Covered by unit tests for the handle's drag-target classification and a hidden renderer E2E that opens the panel with more tabs than fit, drags the handle, and asserts the panel moves.
nplez1
added a commit
that referenced
this pull request
Oct 6, 2026
The floating workspace titlebar doubles as its move target, but once enough tabs fill the strip every press lands on a sortable tab — a no-drag target — so there is nowhere left to grab and the panel cannot be moved. Reserve a fixed-width handle at the far left of the titlebar, outside the tab strip, so it stays pressable no matter how many tabs are open. It relies on pointer events bubbling to the existing titlebar drag handlers, stays a plain div because `button` is a no-drag selector, and draws the same right border as the inter-tab dividers so the strip reads as one set of separators. Covered by unit tests for the handle's drag-target classification and a hidden renderer E2E that opens the panel with more tabs than fit, drags the handle, and asserts the panel moves.
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.
ELI5
The floating workspace window is moved by dragging its titlebar. When you have a lot of tabs open, the tabs cover the whole titlebar, so there is nowhere left to grab and the window feels stuck. This adds a small dedicated handle at the far left of the titlebar that you can always grab to move the window.
What Changed
Before: the floating workspace titlebar is the drag surface, but every press inside it is run through a "no-drag" selector, and tabs match that selector (a press on a tab starts a tab reorder). With enough tabs open, the entire titlebar is tab surface and the panel cannot be moved.
After: a fixed-width (24px) handle sits at the far-left edge of the titlebar, outside the tab strip. It shows a grip icon, uses a grab cursor, and always starts a panel move. It draws the same right border as the inter-tab dividers, so the strip reads as one continuous set of separators.
Mechanism: the handle is rendered as the first child of the titlebar in
FloatingTerminalPanelSurface, before theTabBar. Pointer events bubble to the existing titlebar drag handlers (onPointerDown/Move/Up), so no new drag logic is added. It is a plaindiv— the no-drag selector includesbutton— and the tab strip is a flex sibling, so the handle's width is reserved up front and can never be covered by tabs.Why
The window move gesture already exists; the only defect is that nothing is guaranteed to be left uncovered as the tab count grows. The alternatives were worse:
flex-[0_1_auto]layout and with dnd-kit, and could itself become a tab-adjacent reorder target.Linked Issue
N/A — fork-local UI change; no tracking issue exists.
Visual Proof
Light mode, same titlebar with more tabs than fit. Swipe/tab between the two:
Dark mode:
Screenshots come from a headless Electron renderer (
ORCA_BACKGROUND_LAUNCH=1, no visible window, no focus change).Testing
pnpm test src/renderer/src/components/floating-terminal— 18 files / 148 tests pass, including the new handle unit test and the titlebar-order regression assertion.tests/e2e/floating-workspace-titlebar-grab.spec.ts— hidden-renderer E2E that opens the floating workspace with 14 tabs, asserts the handle is visible and left of the tab strip, then drags it with real mouse input and asserts the panel moved (>30px).pnpm tc,npx oxlint,oxfmt --check, andpnpm run check:code-quality:changed(0 new findings, design-system gate included).Platforms: macOS (headless Electron E2E). The change is renderer-only DOM/CSS with no platform-specific behavior — no modifier-key handling, no file paths, no shells — so it is platform-neutral; SSH/remote is unaffected because the drag is in-page pointer handling over the overlay, not an Electron window API.
AI Disclosure
Implemented with DeepSeek Flash via the pi coding agent.
Review
Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)