Live portal: custom layouts are left alone — new streams chime and wait in a draggable tray; Arrange re-grids and returns to auto

layout store (auto/custom + pending), marked custom on manual move (onDidMovePanel outside arrange), sash drag,
stream/group rename. Tray chips: HTML5 drag accepted via onUnhandledDragOver/onDidDrop (position -> direction),
click = new column. WebAudio two-note chime. Gateway page instructions updated. Verified headless (custom vs auto).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-11-01 14:36:01 -06:00
parent b2e7e9a4bb
commit 645f447015
8 changed files with 115 additions and 13 deletions

23
live/src/Tray.jsx Normal file
View File

@@ -0,0 +1,23 @@
import React from 'react'
import { layout } from './layout.js'
import { streamLabel } from './names.js'
export const STREAM_MIME = 'application/x-vanguard-stream'
// Zero-height when empty. New streams in a custom layout wait here: drag a chip into the dock (any edge, any window,
// or onto a tab bar to stack), or click it to add it as a new column on the right.
export default function Tray({ onPlace }) {
const pending = layout.use(s => s.pending)
if (!pending.length) return null
return (
<div className="tray" title="new streams — drag into the layout, or click to add on the right">
{pending.map(s => (
<div key={s.id} className="chip" draggable
onDragStart={e => { e.dataTransfer.setData(STREAM_MIME, s.id); e.dataTransfer.setData('text/plain', s.id); e.dataTransfer.effectAllowed = 'move' }}
onClick={() => onPlace(s.id, { direction: 'right' })}>
<span className="blink">●</span> {streamLabel(s.id, s)}
</div>
))}
</div>
)
}