Theme scrollbars + global broadcast toggle

Two small QoL additions:

- styles.css: WebKit pseudo-element styling for .xterm-viewport
  scrollbars (8px wide, dark thumb #2a2a2a on transparent track,
  hover lighten). Matches the rest of the dark theme so the right
  edge of each terminal stops looking like default OS chrome.

- tree.ts: setAllBroadcast(root, on) helper that flips every leaf's
  broadcast flag to the given value, preserving object identity
  where nothing changed.

- App.tsx: titlebar 📡 button showing global broadcast state
  ("all off" / "all on" / "N/M"). Click toggles every pane between
  all-broadcasting and all-off. Orange when any panes are
  broadcasting; darker orange when partial.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-22 18:18:56 +01:00
parent 774b8633dc
commit 369ec8e2fd
4 changed files with 86 additions and 0 deletions

View file

@ -21,6 +21,7 @@ import {
changeDistro,
changeLabel,
toggleBroadcast as toggleBroadcastInTree,
setAllBroadcast,
serialize,
deserialize,
presetSingle,
@ -282,6 +283,29 @@ export default function App() {
[paletteOpen, tree],
);
// ---- global broadcast state (derived from tree) -------------------------
const broadcastStats = useMemo(() => {
let on = 0;
let total = 0;
for (const leaf of walkLeaves(tree)) {
total++;
if (leaf.broadcast) on++;
}
return { on, total };
}, [tree]);
const toggleBroadcastAll = useCallback(() => {
// If any pane is broadcasting, turn them all off. Otherwise turn them all on.
setTree((t) => setAllBroadcast(t, broadcastStats.on === 0));
}, [broadcastStats.on]);
const broadcastBtnLabel =
broadcastStats.on === 0
? "📡 all off"
: broadcastStats.on === broadcastStats.total
? "📡 all on"
: `📡 ${broadcastStats.on}/${broadcastStats.total}`;
const onPalettePick = useCallback((leafId: string) => {
setActiveLeafId(leafId);
setPaletteOpen(false);
@ -321,6 +345,20 @@ export default function App() {
<button className="preset-btn" title="2 × 2 grid" onClick={() => applyPreset(presetTwoByTwo)}>2×2</button>
</span>
<button
className={`palette-btn bcast-all${broadcastStats.on > 0 ? " on" : ""}${broadcastStats.on > 0 && broadcastStats.on < broadcastStats.total ? " partial" : ""}`}
onClick={toggleBroadcastAll}
title={
broadcastStats.on === 0
? "Click to broadcast input to ALL panes"
: broadcastStats.on === broadcastStats.total
? "All panes broadcasting — click to disable"
: `${broadcastStats.on} of ${broadcastStats.total} panes broadcasting — click to disable all`
}
>
{broadcastBtnLabel}
</button>
<button
className="palette-btn"
onClick={() => setPaletteOpen(true)}