diff --git a/electron/src/renderer/src/components/FloatingToolbar.tsx b/electron/src/renderer/src/components/FloatingToolbar.tsx index eb31c795..15d10075 100644 --- a/electron/src/renderer/src/components/FloatingToolbar.tsx +++ b/electron/src/renderer/src/components/FloatingToolbar.tsx @@ -76,7 +76,10 @@ if (typeof document !== 'undefined' && !document.getElementById(STYLE_ID)) { '@keyframes spyde-pop-up{from{opacity:0;transform:translate(-50%,6px)}to{opacity:1;transform:translate(-50%,0)}}' + '.spyde-tb-btn{background:none;border:none;color:#cdd6f4;cursor:pointer;width:30px;height:30px;' + 'border-radius:6px;display:flex;align-items:center;justify-content:center;transition:background 90ms}' + - '.spyde-tb-btn:hover{background:rgba(137,180,250,0.18)}' + '.spyde-tb-btn:hover:not(:disabled){background:rgba(137,180,250,0.18)}' + + // A disabled button still matches :hover, so without this the locked + // buttons keep lighting up under the cursor and read as clickable. + '.spyde-tb-btn:disabled{cursor:not-allowed}' document.head.appendChild(s) } @@ -220,6 +223,11 @@ export function FloatingToolbar({ if (!shown.length) return null const click = (a: ToolbarAction) => { + // Locked window (a progressive batch is still filling this tree): the + // button is rendered `disabled` so this should be unreachable, and the + // backend refuses the action regardless — belt and braces against a stale + // config, since the cost of getting it wrong is a node on a half-built tree. + if (a.disabled) return if (live.has(a.name)) { sendAction('set_action_active', { name: a.name, active: false }, windowId) setOpenName(null) @@ -303,10 +311,25 @@ export function FloatingToolbar({ return (