diff --git a/frontend/src/components/ConfigureAmsSlotModal.tsx b/frontend/src/components/ConfigureAmsSlotModal.tsx index 0e83d4dbc..2136fe40c 100644 --- a/frontend/src/components/ConfigureAmsSlotModal.tsx +++ b/frontend/src/components/ConfigureAmsSlotModal.tsx @@ -1,4 +1,4 @@ -import { useState, useMemo, useEffect, useCallback } from 'react'; +import { useState, useMemo, useEffect, useCallback, useRef } from 'react'; import { useQuery, useMutation } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { X, Loader2, Settings2, ChevronDown, CheckCircle2, RotateCcw } from 'lucide-react'; @@ -242,6 +242,7 @@ export function ConfigureAmsSlotModal({ const [searchQuery, setSearchQuery] = useState(''); const [showSuccess, setShowSuccess] = useState(false); const [showExtendedColors, setShowExtendedColors] = useState(false); + const scrolledToRef = useRef(''); // Fetch cloud settings (gracefully handle 401 when logged out) const { data: cloudSettings, isLoading: settingsLoading, isError: cloudError } = useQuery({ @@ -735,6 +736,7 @@ export function ConfigureAmsSlotModal({ setColorInput(''); setSearchQuery(''); setShowSuccess(false); + scrolledToRef.current = ''; } }, [isOpen, slotInfo.savedPresetId, slotInfo.trayInfoIdx, slotInfo.trayColor, cloudSettings?.filament]); @@ -770,6 +772,17 @@ export function ConfigureAmsSlotModal({ } }, [isOpen, handleKeyDown]); + // Scroll selected preset into view only when the selection changes (not on every render). + // Inline callback refs cause scrollIntoView to fire every render, which on Windows + // creates an infinite scroll loop due to scroll → re-render → scrollIntoView cycles. + useEffect(() => { + if (selectedPresetId && selectedPresetId !== scrolledToRef.current) { + scrolledToRef.current = selectedPresetId; + const el = document.querySelector(`[data-preset-id="${CSS.escape(selectedPresetId)}"]`); + el?.scrollIntoView({ block: 'nearest' }); + } + }, [selectedPresetId]); + if (!isOpen) return null; const isLoading = (settingsLoading && !cloudError) || localLoading || builtinLoading || kprofilesLoading; @@ -889,9 +902,7 @@ export function ConfigureAmsSlotModal({ filteredPresets.map((preset) => (