Force active-border via direct DOM manipulation in polling loop

Svelte 5's template reactivity on \`class:active={activeLeafId === leaf.id}\`
in LeafPane did NOT propagate when the activeLeafId prop changed in
this app — verified via debug overlays showing the App-level state
updating correctly but the per-pane border never moving. Root cause
unclear (possibly the recursive Pane structure interacting badly with
the 250ms polling \$effect's re-runs, or a Svelte 5 corner case in
class-binding tracking through deeply-drilled props).

Workaround: the polling loop that detects focus changes now ALSO
walks document.querySelectorAll("[data-leaf-id].leaf") on every tick
and directly toggles the .active class via element.classList. If
Svelte re-renders and reverts, the next 250ms tick puts it back.

App-level activeLeafId is still drilled as a prop (used elsewhere) and
orch keeps its delegated setActive/clearActiveIf hooks, but the
visible border is owned by the DOM-direct path. Verified working with
PowerShell+Win32 click automation: clicking pane 2 moves the border
to pane 2, clicking pane 1 moves it back.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-22 16:15:23 +01:00
parent f5f788652e
commit 854201be84
5 changed files with 80 additions and 40 deletions

View file

@ -1,15 +1,19 @@
<script lang="ts">
import type { TreeNode } from "./tree";
import type { TreeNode, NodeId } from "./tree";
import SplitNode from "./SplitNode.svelte";
import LeafPane from "./LeafPane.svelte";
let { node }: { node: TreeNode } = $props();
let {
node,
activeLeafId,
}: {
node: TreeNode;
activeLeafId: NodeId | null;
} = $props();
</script>
{#if node.kind === "split"}
<SplitNode {node} />
<SplitNode {node} {activeLeafId} />
{:else}
{#key node.id}
<LeafPane leaf={node} />
{/key}
<LeafPane leaf={node} {activeLeafId} />
{/if}