From 96ce1c9e96339afe5a9ecb98d62fd5ceb8189a5f Mon Sep 17 00:00:00 2001 From: Investor Flow Build Date: Tue, 11 Aug 2026 23:25:51 -0400 Subject: [PATCH] fix: sync symbol input with focus ticker - Add searchQuery state to ConfluencePanel that tracks input value - Pass value={searchQuery} and onChange={setSearchQuery} to SymbolAutocomplete - Sync searchQuery when activeSymbol changes externally (from another panel) - Update SymbolAutocomplete onChange to call externalOnChange in controlled mode - Input now shows current symbol after pick and stays in sync --- app/src/components/ConfluencePanel.tsx | 23 ++++++++++++++++------- app/src/components/SymbolAutocomplete.tsx | 11 ++++++++--- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/app/src/components/ConfluencePanel.tsx b/app/src/components/ConfluencePanel.tsx index dcad813..b5c8d52 100644 --- a/app/src/components/ConfluencePanel.tsx +++ b/app/src/components/ConfluencePanel.tsx @@ -48,13 +48,20 @@ export function ConfluencePanel() { const activeSymbol = useActiveSymbol((s) => s.activeSymbol); const setActiveSymbol = useActiveSymbol((s) => s.setActive); const [symbol, setSymbol] = useState(activeSymbol); + const [searchQuery, setSearchQuery] = useState(activeSymbol); const [selectedRackId, setSelectedRackId] = useState(null); const pickSymbol = useCallback((sym: string) => { setSymbol(sym); + setSearchQuery(sym); setActiveSymbol(sym); }, [setActiveSymbol]); + // Sync searchQuery when activeSymbol changes externally (e.g., from another panel) + useEffect(() => { + setSearchQuery(activeSymbol); + }, [activeSymbol]); + // Racks const [racks, setRacks] = useState<{ system: Array<{ id: string; name: string }>; user: Array<{ id: string; name: string }> }>({ system: [], user: [] }); useEffect(() => { @@ -123,13 +130,15 @@ export function ConfluencePanel() {
- pickSymbol(raw.toUpperCase())} - placeholder="Search symbol…" - ariaLabel="Select symbol for signal confluence" - inputClassName="w-full bg-surface-sunken border border-line rounded-lg px-3 py-1.5 text-xs text-fg placeholder:text-fg-muted focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" - /> + pickSymbol(raw.toUpperCase())} + placeholder="Search symbol…" + ariaLabel="Select symbol for signal confluence" + inputClassName="w-full bg-surface-sunken border border-line rounded-lg px-3 py-1.5 text-xs text-fg placeholder:text-fg-muted focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" + />
{symbol && ( diff --git a/app/src/components/SymbolAutocomplete.tsx b/app/src/components/SymbolAutocomplete.tsx index 77e14f3..5f14c9e 100644 --- a/app/src/components/SymbolAutocomplete.tsx +++ b/app/src/components/SymbolAutocomplete.tsx @@ -82,11 +82,16 @@ export function SymbolAutocomplete({ }, [onBusyChange]); const onChange = useCallback((v: string) => { - setInternalQuery(v); - externalOnChange?.(v); + if (controlledValue !== undefined) { + // Controlled mode: let parent handle the value change + externalOnChange?.(v); + } else { + setInternalQuery(v); + externalOnChange?.(v); + } if (timerRef.current) clearTimeout(timerRef.current); timerRef.current = setTimeout(() => runSearch(v), 150); - }, [runSearch, externalOnChange]); + }, [runSearch, externalOnChange, controlledValue]); // Click-outside closes the dropdown. useEffect(() => {