From cba3a0917929a5cf8e27a616f5b399a74d95f6a6 Mon Sep 17 00:00:00 2001 From: Thomas Cristina de Carvalho Date: Tue, 6 Feb 2024 13:50:53 -0500 Subject: [PATCH] Update mobile menu items and variant selector --- .../layout/NavigationProgressBar.tsx | 70 +++++++++++++------ .../navigation/MobileNavigation.tsx | 31 +++++--- app/components/product/VariantSelector.tsx | 1 + .../sanity/link/SanityInternalLink.tsx | 3 + 4 files changed, 77 insertions(+), 28 deletions(-) diff --git a/app/components/layout/NavigationProgressBar.tsx b/app/components/layout/NavigationProgressBar.tsx index 0d80c097..0b19ff4c 100644 --- a/app/components/layout/NavigationProgressBar.tsx +++ b/app/components/layout/NavigationProgressBar.tsx @@ -1,13 +1,38 @@ import {useNavigation} from '@remix-run/react'; import {useNProgress} from '@tanem/react-nprogress'; import {AnimatePresence, m} from 'framer-motion'; +import {useEffect, useState} from 'react'; export function NavigationProgressBar() { const navigation = useNavigation(); - const isLoading = navigation.state !== 'idle'; + const [isLoading, setIsLoading] = useState(false); const {animationDuration, isFinished, progress} = useNProgress({ isAnimating: isLoading, }); + const delay = 300; + + // Delay the progress bar apparing to avoid flickering when the page loads quickly + useEffect(() => { + const timeout = setTimeout(() => { + setIsLoading(navigation.state !== 'idle'); + }, delay); + + return () => clearTimeout(timeout); + }, [navigation.state]); + + return ( + + + + ); +} + +function Container(props: { + animationDuration: number; + children: React.ReactNode; + isFinished: boolean; +}) { + const {animationDuration, children, isFinished} = props; return ( @@ -17,30 +42,35 @@ export function NavigationProgressBar() { exit={{opacity: 0}} initial={{opacity: 0}} transition={{ - delay: 0.15, duration: animationDuration / 1000, }} > - -
- + {children} )} ); } + +function Bar(props: {animationDuration: number; progress: number}) { + const {animationDuration, progress} = props; + const marginLeft = `${(-1 + progress) * 100}%`; + + return ( + +
+ + ); +} diff --git a/app/components/navigation/MobileNavigation.tsx b/app/components/navigation/MobileNavigation.tsx index a9d1e964..bddf5fd6 100644 --- a/app/components/navigation/MobileNavigation.tsx +++ b/app/components/navigation/MobileNavigation.tsx @@ -17,6 +17,10 @@ import { DrawerTrigger, } from '../ui/Drawer'; +const mobileMenuLinkClass = cn( + 'flex rounded-md px-3 py-2 items-center gap-2 w-full transition-colors hover:bg-accent hover:text-accent-foreground', +); + export function MobileNavigation(props: {data?: NavigationProps}) { const [open, setOpen] = useState(false); const device = useDevice(); @@ -41,9 +45,11 @@ export function MobileNavigation(props: {data?: NavigationProps}) { props.data?.map((item) => (
  • {item._type === 'internalLink' && ( -
    - -
    + )} {item._type === 'externalLink' && (
    @@ -77,7 +83,7 @@ function MobileNavigationContent(props: { onOpenAutoFocus={(e) => e.preventDefault()} > @@ -107,7 +113,7 @@ function MobileNavigationNested(props: { onOpenChange={setOpen} open={open} > - + {data.name} @@ -122,11 +128,18 @@ function MobileNavigationNested(props: { {childLinks && childLinks.length > 0 && childLinks.map((child) => ( -
  • +
  • {child._type === 'internalLink' ? ( - + ) : child._type === 'externalLink' ? ( - + ) : null}
  • ))} @@ -135,6 +148,7 @@ function MobileNavigationNested(props: { ) : data.link && data.name && (!childLinks || childLinks.length === 0) ? ( // Render internal link if no child links {data.name} diff --git a/app/components/product/VariantSelector.tsx b/app/components/product/VariantSelector.tsx index 10a2b3ef..6541ee22 100644 --- a/app/components/product/VariantSelector.tsx +++ b/app/components/product/VariantSelector.tsx @@ -170,6 +170,7 @@ function Pills(props: { )} {value} diff --git a/app/components/sanity/link/SanityInternalLink.tsx b/app/components/sanity/link/SanityInternalLink.tsx index d1ddcf2a..668a8484 100644 --- a/app/components/sanity/link/SanityInternalLink.tsx +++ b/app/components/sanity/link/SanityInternalLink.tsx @@ -1,3 +1,4 @@ +import type {LinkProps} from '@remix-run/react'; import type {TypeFromSelection} from 'groqd'; import {Link} from '@remix-run/react'; @@ -14,6 +15,7 @@ export function SanityInternalLink(props: { children?: React.ReactNode; className?: string; data?: SanityInternalLinkProps; + onClick?: () => void; }) { const locale = useLocale(); const {children, className, data} = props; @@ -53,6 +55,7 @@ export function SanityInternalLink(props: { 'focus-visible:rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2', className, ])} + onClick={props.onClick} prefetch="intent" to={url} >