Skip to content

fix(console): #140 bug fixes + multi-session manager (tabs/dock/popout) - #141

Merged
sarg3nt merged 2 commits into
mainfrom
fix/bx-shell-icon-tools-column
May 18, 2026
Merged

fix(console): #140 bug fixes + multi-session manager (tabs/dock/popout)#141
sarg3nt merged 2 commits into
mainfrom
fix/bx-shell-icon-tools-column

Conversation

@sarg3nt

@sarg3nt sarg3nt commented May 18, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #140.

Started as the bug fixes from #140 (404 on shell icon, drop-to-Home navigation, Tools-column placement). User asked to bundle scope-creep QoL work in the same PR — multi-session/tabs/dock/popout/font-slider — since they prefer one big diff over many small ones. Result: full console-manager rewrite layered on top of the original fixes.

Bug fixes (original #140 scope)

  • d.idd.box_id at three call sites in static/js/bx/bx-page.js (cellClick, palette command id, palette run). BoxRow.JSONfield is box_id, not id — old code sent /api/console/undefined/capabilities → 404.
  • Guard grid.on('rowClick', …) against clicks originating in the Tools column. Tabulator fires rowClick from its own event delegation independent of DOM bubbling, so e.stopPropagation() inside cellClick was not enough.
  • Move shell icon out from between Name / Location into a right-anchored Tools column. Originally frozen: true; switched to unfrozen after the user pointed out the Tabulator divider was ugly.

Reusable console plumbing

static/js/console/console.js rewritten as a ConsoleSession (one PTY + xterm + WS) plus a ConsoleManager (chrome / tabs / layout / prefs). Sessions take a descriptor: { kind, boxID, … }. Adding container-exec for the future Docker gear means a new kind: 'container' case in wsURLForDescriptor + capsURLForDescriptor — the chrome and tabs come along for free.

Layouts

  • drawer — fullscreen overlay (the original behavior).
  • dock — pinned bottom strip, drag-resizable, height persisted to localStorage["gearbox.console.dockHeight"]. Pure-CSS sibling selector keeps the dock anchored to the right of the sidebar (#main-content.ml-16 ~ #console-drawer.console-layout-dock { left: 4rem }), with a transition: left 0.3s to track the sidebar's own collapse animation.
  • popoutwindow.open('/console/popout/{boxID}', '_blank', 'popup=yes …') opens a chromeless window driven by pages.ConsolePopoutPage. Authentication + per-box opt-in gating match APIConsoleCapabilities. In popout mode all chrome is hidden (.console-popout .console-header, .console-tab-bar, .console-dock-handle { display: none }) so the terminal fills the window.

Drawer ↔ dock are mutually exclusive — only the inactive layout's button is visible in the toolbar. Popout button stays put.

Tabs

  • Tab strip + per-tab close button, visible from the first session so the + new tab affordance is always discoverable.
  • Every click of the bx-grid shell icon spawns a new tab (no de-duping). The + button reuses the active tab's descriptor — "another shell into the same box."
  • Duplicate labels get a #N suffix at render time; closing one of two clones renames the survivor back.
  • Per-tab status dot (left of the label) doubles as the reconnect button: green = connected (inert), yellow = connecting, red = error (clickable → reconnect), gray = closed/idle. Connected dots are inert to avoid an accidental session rip.

Header + toolbar

  • "Console: <box>" prefix + box-name span + status/mode/uid pills all removed — the box name lives in the tab, the dot carries connection state, uid is recoverable with whoami, mode is a single value today (revisit if we add an SSH-bridge mode).
  • Toolbar: font-slider (10–24 px, persisted to localStorage, matches logs-viewer pattern), Clear, layout-switch (drawer-or-dock, mutually exclusive), popout, close.
  • Header padding tightened (py-2py-1), dock resize handle dropped from 6px → 5px.

Preferences

All under gearbox.console.*:

  • fontSize (int 10..24, default 13) — applied to all sessions immediately
  • dockHeight (int px, default 320, min 160)
  • layout ("drawer" | "dock", default "drawer") — popout is transient, never persisted

Files

gearbox/cmd/server/main.go                                           +5      route /console/popout/{boxID}
gearbox/internal/framework/handler/console_popout.go                 +46     NEW — popout page handler
gearbox/internal/framework/templates/components/console.templ        ~151    drawer chrome rewritten
gearbox/internal/framework/templates/pages/console_popout.templ      +69     NEW — chromeless popout page
gearbox/static/css/components/console.css                            +253    NEW — layouts, tabs, dot, handle
gearbox/static/js/bx/bx-page.js                                      ~59     bug fixes + Tools column
gearbox/static/js/console/console.js                                 ~1001   ConsoleSession + ConsoleManager

Test plan

  • Shell icon on the bx grid opens a console for the targeted box (no 404, no nav to Home).
  • Tools column on the right of the grid, no divider between Last checked and Tools.
  • Clicking the shell icon twice opens two tabs against the same box, labelled Light Hugger #1 / #2.
  • Closing one duplicate tab renames the survivor back to Light Hugger.
  • Closing the only tab closes the panel.
  • Per-tab dot is green when connected, red on error, clickable to reconnect when closed/errored.
  • Font slider changes the size live, persists across reload, applies to all sessions in the panel.
  • Drawer ↔ dock toggle: clicking the visible layout button swaps modes; only one layout button is visible at a time.
  • In dock mode, the panel sits to the right of the sidebar (does NOT cover it), drag handle resizes, the height survives a reload.
  • Collapsing the sidebar slides the dock left to meet it (transition synced).
  • Popout button opens a new chromeless window with no header / tabs / toolbar — just the terminal.
  • Cmd-W closes the popout window cleanly.
  • Esc closes the in-page console (or just the active tab in dock mode with ≥ 2 sessions); Esc is a no-op inside a popout window.
  • Permissions still gated: a user without box_console:view gets 403 on /console/popout/{boxID}.
  • A box with console_enabled: false returns 404 on /console/popout/{boxID} and the bx grid does not show the shell icon for it.

🤖 Generated with Claude Code

- Removed the console column from the grid and replaced it with a tools column for better organization.
- Updated the console opening logic to use box_id instead of id for consistency.
- Enhanced the console.js file to support multi-session management with a new ConsoleSession class.
- Improved the layout handling for console sessions, including dock and drawer modes.
- Added preference management for font size and dock height.
- Implemented a more robust session lifecycle management, including connection handling and error reporting.
Copilot AI review requested due to automatic review settings May 18, 2026 06:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 fixes the /bx console-launch regressions from #140 and introduces a rewritten multi-session console UI (tabs + dock + popout) built around a ConsoleSession/ConsoleManager architecture. It also adds a new server route + handler + templ page to support a chromeless console popout window.

Changes:

  • Fix bx-grid console actions: correct box_id usage, prevent Tools-cell clicks from triggering row navigation, and move the shell icon into a dedicated Tools column.
  • Replace the single-session console drawer JS with a multi-session manager supporting tabs, drawer/dock layouts, persisted preferences, and popout.
  • Add popout page plumbing (route, handler, templ page) and new console panel CSS (layouts, tabs, status dot, dock resize handle).

Reviewed changes

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

Show a summary per file
File Description
gearbox/static/js/console/console.js Rewritten console client into session/manager model with tabs, layout modes, popout integration, and persisted prefs.
gearbox/static/js/bx/bx-page.js Fixes console launch bugs (wrong ID field, rowClick interference) and adds a Tools column.
gearbox/static/css/components/console.css New stylesheet for console chrome: dock/drawer positioning, tabs, status dot, dock resize handle, popout mode.
gearbox/internal/framework/templates/components/console.templ Updates ConsoleDrawer markup for new toolbar/tab UI and loads console.css.
gearbox/internal/framework/templates/pages/console_popout.templ New standalone chromeless page that boots the console manager in popout mode.
gearbox/internal/framework/handler/console_popout.go New handler to serve the popout page with auth + box gating.
gearbox/cmd/server/main.go Registers /console/popout/{boxID} route.

Comment thread gearbox/static/js/console/console.js
Comment thread gearbox/static/js/console/console.js
Comment thread gearbox/static/js/console/console.js
Comment thread gearbox/static/js/console/console.js
Comment thread gearbox/internal/framework/templates/pages/console_popout.templ Outdated
Comment thread gearbox/internal/framework/templates/components/console.templ Outdated
Comment thread gearbox/static/css/components/console.css Outdated
- ARIA tab semantics: move role="tab" onto the label button so nested
  interactive elements (dot, close) are siblings of the tabbable element,
  not nested inside it. Wrapper is now role="presentation".
- Per-tab status dot: add aria-label that reflects current state and
  reconnect action; aria-disabled when inert.
- Toolbar buttons (clear, layout-drawer/dock/popout, close, +): add
  explicit aria-label; mark icon SVGs aria-hidden so screen readers
  don't try to announce path data.
- Capabilities fetch failures and websocket errors now also write a
  red [console] line into the xterm buffer, so a failing session
  isn't a silent black void — matches the existing 'err' frame path.
- Dock resize: switch from mouse events to Pointer Events with
  setPointerCapture/releasePointerCapture, plus blur and
  visibilitychange cleanups. Prevents stuck drag state when the mouse
  releases outside the window.
- Fix CSS selector for .xterm height: actual DOM is
  .console-xterm-pad > #console-xterm > .console-session-host > .xterm
  — old selector skipped the #console-xterm wrapper, so the rule was
  inert and the terminal didn't always fill its container.
- Popout templ doc comment was stale (mentioned overriding the close
  button); CSS now hides the entire header in popout mode, comment
  updated to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sarg3nt
sarg3nt merged commit 334c2e9 into main May 18, 2026
22 checks passed
@sarg3nt
sarg3nt deleted the fix/bx-shell-icon-tools-column branch May 28, 2026 16:59
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.

fix(bx): shell icon opens 404 then nav drops to Home; move icon to a Tools column

2 participants