feat(ui): floating widget windows (shell capability), enable for Image Map - #39
Open
lstein wants to merge 1 commit into
Open
feat(ui): floating widget windows (shell capability), enable for Image Map#39lstein wants to merge 1 commit into
lstein wants to merge 1 commit into
Conversation
lstein
marked this pull request as draft
August 2, 2026 22:23
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 2, 2026 22:38
0da5cc5 to
5fb4304
Compare
lstein
force-pushed
the
feat/image-map-06-floating
branch
2 times, most recently
from
August 3, 2026 01:38
035de15 to
d36b46d
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
2 times, most recently
from
August 3, 2026 02:26
599acac to
72b3041
Compare
lstein
force-pushed
the
feat/image-map-06-floating
branch
from
August 3, 2026 02:26
d36b46d to
0a64ade
Compare
lstein
marked this pull request as ready for review
August 3, 2026 18:28
lstein
force-pushed
the
feat/image-map-06-floating
branch
from
August 4, 2026 01:43
0a64ade to
a58e9c7
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 4, 2026 01:43
72b3041 to
8030e09
Compare
lstein
force-pushed
the
feat/image-map-06-floating
branch
from
August 4, 2026 05:37
a58e9c7 to
d7e56a7
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 4, 2026 05:37
8030e09 to
0be308f
Compare
lstein
force-pushed
the
feat/image-map-06-floating
branch
from
August 4, 2026 14:58
d7e56a7 to
925649a
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
2 times, most recently
from
August 4, 2026 22:32
8f0e63b to
e4f4132
Compare
lstein
force-pushed
the
feat/image-map-06-floating
branch
2 times, most recently
from
August 5, 2026 00:31
08aa934 to
ef19bf0
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 5, 2026 00:31
e4f4132 to
408ef0c
Compare
lstein
force-pushed
the
feat/image-map-06-floating
branch
from
August 5, 2026 00:38
ef19bf0 to
8666f99
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 5, 2026 00:38
408ef0c to
7259190
Compare
lstein
force-pushed
the
feat/image-map-06-floating
branch
from
August 5, 2026 01:18
8666f99 to
dc89f69
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 5, 2026 01:18
7259190 to
3726790
Compare
…e Map Adds a generic floating-window layer to the workbench shell. Any widget can opt in via `manifest.allowFloating`; the Image Map is the first user. - New per-project state: `floatingWidgets` maps instance ids to geometry, mode (windowed/maximized/shaded), z-order, and the region to dock back into. Additive and optional, so persisted projects hydrate unchanged. - Reducer actions: floatWidget (detaches from its region and repairs the active instance), dockFloatingWidget (returns it as the region's active widget), setFloatingWidgetGeometry (min-size clamped), setFloatingWidgetMode, focusFloatingWidget (raise). Placing a floating instance back into a region via openRegionWidget implicitly docks it so an instance can never render twice. - FloatingWidgetWindow: fixed-position chrome with title-bar drag and corner resize (same raw-pointer commit-on-release pattern as the panel resize handles), shade/maximize/dock buttons, double-click-to-shade, viewport clamping so a window can never be stranded off-screen, and the standard widget renderer (bare, chrome-less) as its body. - "Float Window" lives in the shared widget actions menu, gated on the manifest flag. Amended during the rebase onto the re-architected webv2: - Types moved from the deleted `workbench/types.ts` into the split contract files: `FloatingWidgetMode`/`FloatingWidgetState` live in `layoutContracts.ts`, `allowFloating` on `WidgetManifest` and the 'floating' member of `WorkbenchRegion` in `widgetContracts.ts`, and `Project.floatingWidgets` + `ProjectUndoSnapshot.floatingWidgets` in `projectContracts.ts`. `WidgetRegion` stays untouched — floating instances are tracked solely in `Project.floatingWidgets`. - The reducer action union is private on main, so the five floating actions join `WorkbenchReducerAction` in `workbenchState.ts` and are surfaced as mechanical commands in the `widgets` namespace of `createCommands()`: `widgets.float`, `widgets.dockFloating`, `widgets.focusFloating`, `widgets.setFloatingGeometry`, `widgets.setFloatingMode`. All components now call `useWorkbenchCommands()` instead of the removed `useWorkbenchDispatch`. - The three feature-local structural mirrors of `WorkbenchRegion` (gallery's `GalleryWidgetProps`, queue's view props, workflow's `WorkflowRegion`) gained 'floating', as their drift-check design demands. - `FloatingWidgetWindow` resolves the widget via `useWorkbenchWidgetRegistry()`, renders through main's existing `WidgetRendererById`, titles via `resolveWidgetInstanceLabel`, uses `IconButton`/`Tooltip` from `@platform/ui`, adopts the AbortController pointer-session idiom from `WidgetFrames.tsx`, and takes all chrome strings from new i18n keys under `widgets.floating` (en.json). - `FloatingWidgetLayer` lazy-loads the window chrome (`React.lazy`) so it stays out of the shell's eager path; the layer itself mounts eagerly in the rewritten `WorkbenchShell` after `StatusBar`, inside the DndContext. - Reducer tests rewritten against the `workbenchState.testing` facade (mirroring `workbenchState.test.ts`) with the renamed 'compose' preset; the widget-command mocks in `createWidgetRuntime.test.ts` and `widgetPlacementCommands.test.ts` implement the five new commands. - `floatingWindows.ts` registered in `workbenchOwnershipManifest.json` rootFiles; architecture and browser performance baselines recaptured for the intended new eager bytes (commands + layer mount; window chrome stays lazy). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lstein
force-pushed
the
feat/image-map-06-floating
branch
from
August 5, 2026 01:21
dc89f69 to
b3136de
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 5, 2026 01:21
3726790 to
43542e6
Compare
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.
Summary
PR 6 of the Image Map stack. Adds a generic floating-window layer to the workbench shell — any widget can opt in via
manifest.allowFloating; the Image Map is the first user.Project.floatingWidgetsmaps instance ids to geometry, mode (windowed/maximized/shaded), z-order, and the region to dock back into. Additive + optional, so persisted projects hydrate unchanged; the field round-trips through project persistence and is captured/restored withwidgetRegionsin undo snapshots (they are one placement fact).floatWidget(detaches from its region, repairs the active instance),dockFloatingWidget,setFloatingWidgetGeometry(min-size clamped),setFloatingWidgetMode,focusFloatingWidget. Invariant: an instance never renders docked and floating at once — placing a floating instance into a region implicitly docks it, and applying a layout preset docks all floating widgets.clamp()keeps a grabbable sliver on-screen even for geometry persisted on a larger display. z-index derives from stacking rank, not the persisted monotonic counter, so long-lived projects can never climb past the UI library's layer tokens.An adversarial review of this diff was run; all confirmed findings are fixed with regression tests: preset-apply/undo double-render and widget-loss holes, off-screen stranding, z-token decay, double-click-on-button shading, non-main-button drags, plus the lint failures the review caught (my earlier lint invocation masked a failing format step — now verified by exit code).
Known accepted gaps (documented for reviewers): floating bodies don't participate in focus-region/hotkey attribution (irrelevant for Image Map, which registers no hotkeys — flagged for future floatable widgets); mid-drag unmount leaves window listeners until the next global pointerup (self-healing).
Testing
16 reducer/helper tests: float/dock round-trips, active-instance repair, geometry clamps, mode/no-op semantics, z-rank raising, preset-docking, undo consistency (widget is exactly one of docked/floating), viewport clamp math. Full suite: 885+ tests,
pnpm lint+pnpm buildpass.🤖 Generated with Claude Code