From b6a8028eff77f6d071e7dbb4eefd268d86ec77d4 Mon Sep 17 00:00:00 2001 From: Pas <74743263+Pasithea0@users.noreply.github.com> Date: Sat, 8 Nov 2025 12:39:28 -0700 Subject: [PATCH] refactor and simplify search bar positioning --- src/pages/Settings.tsx | 34 +++++++---------------- src/pages/parts/home/HeroPart.tsx | 45 +++++++++---------------------- 2 files changed, 22 insertions(+), 57 deletions(-) diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index a1639b68..8d390c74 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -1,7 +1,7 @@ import classNames from "classnames"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useAsyncFn, useWindowSize } from "react-use"; +import { useAsyncFn } from "react-use"; import { base64ToBuffer, @@ -33,6 +33,7 @@ import { RegisterCalloutPart } from "@/pages/parts/settings/RegisterCalloutPart" import { SidebarPart } from "@/pages/parts/settings/SidebarPart"; import { PageTitle } from "@/pages/parts/util/PageTitle"; import { AccountWithToken, useAuthStore } from "@/stores/auth"; +import { useBannerSize } from "@/stores/banner"; import { useLanguageStore } from "@/stores/language"; import { usePreferencesStore } from "@/stores/preferences"; import { useSubtitleStore } from "@/stores/subtitles"; @@ -56,30 +57,13 @@ function SettingsLayout(props: { const { t } = useTranslation(); const { isMobile } = useIsMobile(); const searchRef = useRef(null); - const { width: windowWidth, height: windowHeight } = useWindowSize(); + const bannerSize = useBannerSize(); - // Dynamic offset calculation like HeroPart - const topSpacing = 16; // Base spacing - const [stickyOffset, setStickyOffset] = useState(topSpacing); - - // Detect if running as a PWA on iOS - const isIOSPWA = - /iPad|iPhone|iPod/i.test(navigator.userAgent) && - window.matchMedia("(display-mode: standalone)").matches; - - const adjustedTopSpacing = isIOSPWA ? 60 : topSpacing; - const isLandscape = windowHeight < windowWidth && isIOSPWA; - const adjustedOffset = isLandscape ? -40 : 0; - - useEffect(() => { - if (windowWidth > 1280) { - // On large screens the bar goes inline with the nav elements - setStickyOffset(adjustedTopSpacing); - } else { - // On smaller screens the bar goes below the nav elements - setStickyOffset(adjustedTopSpacing + 60 + adjustedOffset); - } - }, [adjustedOffset, adjustedTopSpacing, windowWidth]); + // Navbar height is 80px (h-20) + const navbarHeight = 80; + // On desktop: inline with navbar (same top position + 14px adjustment) + // On mobile: below navbar (navbar height + banner) + const topOffset = isMobile ? navbarHeight + bannerSize : bannerSize + 14; return ( @@ -87,7 +71,7 @@ function SettingsLayout(props: {
diff --git a/src/pages/parts/home/HeroPart.tsx b/src/pages/parts/home/HeroPart.tsx index 674b9e89..982dd198 100644 --- a/src/pages/parts/home/HeroPart.tsx +++ b/src/pages/parts/home/HeroPart.tsx @@ -1,12 +1,12 @@ import classNames from "classnames"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { useCallback, useRef, useState } from "react"; import Sticky from "react-sticky-el"; -import { useWindowSize } from "react-use"; import { SearchBarInput } from "@/components/form/SearchBar"; import { ThinContainer } from "@/components/layout/ThinContainer"; import { useSlashFocus } from "@/components/player/hooks/useSlashFocus"; import { HeroTitle } from "@/components/text/HeroTitle"; +import { useIsMobile } from "@/hooks/useIsMobile"; import { useIsTV } from "@/hooks/useIsTv"; import { useRandomTranslation } from "@/hooks/useRandomTranslation"; import { useSearchQuery } from "@/hooks/useSearchQuery"; @@ -44,41 +44,22 @@ export function HeroPart({ const [search, setSearch, setSearchUnFocus] = searchParams; const [showBg, setShowBg] = useState(false); const bannerSize = useBannerSize(); + const { isMobile } = useIsMobile(); + const { isTV } = useIsTV(); const stickStateChanged = useCallback( (isFixed: boolean) => { setShowBg(isFixed); setIsSticky(isFixed); }, - [setShowBg, setIsSticky], + [setIsSticky], ); - const { width: windowWidth, height: windowHeight } = useWindowSize(); - - const { isTV } = useIsTV(); - - // Detect if running as a PWA on iOS - const isIOSPWA = - /iPad|iPhone|iPod/i.test(navigator.userAgent) && - window.matchMedia("(display-mode: standalone)").matches; - - const topSpacing = isIOSPWA ? 60 : 16; - const [stickyOffset, setStickyOffset] = useState(topSpacing); - - const isLandscape = windowHeight < windowWidth && isIOSPWA; - const adjustedOffset = isLandscape - ? -40 // landscape - : 0; // portrait - - useEffect(() => { - if (windowWidth > 1280) { - // On large screens the bar goes inline with the nav elements - setStickyOffset(topSpacing); - } else { - // On smaller screens the bar goes below the nav elements - setStickyOffset(topSpacing + 60 + adjustedOffset); - } - }, [adjustedOffset, topSpacing, windowWidth]); + // Navbar height is 80px (h-20) + const navbarHeight = 80; + // On desktop: inline with navbar (same top position) + // On mobile: below navbar (navbar height + banner) + const topOffset = isMobile ? navbarHeight + bannerSize : bannerSize + 14; const time = getTimeOfDay(new Date()); const title = randomT(`home.titles.${time}`); @@ -91,7 +72,7 @@ export function HeroPart({
{showTitle && (!isTV || search.length === 0) ? ( @@ -102,9 +83,9 @@ export function HeroPart({