diff --git a/components/text-selection-toolbar.tsx b/components/text-selection-toolbar.tsx index fcd2f576..6cef6538 100644 --- a/components/text-selection-toolbar.tsx +++ b/components/text-selection-toolbar.tsx @@ -331,7 +331,20 @@ export function TextSelectionToolbar() { return null; } - if (!toolbarPos || !selectedText) return null; + // The share dialog deliberately OUTLIVES the selection that opened it: + // onChat snapshots the passage and then calls finishAction, which clears + // selectedText. Rendered only below the guard, it would never mount — the + // component returns null on that same render, and the dialog would appear + // on the next selection instead, when selectedText is non-empty again. + // + // The other surfaces avoid this by using saveAndClearSelection, which keeps + // selectedText in state; this one lets the selection go entirely. + const shareToChat = + chatQuote !== null ? ( + setChatQuote(null)} /> + ) : null; + + if (!toolbarPos || !selectedText) return shareToChat; // ─── Action handlers ────────────────────────────────────────────────── @@ -628,12 +641,7 @@ export function TextSelectionToolbar() { selectedText={selectedText} /> - {chatQuote !== null && ( - setChatQuote(null)} - /> - )} + {shareToChat} ); }