diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 4da6d20d..2b25d70e 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -54,6 +54,7 @@ function SettingsLayout(props: { onSearchUnFocus: (newSearch?: string) => void; selectedCategory: string | null; setSelectedCategory: (category: string | null) => void; + onCategoryChange?: (category: string | null) => void; }) { const { className } = props; const { t } = useTranslation(); @@ -105,6 +106,7 @@ function SettingsLayout(props: {
{props.children}
@@ -168,7 +170,6 @@ export function AccountSettings(props: { export function SettingsPage() { const [searchQuery, setSearchQuery] = useState(""); const [selectedCategory, setSelectedCategory] = useState(null); - const prevCategoryRef = useRef(null); const backendChangeModal = useModal("settings-backend-change-confirmation"); const [pendingBackendChange, setPendingBackendChange] = useState< string | null @@ -271,22 +272,6 @@ export function SettingsPage() { }; }, []); - // Scroll to top when category changes (but not on initial load or when searching) - useEffect(() => { - if ( - prevCategoryRef.current !== null && - prevCategoryRef.current !== selectedCategory && - !searchQuery.trim() - ) { - // Only scroll to top if we're actually switching categories (not initial load) - // Use requestAnimationFrame to ensure DOM has updated - requestAnimationFrame(() => { - window.scrollTo({ top: 0, behavior: "smooth" }); - }); - } - prevCategoryRef.current = selectedCategory; - }, [selectedCategory, searchQuery]); - const { t } = useTranslation(); const activeTheme = useThemeStore((s) => s.theme); const setTheme = useThemeStore((s) => s.setTheme); @@ -381,6 +366,21 @@ export function SettingsPage() { } }, []); + const handleCategoryChange = useCallback( + (category: string | null) => { + if (searchQuery.trim()) return; + const sectionId = category ?? "settings-account"; + setTimeout(() => { + scrollToElement(`#${sectionId}`, { + behavior: "smooth", + block: "start", + offset: 120, // Account for fixed search bar + }); + }, 100); // Wait for section to render after tab switch + }, + [searchQuery], + ); + const appLanguage = useLanguageStore((s) => s.language); const setAppLanguage = useLanguageStore((s) => s.setLanguage); @@ -983,6 +983,7 @@ export function SettingsPage() { onSearchUnFocus={handleSearchUnFocus} selectedCategory={selectedCategory} setSelectedCategory={setSelectedCategory} + onCategoryChange={handleCategoryChange} className="space-y-28" > {(searchQuery.trim() || diff --git a/src/pages/parts/settings/SidebarPart.tsx b/src/pages/parts/settings/SidebarPart.tsx index 0bada997..57f7d6f2 100644 --- a/src/pages/parts/settings/SidebarPart.tsx +++ b/src/pages/parts/settings/SidebarPart.tsx @@ -11,6 +11,7 @@ import { AppInfoPart } from "./AppInfoPart"; export function SidebarPart(props: { selectedCategory: string | null; setSelectedCategory: (category: string | null) => void; + onCategoryChange?: (category: string | null) => void; searchQuery: string; }) { const { t } = useTranslation(); @@ -102,6 +103,7 @@ export function SidebarPart(props: { // Set the selected category when clicking a sidebar link // null means "All Settings" - show all sections props.setSelectedCategory(id); + props.onCategoryChange?.(id); }, [props], );