From 24c753f6e6b65e887eafce71492215a867a245d3 Mon Sep 17 00:00:00 2001 From: Celes Renata Date: Wed, 29 Apr 2026 16:54:19 +0000 Subject: [PATCH] fix: debounce ticker search on Trends page to preserve input focus The TickerFilter triggered a query on every keystroke, causing re-renders that stole focus from the input. Now uses a local input state with a 300ms debounce before updating the query, keeping focus on the text box while typing. --- frontend/src/pages/Trends.tsx | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/Trends.tsx b/frontend/src/pages/Trends.tsx index 433f622..0befa3d 100644 --- a/frontend/src/pages/Trends.tsx +++ b/frontend/src/pages/Trends.tsx @@ -1,7 +1,7 @@ -import { useState } from 'react'; +import { useState, useRef, useEffect } from 'react'; import { useNavigate, Link } from '@tanstack/react-router'; import { useTrends, useDocument } from '../api/hooks'; -import { TrendArrow, ConfidenceBar, LoadingSpinner, TickerFilter, Card } from '../components/ui'; +import { TrendArrow, ConfidenceBar, LoadingSpinner, Card } from '../components/ui'; import type { TrendSummary } from '../api/hooks'; const WINDOWS = ['intraday', '1d', '7d', '30d', '90d']; @@ -9,8 +9,17 @@ const WINDOWS = ['intraday', '1d', '7d', '30d', '90d']; export function TrendsPage() { const navigate = useNavigate(); const [ticker, setTicker] = useState(''); + const [debouncedTicker, setDebouncedTicker] = useState(''); const [window, setWindow] = useState(undefined); - const { data, isLoading } = useTrends({ ticker: ticker || undefined, window, limit: 100 }); + const inputRef = useRef(null); + + // Debounce ticker search — only query after 300ms of no typing + useEffect(() => { + const timer = setTimeout(() => setDebouncedTicker(ticker), 300); + return () => clearTimeout(timer); + }, [ticker]); + + const { data, isLoading } = useTrends({ ticker: debouncedTicker || undefined, window, limit: 100 }); if (isLoading) return ; @@ -19,7 +28,15 @@ export function TrendsPage() {

Trends

- + setTicker(e.target.value.toUpperCase())} + className="w-24 rounded-md border border-surface-700 bg-surface-900 px-2 py-1 text-xs text-gray-200 placeholder-gray-500 focus:border-brand-500 focus:outline-none" + aria-label="Filter by ticker" + />