diff --git a/apps/info/public/card_icon_1.svg b/apps/info/public/card_icon_1.svg new file mode 100644 index 00000000..6beba271 --- /dev/null +++ b/apps/info/public/card_icon_1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/info/public/card_icon_2.svg b/apps/info/public/card_icon_2.svg new file mode 100644 index 00000000..5f6a2135 --- /dev/null +++ b/apps/info/public/card_icon_2.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/info/public/card_icon_3.svg b/apps/info/public/card_icon_3.svg new file mode 100644 index 00000000..9be2fa6a --- /dev/null +++ b/apps/info/public/card_icon_3.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/info/public/exhibit_background.png b/apps/info/public/exhibit_background.png new file mode 100644 index 00000000..c677316c Binary files /dev/null and b/apps/info/public/exhibit_background.png differ diff --git a/apps/info/public/exhibit_background.svg b/apps/info/public/exhibit_background.svg new file mode 100644 index 00000000..d72c6c70 --- /dev/null +++ b/apps/info/public/exhibit_background.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/info/public/icon_building.svg b/apps/info/public/icon_building.svg new file mode 100644 index 00000000..126b7dfa --- /dev/null +++ b/apps/info/public/icon_building.svg @@ -0,0 +1,278 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/info/public/icon_calendar.svg b/apps/info/public/icon_calendar.svg new file mode 100644 index 00000000..332883d4 --- /dev/null +++ b/apps/info/public/icon_calendar.svg @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/info/public/icon_location.svg b/apps/info/public/icon_location.svg new file mode 100644 index 00000000..5496c990 --- /dev/null +++ b/apps/info/public/icon_location.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/info/public/icon_person.svg b/apps/info/public/icon_person.svg new file mode 100644 index 00000000..6d3695b9 --- /dev/null +++ b/apps/info/public/icon_person.svg @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/info/public/icon_speaker.svg b/apps/info/public/icon_speaker.svg new file mode 100644 index 00000000..3b0bb966 --- /dev/null +++ b/apps/info/public/icon_speaker.svg @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/info/public/instagram_logo.png b/apps/info/public/instagram_logo.png new file mode 100644 index 00000000..1ba06941 Binary files /dev/null and b/apps/info/public/instagram_logo.png differ diff --git a/apps/info/public/logo_2018.svg b/apps/info/public/logo_2018.svg new file mode 100644 index 00000000..5f4e7179 --- /dev/null +++ b/apps/info/public/logo_2018.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +RP 2017 logo + diff --git a/apps/info/public/logo_2019.svg b/apps/info/public/logo_2019.svg new file mode 100644 index 00000000..18019b26 --- /dev/null +++ b/apps/info/public/logo_2019.svg @@ -0,0 +1 @@ +Asset 130 \ No newline at end of file diff --git a/apps/info/public/logo_2020.svg b/apps/info/public/logo_2020.svg new file mode 100644 index 00000000..659fa97c --- /dev/null +++ b/apps/info/public/logo_2020.svg @@ -0,0 +1 @@ +Asset 130 \ No newline at end of file diff --git a/apps/info/public/logo_2021.svg b/apps/info/public/logo_2021.svg new file mode 100644 index 00000000..d7d5f090 --- /dev/null +++ b/apps/info/public/logo_2021.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/info/public/logo_2022.svg b/apps/info/public/logo_2022.svg new file mode 100644 index 00000000..d54cd07e --- /dev/null +++ b/apps/info/public/logo_2022.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/info/public/logo_2023.svg b/apps/info/public/logo_2023.svg new file mode 100644 index 00000000..5fd6df68 --- /dev/null +++ b/apps/info/public/logo_2023.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/info/public/logo_2024.svg b/apps/info/public/logo_2024.svg new file mode 100644 index 00000000..2236be55 --- /dev/null +++ b/apps/info/public/logo_2024.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/info/public/logo_2025.svg b/apps/info/public/logo_2025.svg new file mode 100644 index 00000000..c9ebca2f --- /dev/null +++ b/apps/info/public/logo_2025.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/info/public/logo_info.svg b/apps/info/public/logo_info.svg new file mode 100644 index 00000000..37eb429f --- /dev/null +++ b/apps/info/public/logo_info.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/info/public/rp2024shine_logo.png b/apps/info/public/rp2024shine_logo.png new file mode 100644 index 00000000..5287b43a Binary files /dev/null and b/apps/info/public/rp2024shine_logo.png differ diff --git a/apps/info/public/spotlight.svg b/apps/info/public/spotlight.svg new file mode 100644 index 00000000..83e62ca2 --- /dev/null +++ b/apps/info/public/spotlight.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/info/public/vite.svg b/apps/info/public/vite.svg deleted file mode 100644 index e7b8dfb1..00000000 --- a/apps/info/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/info/src/components/AnimatedLogo.tsx b/apps/info/src/components/AnimatedLogo.tsx new file mode 100644 index 00000000..0106991d --- /dev/null +++ b/apps/info/src/components/AnimatedLogo.tsx @@ -0,0 +1,182 @@ +import { motion } from "framer-motion"; +import { useCallback, useEffect, useRef, useState } from "react"; + +export const AnimatedLogoConstant = () => { + const changeImageFnRef = useRef<() => void>(() => {}); + const [rotation, setRotation] = useState(0); + const [topOpacity, setTopOpacity] = useState(1); + const [topCurrentImage, setTopCurrentImage] = useState(0); + const [bottomCurrentImage, setBottomCurrentImage] = useState(-1); + const intervalRef = useRef(null); + + const images = [ + "logo_2025.svg", + "logo_2024.svg", + "logo_2023.svg", + "logo_2022.svg", + "logo_2021.svg", + "logo_2020.svg", + "logo_2019.svg", + "logo_2018.svg" + ]; + + // this updates every render so the ref always has a fresh function + changeImageFnRef.current = () => { + // switch to bottom + if (topOpacity) { + setRotation((prev) => prev + 360); + setBottomCurrentImage((prev) => (prev + 2) % images.length); // bottom switches by 2 + setTopOpacity((prev) => (prev + 1) % 2); // top fades out + } + // switch to top + else { + setRotation((prev) => prev + 360); + setTopCurrentImage((prev) => (prev + 2) % images.length); // top switches by 2 + setTopOpacity((prev) => (prev + 1) % 2); // top fades in + } + }; + + const stopRotation = () => { + if (intervalRef.current) { + clearInterval(intervalRef.current); + } + }; + + const startRotation = useCallback(() => { + // if the browser 'focus' event fires twice, just + // stop the extra trigger here + stopRotation(); + intervalRef.current = window.setInterval(() => { + changeImageFnRef.current(); + }, 6000); + }, []); + + useEffect(() => { + console.log("setting window listeners..."); + startRotation(); + window.addEventListener("blur", stopRotation); + window.addEventListener("focus", startRotation); + + return () => { + stopRotation(); + window.removeEventListener("blur", stopRotation); + window.removeEventListener("focus", startRotation); + }; + }, [startRotation]); // happy linter... (and just in case) + + return ( + <> + + + + ); +}; + +export const AnimatedLogoHover = () => { + const [isHovered, setIsHovered] = useState(false); + const changeImageFnRef = useRef<() => void>(() => {}); + const [rotation, setRotation] = useState(0); + const [topOpacity, setTopOpacity] = useState(1); + const [topCurrentImage, setTopCurrentImage] = useState(0); + const [bottomCurrentImage, setBottomCurrentImage] = useState(-1); + const intervalRef = useRef(null); + + const images = [ + "logo_info.svg", + "logo_2025.svg", + "logo_2024.svg", + "logo_2023.svg", + "logo_2022.svg", + "logo_2021.svg", + "logo_2020.svg", + "logo_2019.svg", + "logo_2018.svg" + ]; + + // this updates every render so the ref always has a fresh function + changeImageFnRef.current = () => { + // switch to bottom + if (topOpacity) { + setRotation((prev) => prev + 360); + setBottomCurrentImage((prev) => (prev + 2) % images.length); // bottom switches by 2 + setTopOpacity((prev) => (prev + 1) % 2); // top fades out + } + // switch to top + else { + setRotation((prev) => prev + 360); + setTopCurrentImage((prev) => (prev + 2) % images.length); // top switches by 2 + setTopOpacity((prev) => (prev + 1) % 2); // top fades in + } + }; + + // runs on hover on/off - either enabling or disabling the rotation interval + useEffect(() => { + if (isHovered) { + changeImageFnRef.current(); + intervalRef.current = window.setInterval(() => { + changeImageFnRef.current(); + }, 2000); + } else { + if (intervalRef.current) { + clearInterval(intervalRef.current); + } + } + // every time isHovered becomes false, useEffect runs here, + // hitting the else statement and killing the active interval. + + return () => { + if (intervalRef.current) { + clearInterval(intervalRef.current); + } + }; + }, [isHovered]); + + return ( + <> + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + animate={{ rotate: rotation, opacity: topOpacity }} + transition={{ duration: 0.5, ease: "easeInOut" }} + width="100%" + height="100%" + style={{ + zIndex: 2, + position: "absolute" + }} + src={images[topCurrentImage]} + /> + + + ); +}; diff --git a/apps/info/src/components/AnimatedPillar.tsx b/apps/info/src/components/AnimatedPillar.tsx new file mode 100644 index 00000000..9b8b1010 --- /dev/null +++ b/apps/info/src/components/AnimatedPillar.tsx @@ -0,0 +1,88 @@ +import { Box } from "@chakra-ui/react"; +import { motion, useInView } from "framer-motion"; +import { useRef } from "react"; + +const MotionBox = motion(Box); + +type AnimatedCounterProps = { + // icon?: string; + baseHeight: number; + heightDelta: number; + time: number; + children: React.ReactNode; +}; + +const AnimatedPillar: React.FC = ({ + baseHeight, + heightDelta, + time, + children +}) => { + const viewMarkerRef = useRef(null); + const isInView = useInView(viewMarkerRef); + + return ( + + + {/* pillar */} + + {children} + + + + + + + + + ); +}; + +export default AnimatedPillar; diff --git a/apps/info/src/components/AnimatedPillarsSection.tsx b/apps/info/src/components/AnimatedPillarsSection.tsx new file mode 100644 index 00000000..8d866c8b --- /dev/null +++ b/apps/info/src/components/AnimatedPillarsSection.tsx @@ -0,0 +1,198 @@ +import { Box, VStack, Image, Flex, Container } from "@chakra-ui/react"; +import { motion, useScroll, useTransform } from "framer-motion"; +import { createPortal } from "react-dom"; +import AnimatedPillar from "./AnimatedPillar"; + +interface AnimatedPillarsSectionProps { + icons: string[]; +} + +const MotionBox = motion(Box); +const MotionContainer = motion(Container); +const spotlightHeight = "975px"; + +export const AnimatedPillarsSection: React.FC = ({ + icons +}) => { + const { scrollY } = useScroll(); + const offset = 950; + const shadowOpacity = useTransform( + scrollY, + [-350 + offset, -60 + offset, 350 + offset, 650 + offset], + [0, 0.35, 0.35, 0] + ); + const heightDiff = useTransform( + scrollY, + [-250 + offset, 700 + offset], + [200, -750] + ); + const translateY = useTransform(heightDiff, (h) => `translateY(${h}px)`); + + return ( + + {/* portal */} + {createPortal( + + + + + + + + + + + + + + + + + + + + + + + , + document.body + )}{" "} + {/* portal */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/apps/info/src/components/Carousel.tsx b/apps/info/src/components/Carousel.tsx index 7ae950ad..42993616 100644 --- a/apps/info/src/components/Carousel.tsx +++ b/apps/info/src/components/Carousel.tsx @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import { Box, Heading, Flex, Image, Text, Button } from "@chakra-ui/react"; +import { Box, Flex, Image, Text, Button } from "@chakra-ui/react"; interface CarouselItem { title: string; @@ -102,9 +102,9 @@ const CircularCarousel: React.FC = ({ items }) => { h="700px" pt={8} > - + {/* Meet the Team - + */} = ({ items }) => { + + + ); +}; diff --git a/apps/info/src/pages/Home/Stats.tsx b/apps/info/src/components/Home/Stats.tsx similarity index 69% rename from apps/info/src/pages/Home/Stats.tsx rename to apps/info/src/components/Home/Stats.tsx index 6b1d8813..95f0de29 100644 --- a/apps/info/src/pages/Home/Stats.tsx +++ b/apps/info/src/components/Home/Stats.tsx @@ -1,27 +1,10 @@ -import { - Box, - Flex, - Heading, - Text, - Container, - VStack, - Icon, - Divider -} from "@chakra-ui/react"; -import { - FaUser, - FaCalendar, - FaBuilding, - FaMicrophone, - FaMapMarkerAlt -} from "react-icons/fa"; -import AnimatedCounter from "../../components/AnimatedCounter"; - -const Stats = () => { - const iconColor = "#d84949"; +import { Box, Flex, Heading, Text, Container, VStack } from "@chakra-ui/react"; +import AnimatedCounter from "@/components/AnimatedCounter"; +import { AnimatedPillarsSection } from "@/components/AnimatedPillarsSection"; +export const Stats = () => { return ( - + @@ -52,19 +35,21 @@ const Stats = () => { - + - Midwest's Largest Student-Run + The Midwest's Largest Student-Run
Tech Conference
- @@ -102,27 +87,17 @@ const Stats = () => { - - - - - - - - - - - +
); }; - -export default Stats; diff --git a/apps/info/src/components/Home/TeamSection.tsx b/apps/info/src/components/Home/TeamSection.tsx new file mode 100644 index 00000000..912af735 --- /dev/null +++ b/apps/info/src/components/Home/TeamSection.tsx @@ -0,0 +1,50 @@ +import { Box, Flex, Heading, Container, Button } from "@chakra-ui/react"; +import CircularCarousel from "../Carousel"; +import { NavLink } from "react-router-dom"; + +export const TeamSection = () => { + const teamCards: { title: string; image: string }[] = [ + { title: "Dev", image: "logo_2018.svg" }, + { title: "Design", image: "logo_2019.svg" }, + { title: "Marketing", image: "logo_2020.svg" }, + { title: "Content", image: "logo_2021.svg" }, + { title: "Ops", image: "logo_2022.svg" } + ]; + + return ( + + + + + Meet the Team + + + + + + + + + + ); +}; diff --git a/apps/info/src/components/HoverIconLink.tsx b/apps/info/src/components/HoverIconLink.tsx new file mode 100644 index 00000000..5a221ff6 --- /dev/null +++ b/apps/info/src/components/HoverIconLink.tsx @@ -0,0 +1,102 @@ +import { Box, Image, Link } from "@chakra-ui/react"; +import { motion } from "framer-motion"; +import React from "react"; + +interface HoverIconLinkProps { + link: string; + src: string; + title?: string; +} + +export const HoverIconLink: React.FC = ({ + link, + src, + title +}) => { + // const [isHovered, setIsHovered] = useState(false); + // const animation = useAnimation(); + + // useEffect(() => { + // console.log("animate START") + + // console.log("animate STOP") + + // }, [isHovered, animation]) + + return ( + + + + + setIsHovered(true)} + // onMouseLeave={() => setIsHovered(false)} + style={{ + width: "80px", + height: "80px", + zIndex: "2", + position: "absolute", + top: "0px", + justifyContent: "center", + alignItems: "center", + display: "flex", + transformStyle: "preserve-3d" + }} + > + + + + + + ); +}; diff --git a/apps/info/src/components/Navbar.tsx b/apps/info/src/components/Navbar.tsx index 0f4b3970..c2bc4d38 100644 --- a/apps/info/src/components/Navbar.tsx +++ b/apps/info/src/components/Navbar.tsx @@ -1,24 +1,117 @@ // src/components/Navbar.tsx -import { Box, Flex, HStack, Link, Text } from "@chakra-ui/react"; -import { NavLink } from "react-router-dom"; +import { Box, HStack, Link } from "@chakra-ui/react"; +import { NavLink, useLocation } from "react-router-dom"; +import { AnimatedLogoHover } from "./AnimatedLogo"; +// import { motion, useScroll, useTransform } from "framer-motion"; export const Navbar = () => { + const location = useLocation(); + + //const MotionBox = motion(Box); + + // const { scrollY } = useScroll(); + // const width = useTransform(scrollY, [0, 500], ['100%', '50%']); + // const height = useTransform(scrollY, [0, 500], ['85px', '75px']); + // const top = useTransform(scrollY, [0, 500], [0, 10]); + // const fontSize = useTransform(scrollY, [0, 500], ['1.75rem', '1.15rem']); + // const borderRadius = useTransform(scrollY, [0, 500], ['0px', '16px']); + return ( - - - Info.RP - - - Home - - - Archive - - - FAQ - - - + // + + {/* todo(): add a small-web version */} + + + + + + + ABOUT + + + ARCHIVE + + + TEAM + + + FAQ + + + SPONSORS + + + join us! + + + // ); }; diff --git a/apps/info/src/customTheme.ts b/apps/info/src/customTheme.ts index a59d0608..7b0e90a9 100644 --- a/apps/info/src/customTheme.ts +++ b/apps/info/src/customTheme.ts @@ -9,6 +9,23 @@ export const customTheme = extendTheme({ config, fonts: { heading: "'Anonymous Pro', monospace", - body: "'Anonymous Pro', monospace" + body: "'Anonymous Pro', monospace", + menu: "'Raleway', monospace" + }, + textStyles: { + menu: { + fontFamily: "menu", + fontSize: "18px", + textColor: "black", + fontWeight: "700", + textUnderlineOffset: "5px" + }, + textBlock: { + fontFamily: "menu", + fontSize: "65px", + textColor: "black", + fontWeight: "700", + textUnderlineOffset: "5px" + } } }); diff --git a/apps/info/src/routes/Home.tsx b/apps/info/src/routes/Home.tsx index 5e08c035..9ac28cd0 100644 --- a/apps/info/src/routes/Home.tsx +++ b/apps/info/src/routes/Home.tsx @@ -1,7 +1,10 @@ // src/routes/Home.tsx -import { ExhibitSection } from "../pages/Home/ExhibitSection"; -import { Header } from "../pages/Home/Header"; -import Stats from "../pages/Home/Stats"; +import { ExhibitSection } from "@/components/Home/ExhibitSection"; +import { Footer } from "@/components/Footer"; +import { Header } from "@/components/Home/Header"; +import { SponsorSection } from "@/components/Home/SponsorSection"; +import { Stats } from "@/components/Home/Stats"; +import { TeamSection } from "@/components/Home/TeamSection"; export const Home = () => { return ( @@ -9,6 +12,9 @@ export const Home = () => {
+ + +