From 369ec8e2fd7cbc75d43c33b746e95397c80f21c2 Mon Sep 17 00:00:00 2001 From: megaproxy Date: Fri, 22 May 2026 18:18:56 +0100 Subject: [PATCH] Theme scrollbars + global broadcast toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- src/App.css | 9 +++++++++ src/App.tsx | 38 ++++++++++++++++++++++++++++++++++++++ src/lib/layout/tree.ts | 13 +++++++++++++ src/styles.css | 26 ++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/src/App.css b/src/App.css index eab9bdd..702340e 100644 --- a/src/App.css +++ b/src/App.css @@ -47,6 +47,15 @@ color: #cce6ff; border-color: #2a5a8c; } +.palette-btn.bcast-all.on { + background: #4a3010; + color: #f0c060; + border-color: #c98a1f; +} +.palette-btn.bcast-all.on.partial { + background: #2a2010; + color: #c98a1f; +} .preset-btn { min-width: 28px; text-align: center; diff --git a/src/App.tsx b/src/App.tsx index 5174ceb..7a4b5ef 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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() { + +