diff --git a/src/components/pages/landing-page.js b/src/components/pages/landing-page.js index 41be0bf..fdf3628 100644 --- a/src/components/pages/landing-page.js +++ b/src/components/pages/landing-page.js @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useRef } from 'react'; import { Box, Flex } from '@chakra-ui/react'; import { useLocation } from 'react-router-dom'; import { parse } from 'query-string'; @@ -11,9 +11,18 @@ import Faq from '../ui/landing-page/faq'; import DonatePage from '../ui/landing-page/donate-page'; import LandingPageHeader from '../ui/landing-page-header'; import SponsorList from '../ui/landing-page/sponsor-list'; +import useOnViewport from '../../utils/use-on-viewport'; function LandingPage() { const location = useLocation(); + const splashScreenRef = useRef(); + const problemSolutionRef = useRef(); + const howItWorksRef = useRef(); + const faqRef = useRef(); + const isSplashScreenVisible = useOnViewport(splashScreenRef); + const isProblemSolutionVisible = useOnViewport(problemSolutionRef); + const isHowItWorksVisible = useOnViewport(howItWorksRef); + const isFaqVisible = useOnViewport(faqRef); useEffect(() => { if (location.state?.redirectedFromAuth) { @@ -30,25 +39,33 @@ function LandingPage() { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + function activeMenuItem() { + if (isSplashScreenVisible) return '#splash-screen'; + if (isProblemSolutionVisible) return '#problem-solution'; + if (isHowItWorksVisible) return '#how-it-works'; + if (isFaqVisible) return '#faq'; + return ''; + } + return ( <> Uçurtma Projesi - + - + - + - + @@ -57,7 +74,7 @@ function LandingPage() { - + ); diff --git a/src/components/ui/landing-page-header.js b/src/components/ui/landing-page-header.js index 390ee7b..721bff3 100644 --- a/src/components/ui/landing-page-header.js +++ b/src/components/ui/landing-page-header.js @@ -30,7 +30,7 @@ export function SupportButton({ ...otherProps }) { ); } -function LandingPageHeader() { +function LandingPageHeader({ activeMenuItem }) { const { t } = useTranslation('titles'); const menuItems = [ @@ -62,6 +62,12 @@ function LandingPageHeader() { px={{ base: 4, lg: 0 }} justifyContent="space-between" alignItems="center" + position="fixed" + top="0" + right="0" + left="0" + bg="white" + zIndex="2" > - + diff --git a/src/components/ui/landing-page/faq.js b/src/components/ui/landing-page/faq.js index f14412e..5e9c347 100644 --- a/src/components/ui/landing-page/faq.js +++ b/src/components/ui/landing-page/faq.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { forwardRef } from 'react'; import { Box, Heading, @@ -16,65 +16,67 @@ import FAQ from './faq.json'; const { studentQuestions, donatorQuestions } = FAQ; const options = ['student', 'supporter']; -function Faq() { +function Faq(props, ref) { const [activeFaq, setActiveFaq] = React.useState('student'); const { t } = useTranslation(['faq', 'titles']); const questionType = activeFaq === 'student' ? studentQuestions : donatorQuestions; return ( - - - {t('titles:FAQ')} - - {options.map(option => ( - - ))} - + + + + {t('titles:FAQ')} + + {options.map(option => ( + + ))} + - - - - - i % 2 === 0)} - /> - i % 2 !== 0)} - /> - - - + + + + + i % 2 === 0)} + /> + i % 2 !== 0)} + /> + + + + ); } -export default Faq; +export default forwardRef(Faq); diff --git a/src/components/ui/landing-page/how-it-works.js b/src/components/ui/landing-page/how-it-works.js index b4eed64..9e56f93 100644 --- a/src/components/ui/landing-page/how-it-works.js +++ b/src/components/ui/landing-page/how-it-works.js @@ -1,10 +1,10 @@ -import React from 'react'; +import React, { forwardRef } from 'react'; import { Heading, Grid, Text, Box, Divider, Image } from '@chakra-ui/react'; import { useTranslation } from 'react-i18next'; import Container from '../container'; import Card from '../card'; -function HowItWorks() { +function HowItWorks(props, ref) { const { t } = useTranslation(['howItWorks', 'titles']); const cards = [ { @@ -25,63 +25,65 @@ function HowItWorks() { ]; return ( - - - {t('titles:How it works')} - {t('Three Steps')} - - - + - {cards.map(card => ( - - - - {card.title} - - - {card.text} - - - ))} - - + + {t('titles:How it works')} + {t('Three Steps')} + + + + {cards.map(card => ( + + + + {card.title} + + + {card.text} + + + ))} + + + ); } -export default HowItWorks; +export default forwardRef(HowItWorks); diff --git a/src/components/ui/landing-page/problem-and-solution.js b/src/components/ui/landing-page/problem-and-solution.js index 6816366..7f7218b 100644 --- a/src/components/ui/landing-page/problem-and-solution.js +++ b/src/components/ui/landing-page/problem-and-solution.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { forwardRef } from 'react'; import { Shield, Droplet, CloudLightning } from 'react-feather'; import { useTranslation } from 'react-i18next'; import { Box, Flex, Heading, Text, Grid, Image, Icon } from '@chakra-ui/react'; @@ -6,66 +6,71 @@ import MobileMockupTR from '../../assets/mobile-mockup-tr.svg'; import MobileMockupEN from '../../assets/mobile-mockup-en.svg'; import Container from '../container'; -function ProblemSolution() { +function ProblemSolution(props, ref) { const { t, i18n } = useTranslation('problemAndSolution'); const currentLanguage = i18n.language; return ( - - - - {t('New solution with blockchain')} - {t('What was the problem')} - - - - - - {t('Safe')} - - {t('Safe_details')} - - + + + + + {t('New solution with blockchain')} + {t('What was the problem')} + + + + + + {t('Safe')} + + {t('Safe_details')} + + + + + {t('Transparent')} + + {t('Transparent_details')} + + + - - {t('Transparent')} + + {t('Fast')} - {t('Transparent_details')} + {t('Fast_details')} - - - - - {t('Fast')} - - {t('Fast_details')} - - - - - - - + + + + + + + ); } -export default ProblemSolution; +export default forwardRef(ProblemSolution); diff --git a/src/components/ui/landing-page/splash-screen.js b/src/components/ui/landing-page/splash-screen.js index 7bb830a..1003f21 100644 --- a/src/components/ui/landing-page/splash-screen.js +++ b/src/components/ui/landing-page/splash-screen.js @@ -1,17 +1,17 @@ -import React from 'react'; +import React, { forwardRef } from 'react'; import { Link as RouterLink, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { Box, Heading, Text, Button, Stack } from '@chakra-ui/react'; +import { Box, Heading, Text, Button, Stack, Center } from '@chakra-ui/react'; import { ReactComponent as LeftKite } from '../../assets/left-kite.svg'; import { ReactComponent as RightKite } from '../../assets/right-kite.svg'; import Container from '../container'; -function SplashScreen() { +function SplashScreen(props, ref) { const { t } = useTranslation(['splashScreen', 'titles']); const navigate = useNavigate(); return ( - <> + - + ); } -export default SplashScreen; +export default forwardRef(SplashScreen); diff --git a/src/components/ui/menu-items.js b/src/components/ui/menu-items.js index 4e16346..3c3aa37 100644 --- a/src/components/ui/menu-items.js +++ b/src/components/ui/menu-items.js @@ -2,7 +2,7 @@ import React from 'react'; import { Button, Stack } from '@chakra-ui/react'; import { Link } from 'react-router-dom'; -function MenuItems({ isDrawer, items, ...otherProps }) { +function MenuItems({ isDrawer, items, activeMenuItem, ...otherProps }) { const drawerProps = { wrapper: { flexDirection: 'column', @@ -40,6 +40,7 @@ function MenuItems({ isDrawer, items, ...otherProps }) { flexShrink={0} {...(isDrawer && drawerProps.button)} {...navItem.buttonProps} + isActive={navItem.href === activeMenuItem} > {navItem.label} diff --git a/src/utils/use-on-viewport.js b/src/utils/use-on-viewport.js new file mode 100644 index 0000000..85f1aa9 --- /dev/null +++ b/src/utils/use-on-viewport.js @@ -0,0 +1,18 @@ +import { useEffect, useState } from 'react'; + +export default function useOnViewport(ref) { + const [isOnViewport, setIsOnViewport] = useState(false); + + const observer = new IntersectionObserver(([entry]) => + setIsOnViewport(entry.isIntersecting) + ); + + useEffect(() => { + observer.observe(ref.current); + return () => { + observer.disconnect(); + }; + }, [ref]); + + return isOnViewport; +}