diff --git a/main-site/components/about-section/AboutSection.animations.ts b/main-site/components/about-section/AboutSection.animations.ts new file mode 100644 index 00000000..ca14d824 --- /dev/null +++ b/main-site/components/about-section/AboutSection.animations.ts @@ -0,0 +1,27 @@ +export const hidden = { + initial: { + opacity: 0, + transition: { + duration: 1 + } + }, + animate: { + opacity: 0, + transition: { + duration: 1 + } + } +}; +export const fadeInUp = { + initial: { + y: 60, + opacity: 0 + }, + animate: { + y: 0, + opacity: 1, + transition: { + duration: 1 + } + } +}; diff --git a/main-site/components/about-section/AboutSection.styles.ts b/main-site/components/about-section/AboutSection.styles.ts index f42337b0..28865df7 100644 --- a/main-site/components/about-section/AboutSection.styles.ts +++ b/main-site/components/about-section/AboutSection.styles.ts @@ -1,8 +1,9 @@ import styled from '@emotion/styled'; import { H2, H3, P } from '../../../shared-ui/style/typography'; import { max, min } from '../../../shared-ui/lib/responsive'; +import { motion } from 'framer-motion'; -const StyledAboutSectionContainer = styled.div` +const StyledAboutSectionContainer = styled(motion.div)` margin-top: 10em; padding-bottom: 10em; position: relative; @@ -12,7 +13,7 @@ const StyledAboutSectionContainer = styled.div` } `; -const StyledItemsContainer = styled.div` +const StyledItemsContainer = styled(motion.div)` display: flex; margin: 5em; justify-content: center; @@ -35,7 +36,7 @@ const StyledItemTextContainer = styled.div` } `; -const StyledTitle = styled(H2)` +const StyledTitle = styled(motion(H2))` color: white; text-align: center; `; @@ -61,7 +62,7 @@ const StyledItemDescription = styled(P)` } `; -const StyledItemContainer = styled.div` +const StyledItemContainer = styled(motion.div)` width: 17em; display: flex; justify-content: center; diff --git a/main-site/components/about-section/AboutSection.tsx b/main-site/components/about-section/AboutSection.tsx index 850e8187..358ae227 100644 --- a/main-site/components/about-section/AboutSection.tsx +++ b/main-site/components/about-section/AboutSection.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import { min } from '../../../shared-ui/lib/responsive'; import useMatchMedia from 'react-use-match-media'; import { colors } from '../../../shared-ui/style/colors'; @@ -24,6 +24,9 @@ import { AboutSectionData } from '../../lib/types'; import Arrow from '../../../shared-ui/components/arrow/Arrow'; import { getLeftOrRight } from '../../lib/utils'; import Shell from '../../../shared-ui/images/shell.png'; +import { useInView } from 'react-intersection-observer'; +import {fadeInUp, hidden } from './AboutSection.animations'; +import { useAnimation } from 'framer-motion'; function getImage(title: string): string { if (title === 'Community') { @@ -41,10 +44,18 @@ const AboutSection: React.FC = () => { aboutSectionData[0] ); + const animationControls = useAnimation(); + const [ref, inView] = useInView(); + + // if the section is in view, start the animation for the section + useEffect(() => { + inView ? animationControls.start("animate") : animationControls.set("initial") + }, [animationControls, inView]) + return (
- - HackBeanpot is about... + + HackBeanpot is about... {!isDesktop && ( @@ -85,7 +96,7 @@ const AboutSection: React.FC = () => { {isDesktop && ( {aboutSectionData.map((curr) => ( - + diff --git a/main-site/components/events-calendar-section/EventsCalendarSection.styles.ts b/main-site/components/events-calendar-section/EventsCalendarSection.styles.ts index d93866f9..5bd60164 100644 --- a/main-site/components/events-calendar-section/EventsCalendarSection.styles.ts +++ b/main-site/components/events-calendar-section/EventsCalendarSection.styles.ts @@ -3,12 +3,13 @@ import { max, min } from '../../../shared-ui/lib/responsive'; import { colors } from '../../../shared-ui/style/colors'; import { fonts, H2, P } from '../../../shared-ui/style/typography'; import { eventsCalendarData } from '../../lib/data'; +import {motion} from 'framer-motion' const StyledDesktopTextsContainer = styled.div` padding: 1em 0; `; -const StyledSectionContainer = styled.div` +const StyledSectionContainer = styled(motion.div)` padding-top: 5em; padding-bottom: 30em; @media ${max.tablet} { @@ -17,7 +18,7 @@ const StyledSectionContainer = styled.div` } `; -const StyledEventsContainer = styled.div` +const StyledEventsContainer = styled(motion.div)` top: 3em; position: relative; display: flex; @@ -162,7 +163,7 @@ const EventsSubHeader = styled(P)` } `; -const StyledH2 = styled(H2)` +const StyledH2 = styled(motion(H2))` text-align: center; color: ${colors.WHITE}; `; diff --git a/main-site/components/events-calendar-section/EventsCalendarSection.tsx b/main-site/components/events-calendar-section/EventsCalendarSection.tsx index c16461ce..8b579b60 100644 --- a/main-site/components/events-calendar-section/EventsCalendarSection.tsx +++ b/main-site/components/events-calendar-section/EventsCalendarSection.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import EventsSeaweed from '../../../shared-ui/images/seaweed-rock.svg'; import EventsSeaweedDark from '../../../shared-ui/images/seaweed-rock-dark.svg'; import EventsFishSchool from '../../../shared-ui/images/school-fish.svg'; @@ -16,21 +16,35 @@ import { min } from '../../../shared-ui/lib/responsive'; import useMatchMedia from 'react-use-match-media'; import DesktopTexts from './texts/DesktopTexts'; import { eventsCalendarData } from '../../lib/data'; +import variants from '../../../shared-ui/animations/variants'; +import { useAnimation } from 'framer-motion'; +import { useInView } from 'react-intersection-observer'; +import { fadeInUp } from './EventsCalenderSection.animation'; +import { EventsCalenderSectionProps } from '../../lib/types'; -const EventsCalendarSection: React.FC = ({ isDay }) => { +const EventsCalendarSection: React.FC = ({ isDay }) => { const isDesktop = useMatchMedia(min.tablet); + + const animationControls = useAnimation(); + const [ref, inView] = useInView(); + + // if the section is in view, start the animation for the section + useEffect(() => { + inView ? animationControls.start("animate") : animationControls.set("initial") + }, [animationControls, inView]) + return (
- - Events Calendar - + + Events Calendar + {isDesktop && ( )} - + diff --git a/main-site/components/events-calendar-section/EventsCalenderSection.animation.ts b/main-site/components/events-calendar-section/EventsCalenderSection.animation.ts new file mode 100644 index 00000000..f421bce6 --- /dev/null +++ b/main-site/components/events-calendar-section/EventsCalenderSection.animation.ts @@ -0,0 +1,28 @@ +export const hidden = { + initial: { + opacity: 0, + transition: { + duration: 1 + } + }, + animate: { + opacity: 0, + transition: { + duration: 1 + } + } +}; + +export const fadeInUp = { + initial: { + y: 60, + opacity: 0 + }, + animate: { + y: 0, + opacity: 1, + transition: { + duration: 1 + } + } +}; diff --git a/main-site/components/landing-section/LandingSection.animations.ts b/main-site/components/landing-section/LandingSection.animations.ts index dead89a7..04b18920 100644 --- a/main-site/components/landing-section/LandingSection.animations.ts +++ b/main-site/components/landing-section/LandingSection.animations.ts @@ -18,3 +18,53 @@ export const moonRock = { } } }; + + +export const fadeInUp = { + initial: { + y: 60, + opacity: 0 + }, + animate: { + y: 0, + opacity: 1, + transition: { + duration: 1 + } + } +}; +export const fadeInLeft = { + initial: { + x: -60, + opacity: 0 + }, + animate: { + x: 0, + opacity: 1, + transition: { + duration: 1 + } + } +}; + +export const fadeInRight = { + initial: { + x: 60, + opacity: 0 + }, + animate: { + x: 0, + opacity: 1, + transition: { + duration: 1 + } + } +}; + +export const stagger = { + animate: { + transition: { + staggerChildren: 0.5 + } + } +}; \ No newline at end of file diff --git a/main-site/components/landing-section/LandingSection.styles.ts b/main-site/components/landing-section/LandingSection.styles.ts index 7180f1a8..ccedb2bb 100644 --- a/main-site/components/landing-section/LandingSection.styles.ts +++ b/main-site/components/landing-section/LandingSection.styles.ts @@ -5,8 +5,8 @@ import { max, min } from '../../../shared-ui/lib/responsive'; import { colors } from '../../../shared-ui/style/colors'; import { H1, H3, H5, H6, P } from '../../../shared-ui/style/typography'; -const StyledHackathonText = styled(H5)` - { +const StyledHackathonText = styled(motion(H5))` + { color: ${colors.WHITE}; padding-bottom: 0.2em; @media ${max.tablet} { @@ -19,8 +19,7 @@ const StyledHackathonText = styled(H5)` } `; - -const StyledThemeText = styled(H1)` +const StyledThemeText = styled(motion(H1))` { color: ${colors.WHITE}; padding-bottom: 0.1em; @@ -33,7 +32,7 @@ const StyledThemeText = styled(H1)` } `; -const StyledThemeTextSmall = styled(H6)` +const StyledThemeTextSmall = styled(motion(H6))` { color: ${colors.WHITE}; padding-bottom: 0.1em; @@ -46,7 +45,7 @@ const StyledThemeTextSmall = styled(H6)` } `; -const StyledThemeTextParagraph = styled(P)` +const StyledThemeTextParagraph = styled(motion(P))` { color: ${colors.WHITE}; padding-bottom: 0.1em; @@ -88,7 +87,7 @@ const StyledBubble1 = styled.img` @media ${min.tablet} { width: 5%; } -` +`; const StyledBubble2 = styled.img` position: absolute; @@ -107,7 +106,7 @@ const StyledBubble2 = styled.img` top: 90vw; right: -5vw; } -` +`; const StyledFish = styled.img` position: absolute; @@ -126,7 +125,7 @@ const StyledFish = styled.img` @media ${max.mobile} { top: 110vw; } -` +`; const StyledJellyfish = styled.img` position: absolute; @@ -146,7 +145,7 @@ const StyledJellyfish = styled.img` @media ${max.mobile} { top: 110vw; } -` +`; const StyledWhale = styled.img` position: absolute; @@ -165,9 +164,9 @@ const StyledWhale = styled.img` @media ${max.mobile} { top: 120vw; } -` +`; -const StyledLandingTextContainer = styled.div` +const StyledLandingTextContainer = styled(motion.div)` padding-top: 21em; text-align: center; @media ${max.tabletLg} { @@ -184,11 +183,11 @@ const StyledLandingTextContainer = styled.div` } `; -const StyledLandingSectionContainer = styled.div` +const StyledLandingSectionContainer = styled(motion.div)` position: relative; `; -const StyledLandingButtonContainer = styled(PrimaryButton)` +const StyledLandingButtonContainer = styled(motion(PrimaryButton))` padding-top: 2em; position: fixed; justify-content: left; @@ -226,7 +225,7 @@ const StyledHourglass = styled.img` margin-right: 0.3em; `; -const StyledCountdownContainer = styled.div` +const StyledCountdownContainer = styled(motion.div)` display: flex; justify-content: center; `; @@ -234,7 +233,7 @@ const StyledCountdownContainer = styled.div` export { StyledHackathonText, StyledThemeText, - StyledThemeTextSmall, + StyledThemeTextSmall, StyledThemeTextParagraph, StyledLandingButtonContainer, StyledLandingSectionContainer, diff --git a/main-site/components/landing-section/LandingSection.tsx b/main-site/components/landing-section/LandingSection.tsx index 26872f00..81505111 100644 --- a/main-site/components/landing-section/LandingSection.tsx +++ b/main-site/components/landing-section/LandingSection.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useRef, useEffect, useState } from 'react'; import { StyledHackathonText, StyledThemeText, @@ -16,12 +16,14 @@ import { StyledHourglass, StyledCountdownContainer } from './LandingSection.styles'; -import Bubble from '../../../shared-ui/images/bubbles.svg' -import Bubble2 from '../../../shared-ui/images/bubbles2.svg' -import Fish from '../../../shared-ui/images/fish.svg' -import Jellyfish from '../../../shared-ui/images/jellyfish.svg' -import Whale from '../../../shared-ui/images/whale.svg' +import Bubble from '../../../shared-ui/images/bubbles.svg'; +import Bubble2 from '../../../shared-ui/images/bubbles2.svg'; +import Fish from '../../../shared-ui/images/fish.svg'; +import Jellyfish from '../../../shared-ui/images/jellyfish.svg'; +import Whale from '../../../shared-ui/images/whale.svg'; import ToggleMode from '../../../shared-ui/components/toggle-mode/ToggleMode'; +import { useInView } from 'framer-motion'; +import { fadeInUp, stagger } from './LandingSection.animations'; import { CountdownProps, LandingSectionProps } from '../../lib/types'; import { CountdownData } from '../../lib/data'; import hourglass from '../../../shared-ui/images/hourglass.svg' @@ -66,28 +68,31 @@ const Countdown: React.FC = ({ targetDate }) => { }; const LandingSection: React.FC = ({ isDay, setIsDay }) => { + return ( - + - - HackBeanpot 2024 - Under the Sea - February 9-11, 2024 - Location TBD + + HackBeanpot 2024 + Under the Sea + February 9-11, 2024 + Location TBD {/* @ Wood Mackenzie (Formerly known as PowerAdvocate)
179 Lincoln St, Boston, MA 02111
*/} {/* */} - + {/* */} + diff --git a/main-site/lib/types.ts b/main-site/lib/types.ts index 039fb329..bb52a942 100644 --- a/main-site/lib/types.ts +++ b/main-site/lib/types.ts @@ -32,6 +32,10 @@ export interface ExploreSectionProps { isDay: boolean; } +export interface EventsCalenderSectionProps { + isDay: boolean; +} + export interface TestimonialData { id: number; author: string; diff --git a/package.json b/package.json index 39d49151..5342e174 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "path": "0.12.7", "react": "18.2.0", "react-helmet": "6.1.0", + "react-intersection-observer": "^9.5.2", "react-media-match": "1.14.2", "styled-components": "5.3.11", "ts-node": "10.9.1" diff --git a/shared-ui/components/primary-button/PrimaryButton.tsx b/shared-ui/components/primary-button/PrimaryButton.tsx index 0fb0e4d7..7f638853 100644 --- a/shared-ui/components/primary-button/PrimaryButton.tsx +++ b/shared-ui/components/primary-button/PrimaryButton.tsx @@ -3,14 +3,14 @@ import { StyledPrimaryButton } from './PrimaryButton.styles'; import { ButtonProps } from '../../lib/types'; import { buttonAnimations } from './PrimaryButton.animations'; -const PrimaryButton: React.FC = ({ +const PrimaryButton: React.FC = React.forwardRef(({ btnText, btnLink, newTab = false, isSmallPrimary = false, transparent = false, isApplyButton = false, -}) => { +}, ref) => { const [isClicked, setIsClicked] = useState(false); if (!btnLink) { const ctaText = isClicked ? 'Copied to clipboard!' : btnText; @@ -28,7 +28,7 @@ const PrimaryButton: React.FC = ({ document.body.removeChild(el); }; return ( - + {ctaText} @@ -37,7 +37,7 @@ const PrimaryButton: React.FC = ({ } return ( - + = ({ ); -}; +}); export default PrimaryButton; diff --git a/yarn.lock b/yarn.lock index 0c8d3ab6..70fadbf7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2460,6 +2460,11 @@ react-helmet@6.1.0: react-fast-compare "^3.1.1" react-side-effect "^2.1.0" +react-intersection-observer@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-9.5.2.tgz#f68363a1ff292323c0808201b58134307a1626d0" + integrity sha512-EmoV66/yvksJcGa1rdW0nDNc4I1RifDWkT50gXSFnPLYQ4xUptuDD4V7k+Rj1OgVAlww628KLGcxPXFlOkkU/Q== + react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"