feat(grid): split-grid v2 — 1×3/2×3, drag-to-quadrant, Ctrl+` cycle, maximize
Builds on the v1 watch board: - Two more layouts: row-3 (1×3) and grid-6 (2×3). A single `grid` marker class on #term now carries the shared cell chrome so it no longer enumerates each lay-*. - Ctrl+` cycles the focused quadrant (Ctrl+Shift+` reverses); matchFocusCycleKey is an exported pure helper so it's unit-tested. No-op / passthrough in single mode. - Per-quadrant ⛶ maximize: the focused cell expands to fill the grid as an absolute overlay while siblings stay live behind it; follows focus, resets on layout change / tab close. - Drag a tab from the tab bar onto a quadrant to assign it there (reuses the existing tab-drag dragIndex); grid-only. Adversarial review (3 lenses → per-finding verify, incl. a headless-Chrome repro) caught a HIGH: maximizing via `grid-column/row: 1/-1` shoved siblings into implicit rows — a strip instead of fullscreen AND a spurious resize to backgrounded live PTYs. Fixed with an absolute-overlay (`position:absolute; inset:0`), then verified in real Chromium (Playwright): maximized cell fills #term, siblings 0px size delta. Also: silence a covered pane's pending pulse under maximize; coarse-pointer target for .cell-max. Verified: typecheck + build:web clean, 1579 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ import { mountDashboard } from './dashboard.js'
|
||||
import { mountHistory } from './history.js'
|
||||
import { mountShortcuts } from './shortcuts.js'
|
||||
import { mountShareSession } from './share.js'
|
||||
import { mountGridToggle } from './grid-layout.js'
|
||||
import { mountGridToggle, matchFocusCycleKey } from './grid-layout.js'
|
||||
|
||||
const paneHost = document.getElementById('term')
|
||||
const tabs = document.getElementById('tabs')
|
||||
@@ -59,6 +59,21 @@ document.addEventListener('visibilitychange', () => {
|
||||
if (!document.hidden) app.refitVisible()
|
||||
})
|
||||
|
||||
// v2: Ctrl+` cycles the focused quadrant in a split grid (Ctrl+Shift+` reverses).
|
||||
// Capture phase so xterm doesn't swallow it; left untouched (no preventDefault)
|
||||
// in single mode so the terminal keeps the keystroke.
|
||||
document.addEventListener(
|
||||
'keydown',
|
||||
(e) => {
|
||||
const dir = matchFocusCycleKey(e)
|
||||
if (dir === null) return
|
||||
if (app.getGridLayout() === 'single') return // let the terminal keep the key
|
||||
e.preventDefault()
|
||||
app.cycleFocus(dir)
|
||||
},
|
||||
{ capture: true },
|
||||
)
|
||||
|
||||
// Toolbar utilities.
|
||||
mountSearch(toolbar, {
|
||||
find: (query, dir) => app.findInActive(query, dir),
|
||||
|
||||
Reference in New Issue
Block a user