From 1d9e445d8446a4fd244e4c32ebb892fd40abdcd0 Mon Sep 17 00:00:00 2001 From: Chad Curtis Date: Mon, 23 Mar 2026 23:10:55 -0500 Subject: [PATCH] Fix arc bugs: revert top arc to upstream, remove top navbar arc, separate bottom nav overhang for harsher curve --- src/components/ArcBackground.tsx | 18 ++++++++++++------ src/components/MainLayout.tsx | 2 +- src/components/MobileBottomNav.tsx | 6 +++--- src/components/MobileTopBar.tsx | 6 ++---- src/index.css | 4 ++-- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/components/ArcBackground.tsx b/src/components/ArcBackground.tsx index d19bb39f..018c3d50 100644 --- a/src/components/ArcBackground.tsx +++ b/src/components/ArcBackground.tsx @@ -1,10 +1,13 @@ import { cn } from '@/lib/utils'; -/** The arc overhang in pixels that extends beyond the element's bounds. */ -export const ARC_OVERHANG_PX = 24; +/** Arc overhang for the downward arc (top bar / sub-header). */ +export const ARC_OVERHANG_PX = 20; + +/** Larger overhang for the upward arc (bottom nav) so the harsher curve isn't clipped. */ +export const ARC_UP_OVERHANG_PX = 28; /** SVG path for a downward arc (used by top bar and sub-header bar). */ -const ARC_DOWN_PATH = 'M0,0 L100,0 L100,24 Q50,64 0,24 Z'; +const ARC_DOWN_PATH = 'M0,0 L100,0 L100,44 Q50,64 0,44 Z'; /** SVG path for an upward arc (used by bottom nav). */ const ARC_UP_PATH = 'M0,30 Q50,0 100,30 L100,64 L0,64 Z'; @@ -12,8 +15,11 @@ const ARC_UP_PATH = 'M0,30 Q50,0 100,30 L100,64 L0,64 Z'; /** SVG path for a plain rectangle with no arc. */ const RECT_PATH = 'M0,0 L100,0 L100,64 L0,64 Z'; -/** Pre-computed style for arc variants (avoids creating a new object on every render). */ -const arcHeightStyle: React.CSSProperties = { height: `calc(100% + ${ARC_OVERHANG_PX}px)` }; +/** Pre-computed style for down-arc variant. */ +const arcDownHeightStyle: React.CSSProperties = { height: `calc(100% + ${ARC_OVERHANG_PX}px)` }; + +/** Pre-computed style for up-arc variant (bottom nav — larger overhang). */ +const arcUpHeightStyle: React.CSSProperties = { height: `calc(100% + ${ARC_UP_OVERHANG_PX}px)` }; /** Pre-computed style for non-arc (rect) variant. */ const fullHeightStyle: React.CSSProperties = { height: '100%' }; @@ -45,7 +51,7 @@ export function ArcBackground({ variant, className }: ArcBackgroundProps) { className={cn(positionClass, 'w-full pointer-events-none', className)} viewBox="0 0 100 64" preserveAspectRatio="none" - style={hasArc ? arcHeightStyle : fullHeightStyle} + style={hasArc ? (variant === 'up' ? arcUpHeightStyle : arcDownHeightStyle) : fullHeightStyle} > diff --git a/src/components/MainLayout.tsx b/src/components/MainLayout.tsx index 26ec016f..3b4d96c3 100644 --- a/src/components/MainLayout.tsx +++ b/src/components/MainLayout.tsx @@ -74,7 +74,7 @@ function MainLayoutInner() { {config.magicMouse && } {/* Mobile top bar - only on small screens */} - setDrawerOpen(true)} showArc={!hasSubHeader && !noArcs} /> + setDrawerOpen(true)} /> {/* Mobile drawer */} diff --git a/src/components/MobileBottomNav.tsx b/src/components/MobileBottomNav.tsx index 7ce51e47..40540b41 100644 --- a/src/components/MobileBottomNav.tsx +++ b/src/components/MobileBottomNav.tsx @@ -10,12 +10,12 @@ import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useScrollDirection } from '@/hooks/useScrollDirection'; import { useProfileUrl } from '@/hooks/useProfileUrl'; import { useLayoutSnapshot } from '@/contexts/LayoutContext'; -import { ArcBackground, ARC_OVERHANG_PX } from '@/components/ArcBackground'; +import { ArcBackground, ARC_UP_OVERHANG_PX } from '@/components/ArcBackground'; import { MobileSearchSheet } from '@/components/MobileSearchSheet'; /** Transform style applied when the bottom nav is hidden (scrolled away). */ const hiddenStyle: React.CSSProperties = { - transform: `translateY(calc(100% + ${ARC_OVERHANG_PX}px))`, + transform: `translateY(calc(100% + ${ARC_UP_OVERHANG_PX}px))`, }; export function MobileBottomNav() { @@ -52,7 +52,7 @@ export function MobileBottomNav() { > -
+
{/* Feed */} void; - /** Whether to show the decorative arc below the header (when no sub-header exists). */ - showArc?: boolean; } -export function MobileTopBar({ onAvatarClick, showArc }: MobileTopBarProps) { +export function MobileTopBar({ onAvatarClick }: MobileTopBarProps) { const location = useLocation(); const handleLogoClick = useCallback((e: React.MouseEvent) => { @@ -22,7 +20,7 @@ export function MobileTopBar({ onAvatarClick, showArc }: MobileTopBarProps) { return (
- +
{/* Left: hamburger menu icon */}
diff --git a/src/index.css b/src/index.css index 6694dc6d..9f50ce38 100644 --- a/src/index.css +++ b/src/index.css @@ -48,9 +48,9 @@ bottom: calc(1.5rem + var(--bottom-nav-height) + env(safe-area-inset-bottom, 0px)); } - /* Position above mobile bottom nav + safe area + arc overhang (24px) */ + /* Position above mobile bottom nav + safe area + arc overhang (28px) */ .bottom-mobile-nav { - bottom: calc(var(--bottom-nav-height) + 24px + env(safe-area-inset-bottom, 0px)); + bottom: calc(var(--bottom-nav-height) + 28px + env(safe-area-inset-bottom, 0px)); } /* Bottom overscroll padding for the center column: