diff --git a/src/panel/Panel.tsx b/src/panel/Panel.tsx index c7393c4..7ff0700 100644 --- a/src/panel/Panel.tsx +++ b/src/panel/Panel.tsx @@ -1,5 +1,6 @@ import { useState, useEffect, useCallback, useRef } from 'react'; import type { TabState, TimelineEvent } from '@/types'; +import { DEBUGGER_TOGGLE_FEEDBACK_MS, REDUX_SEARCH_TIMEOUT_MS } from './constants'; import { UIStateTab } from './tabs/UIStateTab'; import { PerformanceTab } from './tabs/PerformanceTab'; import { SideEffectsTab } from './tabs/SideEffectsTab'; @@ -136,7 +137,7 @@ export function Panel() { type: newEnabled ? 'ENABLE_DEBUGGER' : 'DISABLE_DEBUGGER', tabId, }); - setTimeout(() => setIsTogglingDebugger(false), 3000); + setTimeout(() => setIsTogglingDebugger(false), DEBUGGER_TOGGLE_FEEDBACK_MS); }, [tabId, isDebuggerEnabled]); const handleTabChange = useCallback((newTab: TabId) => { @@ -145,7 +146,7 @@ export function Panel() { if (newTab === 'redux' && !state.reduxDetected) { setIsSearchingRedux(true); safeSendMessage({ type: 'SEARCH_REDUX', tabId }); - setTimeout(() => setIsSearchingRedux(false), 5000); + setTimeout(() => setIsSearchingRedux(false), REDUX_SEARCH_TIMEOUT_MS); } }, [tabId, state.reduxDetected]); diff --git a/src/panel/constants.ts b/src/panel/constants.ts new file mode 100644 index 0000000..6faf315 --- /dev/null +++ b/src/panel/constants.ts @@ -0,0 +1,22 @@ +/** + * Timeout constants for UI feedback (spinners, toast-like states). + * Values tuned for perceived responsiveness without flicker. + */ + +/** Feedback duration for short UI actions (scan toggle, dispatch button) */ +export const UI_FEEDBACK_SHORT_MS = 800; + +/** Feedback duration for medium UI actions (refresh, monitor toggle) */ +export const UI_FEEDBACK_MEDIUM_MS = 1000; + +/** Feedback for debugger enable/disable — longer because background work continues */ +export const DEBUGGER_TOGGLE_FEEDBACK_MS = 3000; + +/** Time to wait for Redux store auto-detection */ +export const REDUX_SEARCH_TIMEOUT_MS = 5000; + +/** Correlation analysis feedback */ +export const CORRELATION_FEEDBACK_MS = 3000; + +/** Snapshot creation feedback (short — operation is fast) */ +export const SNAPSHOT_CREATE_FEEDBACK_MS = 500; diff --git a/src/panel/tabs/MemoryTab.tsx b/src/panel/tabs/MemoryTab.tsx index eddbee1..b81e737 100644 --- a/src/panel/tabs/MemoryTab.tsx +++ b/src/panel/tabs/MemoryTab.tsx @@ -1,5 +1,6 @@ import { useState, useEffect, useMemo } from 'react'; import type { MemoryReport, CrashEntry } from '@/types'; +import { UI_FEEDBACK_MEDIUM_MS } from '../constants'; interface MemoryTabProps { report: MemoryReport | null; @@ -38,7 +39,7 @@ export function MemoryTab({ report, tabId }: MemoryTabProps) { type: newState ? 'START_MEMORY_MONITORING' : 'STOP_MEMORY_MONITORING', tabId, }); - setTimeout(() => setIsTogglingMonitor(false), 1000); + setTimeout(() => setIsTogglingMonitor(false), UI_FEEDBACK_MEDIUM_MS); }; useEffect(() => { diff --git a/src/panel/tabs/PerformanceTab.tsx b/src/panel/tabs/PerformanceTab.tsx index 4ea6ff8..6b4e173 100644 --- a/src/panel/tabs/PerformanceTab.tsx +++ b/src/panel/tabs/PerformanceTab.tsx @@ -1,6 +1,7 @@ import { useMemo, useState } from 'react'; import type { Issue, ComponentInfo, RenderInfo, PageLoadMetrics } from '@/types'; import { IssueCard } from '../components/IssueCard'; +import { UI_FEEDBACK_SHORT_MS } from '../constants'; interface PerformanceTabProps { issues: Issue[]; @@ -50,7 +51,7 @@ export function PerformanceTab({ issues, components, renders, tabId, pageLoadMet type: 'TOGGLE_SCAN', payload: { enabled: newState }, }); - setTimeout(() => setIsTogglingScan(false), 800); + setTimeout(() => setIsTogglingScan(false), UI_FEEDBACK_SHORT_MS); }; const renderStats = useMemo(() => { diff --git a/src/panel/tabs/ReduxTab.tsx b/src/panel/tabs/ReduxTab.tsx index 44e86c4..bbbea1a 100644 --- a/src/panel/tabs/ReduxTab.tsx +++ b/src/panel/tabs/ReduxTab.tsx @@ -1,5 +1,6 @@ import type { ReduxAction } from '@/types'; import { useCallback, useState } from 'react'; +import { UI_FEEDBACK_SHORT_MS, UI_FEEDBACK_MEDIUM_MS } from '../constants'; interface ReduxTabProps { detected: boolean; @@ -37,7 +38,7 @@ export function ReduxTab({ detected, state, actions, tabId, isSearching }: Redux type: 'REFRESH_REDUX_STATE', tabId, }); - setTimeout(() => setIsRefreshing(false), 1000); + setTimeout(() => setIsRefreshing(false), UI_FEEDBACK_MEDIUM_MS); }, [tabId]); const clearOverrides = useCallback(() => { @@ -139,7 +140,7 @@ if (process.env.NODE_ENV === 'development') { } catch { setDispatchError('Invalid JSON payload'); } - setTimeout(() => setIsDispatching(false), 800); + setTimeout(() => setIsDispatching(false), UI_FEEDBACK_SHORT_MS); }; const togglePath = (path: string) => { diff --git a/src/panel/tabs/TimelineTab.tsx b/src/panel/tabs/TimelineTab.tsx index b188917..cfe697b 100644 --- a/src/panel/tabs/TimelineTab.tsx +++ b/src/panel/tabs/TimelineTab.tsx @@ -1,5 +1,6 @@ import { useState, useMemo, useCallback, useRef, useEffect } from 'react'; import type { TimelineEvent, TimelineEventType, RenderEventPayload, StateChangeEventPayload, EffectEventPayload, ErrorEventPayload, MemoryEventPayload, CorrelationResult, ContextChangeEventPayload } from '@/types'; +import { CORRELATION_FEEDBACK_MS, SNAPSHOT_CREATE_FEEDBACK_MS } from '../constants'; interface TimelineTabProps { events: TimelineEvent[]; @@ -89,7 +90,7 @@ export function TimelineTab({ events, tabId, onClear }: TimelineTabProps) { setIsCorrelating(false); } ); - setTimeout(() => setIsCorrelating(false), 3000); + setTimeout(() => setIsCorrelating(false), CORRELATION_FEEDBACK_MS); }, [tabId]); const clearCorrelation = useCallback(() => { @@ -139,7 +140,7 @@ export function TimelineTab({ events, tabId, onClear }: TimelineTabProps) { }; setSnapshots(prev => [...prev, newSnapshot]); - setTimeout(() => setIsCreatingSnapshot(false), 500); + setTimeout(() => setIsCreatingSnapshot(false), SNAPSHOT_CREATE_FEEDBACK_MS); }, [events]); const exportSnapshot = useCallback((snapshot: TimelineSnapshot) => {