Skip to content

Replace WinBox with native Vue scratchbook component#22095

Draft
dannon wants to merge 13 commits intogalaxyproject:devfrom
dannon:scratchbook-styling
Draft

Replace WinBox with native Vue scratchbook component#22095
dannon wants to merge 13 commits intogalaxyproject:devfrom
dannon:scratchbook-styling

Conversation

@dannon
Copy link
Member

@dannon dannon commented Mar 13, 2026

Summary

  • Removes the third-party WinBox library and replaces it with a native Vue ScratchbookWindow component and Pinia store
  • Styling matches Galaxy's GModal aesthetic (rounded corners, white header, layered shadow, clean typography)
  • Adds minimize support with taskbar-style stacking at the bottom of the viewport
  • Clamps window drag/resize to viewport bounds
  • Includes localStorage persistence (built on Persist scratchbook windows across page reloads #22088)

Depends on #22088 — should be merged after that PR lands.

Still WIP, more polish and testing to come.

dannon added 13 commits March 12, 2026 22:14
WindowManager now tracks open windows in a Map and serializes their
metadata (title, url, position, size) to localStorage. On app startup,
restore() reopens any previously saved windows at their last
position/size. Saves are debounced to avoid thrashing during drag/resize.
The original URL is stored before _build_url mangles it so
hide_panels/hide_masthead params don't double-accumulate on restore.
Four Playwright/Selenium tests covering restore-after-reload,
multiple windows, closed-not-restored, and partial-close scenarios.
Scratchbook iframes load the full Galaxy app with hide_masthead=true,
which was triggering restore() inside the iframe, opening nested windows
that would recurse infinitely. Only restore in the top-level app where
the masthead is visible.
One progressive test instead of four separate ones, each doing their own
uploads. Also adds debounce waits before reloads to fix the CI timing
failures where saves hadn't flushed yet.
Replaces the plain JS WindowManager class with a reactive Pinia store
that tracks window state, handles persistence to localStorage (ported
from the persistent-scratchbook branch), and provides the same public
interface (active, add, toggle, beforeUnload) so Galaxy.frame compat
is straightforward.
Draggable, resizable floating window rendered with position:fixed and
scoped styles matching the GModal aesthetic (rounded corners, white
header, soft layered shadow, clean typography). Drag is delta-based
via mousedown/mousemove on the header; resize via a bottom-right
handle. Focus management uses an iframe overlay that passes through
pointer events on the focused window.
App.vue now uses useWindowManagerStore and renders ScratchbookWindow
components directly instead of delegating to the WinBox-based
WindowManager class. Galaxy.frame still points to the store for
backward compat with router-push, ContentItem, and ChatGXY. Masthead
test updated to use a plain windowTab object instead of importing the
old WindowManager.
Drop the winbox npm package, delete window-manager.js and windows.scss,
remove the SCSS import from base.scss. Update navigation YAML selectors
and Selenium test helpers to use the new .scratchbook-window class
names. The core.windows.yaml tour still references #winbox-1 which
will need a follow-up update.
Scratchbook iframes load Galaxy with hide_masthead=true. Without this
guard, the inner App.vue would call restore(), read the parent's saved
windows from localStorage, and create windows inside itself recursively.
Gate both the store setup and window rendering on showMasthead.
Minimized windows collapse to just their title bar and stack
horizontally along the bottom edge, matching WinBox's minimize
behavior. Clicking a minimized window's header restores it.
Prevents windows from being dragged off-screen or resized beyond the
viewport edges, matching WinBox's default boundary behavior.
The old #winbox-1 ID no longer exists now that WinBox has been
replaced with a native Vue component.
}

&.scratchbook-window-close:hover {
background: var(--color-red-100, #fee2e2);
Copy link
Contributor

Choose a reason for hiding this comment

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

The color default should be in the theme imo.

</template>

<style scoped lang="scss">
.scratchbook-window {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably use WindowManager consistently instead of Scratchbook. Over the past years me and others referred to this feature as the window manager, which fits better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants