diff --git a/src/uix/soma/components/words/words-provider.svelte.ts b/src/uix/soma/components/words/words-provider.svelte.ts index 983c097a7..1359ce6fb 100644 --- a/src/uix/soma/components/words/words-provider.svelte.ts +++ b/src/uix/soma/components/words/words-provider.svelte.ts @@ -530,25 +530,22 @@ export class WordsProvider { if (this.shouldIgnoreTransientSelectionCollapse(next, root, options.source ?? 'direct')) { return false; } - // Clear the atomic-block highlight only when the text selection - // genuinely moved AND landed OUTSIDE the wrapper of the currently - // selected atomic. Synthetic selectionchange echoes that arrive - // right after `selectAtomicBlock` (which doesn't actually move - // the DOM caret) would otherwise wipe the highlight a tick - // later, defeating the click. Same intent for nested atomics - // inside a column: when the engine drops the caret into the - // column's trailing paragraph after `insertImage`, the new - // selection is still inside the SAME top-level wrapper as the - // selected image — don't clear in that case (the inspector needs - // to keep showing the image panel until the user moves to a - // different top-level block). + // Clear the atomic-block highlight whenever the text selection + // genuinely moves. We used to keep the highlight sticky when the + // new caret was in the SAME top-level wrapper as the selected + // atomic (so the image inspector would stay open while editing + // the trailing paragraph in the same column). That sounded clever + // but in practice users were left staring at the wrong inspector + // panel — they clicked somewhere new, the inspector didn't + // follow. Inspector-as-a-source-of-truth wins: every move that + // the engine accepts as a real selection change ALSO clears the + // atomic highlight. The user re-selects the atomic via a fresh + // click on the figure if they want its panel back. + // We still skip the clear when `sameWordsSelection` reports + // no-op so synthetic selectionchange echoes can't wipe the + // highlight a tick after `selectAtomicBlock` set it. if (!sameWordsSelection(this.selection, next)) { - const selectedTopIdx = - this.selectedBlockPath?.[0] ?? this.selectedBlockIndex; - const nextTopIdx = next.anchor.path[0]; - if (selectedTopIdx === undefined || nextTopIdx !== selectedTopIdx) { - this.clearSelectedBlock(); - } + this.clearSelectedBlock(); } this.updateSelection(next); return true;