diff --git a/src/components/TypeaheadInput.tsx b/src/components/TypeaheadInput.tsx index 1481332..21f854c 100644 --- a/src/components/TypeaheadInput.tsx +++ b/src/components/TypeaheadInput.tsx @@ -36,11 +36,47 @@ export function TypeaheadInput({ const [isLoading, setIsLoading] = useState(false); const [isExternalUpdate, setIsExternalUpdate] = useState(false); const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0, width: 0 }); + const [isDarkMode, setIsDarkMode] = useState(false); const inputRef = useRef(null); const suggestionsRef = useRef(null); const timeoutRef = useRef(undefined); + // Detect dark mode + useEffect(() => { + const checkDarkMode = () => { + // Check if dark class is on html or body element + const isDark = document.documentElement.classList.contains('dark') || + document.body.classList.contains('dark') || + // Fallback: check system preference + window.matchMedia('(prefers-color-scheme: dark)').matches; + setIsDarkMode(isDark); + }; + + // Initial check + checkDarkMode(); + + // Watch for changes to the dark class + const observer = new MutationObserver(checkDarkMode); + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ['class'] + }); + observer.observe(document.body, { + attributes: true, + attributeFilter: ['class'] + }); + + // Watch for system theme changes + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + mediaQuery.addEventListener('change', checkDarkMode); + + return () => { + observer.disconnect(); + mediaQuery.removeEventListener('change', checkDarkMode); + }; + }, []); + // Calculate dropdown position relative to viewport const calculateDropdownPosition = useCallback((): DropdownPosition => { if (!inputRef.current) { @@ -297,7 +333,8 @@ export function TypeaheadInput({ }, []); const baseInputClassName = ` - w-full px-3 py-2 border border-gray-300 rounded-lg + w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg + bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 ease-in-out ${className} @@ -307,17 +344,24 @@ export function TypeaheadInput({ const DropdownPortal = () => { if (!showSuggestions || suggestions.length === 0) return null; + // Theme-aware colors + const dropdownBgColor = isDarkMode ? 'rgba(31, 41, 55, 1)' : 'rgba(255, 255, 255, 1)'; // gray-800 : white + const borderColor = isDarkMode ? 'rgba(75, 85, 99, 1)' : 'rgba(209, 213, 219, 1)'; // gray-600 : gray-300 + return createPortal(
@@ -326,6 +370,11 @@ export function TypeaheadInput({ const label = suggestion.label || ''; const description = suggestion.description || ''; + // Theme-aware item colors + const itemBgColor = isSelected + ? (isDarkMode ? 'rgba(30, 58, 138, 0.3)' : 'rgba(239, 246, 255, 1)') // blue-900/30 : blue-50 + : dropdownBgColor; + return (
handleSuggestionClick(suggestion)} onMouseEnter={() => setSelectedIndex(index)} style={{ - backgroundColor: isSelected ? 'rgba(239, 246, 255, 1)' : 'rgba(255, 255, 255, 1)' + backgroundColor: itemBgColor }} >
{/* Main label */}
{label}
@@ -355,7 +412,9 @@ export function TypeaheadInput({ {/* Description */} {description && (
{description}
@@ -363,10 +422,16 @@ export function TypeaheadInput({ {/* Wikidata ID */}
- @@ -380,8 +445,8 @@ export function TypeaheadInput({
@@ -392,7 +457,9 @@ export function TypeaheadInput({ {/* Subtle bottom border for separation */} {index < suggestions.length - 1 && ( -
+
)}
);