From 76a3e51bbc921585fd1980954b5ffd8efe4b59b8 Mon Sep 17 00:00:00 2001 From: matteoscrugli Date: Sun, 11 Jan 2026 14:07:58 +0100 Subject: [PATCH] Fix mobile bottom padding on first page load Re-measure tab bar height when tabBarPosition changes from 'top' to 'responsive'. This fixes the issue where bottom padding was incorrect on first load because the CSS variable was measured before the backend loaded the responsive position setting. Co-Authored-By: Claude Opus 4.5 --- frontend/src/components/MobileTitleBar.tsx | 6 ++++++ frontend/src/components/TabsScroller.tsx | 25 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/frontend/src/components/MobileTitleBar.tsx b/frontend/src/components/MobileTitleBar.tsx index caa8db7..8883328 100644 --- a/frontend/src/components/MobileTitleBar.tsx +++ b/frontend/src/components/MobileTitleBar.tsx @@ -68,6 +68,12 @@ const MobileTitleBar = ({ } else if (typeof window !== 'undefined') { window.addEventListener('resize', updateMetrics); } + // Re-measure after fonts are loaded + if (typeof document !== 'undefined' && document.fonts?.ready) { + document.fonts.ready.then(() => { + updateMetrics(); + }); + } return () => { resizeObserver?.disconnect(); diff --git a/frontend/src/components/TabsScroller.tsx b/frontend/src/components/TabsScroller.tsx index 10f509c..b08efc5 100644 --- a/frontend/src/components/TabsScroller.tsx +++ b/frontend/src/components/TabsScroller.tsx @@ -9,6 +9,7 @@ import { type PointerEvent, type MouseEvent } from 'react'; +import { useTheme } from '../contexts/ThemeContext'; type TabsScrollerProps = { className: string; @@ -36,6 +37,7 @@ const TabsScroller = forwardRef( }, ref ) => { + const { tabBarPosition } = useTheme(); const sliderRef = useRef(null); const rafRef = useRef(0); const [showLeft, setShowLeft] = useState(false); @@ -166,6 +168,12 @@ const TabsScroller = forwardRef( } else if (typeof window !== 'undefined') { window.addEventListener('resize', scheduleOverflowUpdate); } + // Re-measure after fonts are loaded (icons may affect height) + if (typeof document !== 'undefined' && document.fonts?.ready) { + document.fonts.ready.then(() => { + scheduleOverflowUpdate(); + }); + } return () => { node.removeEventListener('scroll', handleScroll); resizeObserver?.disconnect(); @@ -187,6 +195,23 @@ const TabsScroller = forwardRef( }; }, []); + // Re-measure when tab bar position changes (e.g., from 'top' to 'responsive') + // This ensures correct measurements after backend loads and position changes + useEffect(() => { + if (tabBarPosition === 'responsive' || tabBarPosition === 'bottom') { + // Reset refs to force re-measurement + sliderHeightRef.current = 0; + heightRef.current = 0; + pillHeightRef.current = 0; + // Schedule update after a brief delay to ensure layout is complete + requestAnimationFrame(() => { + requestAnimationFrame(() => { + updateOverflow(); + }); + }); + } + }, [tabBarPosition, updateOverflow]); + const scrollByAmount = useCallback( (direction: 'left' | 'right') => { const node = sliderRef.current;