diff --git a/public/assets/countdown_image.png b/public/assets/countdown_image.png new file mode 100644 index 0000000..46fa833 Binary files /dev/null and b/public/assets/countdown_image.png differ diff --git a/public/assets/navbar_proj_logo.svg b/public/assets/navbar_proj_logo.svg new file mode 100644 index 0000000..4109c05 --- /dev/null +++ b/public/assets/navbar_proj_logo.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/assets/proj_logo.svg b/public/assets/proj_logo.svg index 4109c05..064606e 100644 --- a/public/assets/proj_logo.svg +++ b/public/assets/proj_logo.svg @@ -1,5 +1,4 @@ - - - - + + + diff --git a/src/components/banner/index.tsx b/src/components/banner/index.tsx deleted file mode 100644 index 9ed6fcc..0000000 --- a/src/components/banner/index.tsx +++ /dev/null @@ -1,58 +0,0 @@ -"use client"; - -import { useState, useEffect } from "react"; -import styles from "./style.module.scss"; - -const Banner = () => { - const [days, setDays] = useState(0); - const [hours, setHours] = useState(0); - const [minutes, setMinutes] = useState(0); - const [seconds, setSeconds] = useState(0); - - useEffect(() => { - const target = new Date("04/02/2024 23:59:59"); - - const interval = setInterval(() => { - const now = new Date(); - const difference = target.getTime() - now.getTime(); - - if (difference <= 0) { - // The target date has passed, set all values to zero - setDays(0); - setHours(0); - setMinutes(0); - setSeconds(0); - clearInterval(interval); - } else { - const d = Math.floor(difference / (1000 * 60 * 60 * 24)); - setDays(d); - - const h = Math.floor( - (difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) - ); - setHours(h); - - const m = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60)); - setMinutes(m); - - const s = Math.floor((difference % (1000 * 60)) / 1000); - setSeconds(s); - } - }, 1000); - - return () => clearInterval(interval); - }, []); - - return ( -
-
- Projects applications close in{" "} - - {days} days {hours} hours {minutes} minutes {seconds} seconds - -
-
- ); -}; - -export default Banner; diff --git a/src/components/banner/style.module.scss b/src/components/banner/style.module.scss deleted file mode 100644 index ae815cf..0000000 --- a/src/components/banner/style.module.scss +++ /dev/null @@ -1,18 +0,0 @@ -@use "../../styles/vars.scss" as v; // allows you to use pre-defined colors - -.bannerbg { - background-color: v.$acm-blue-30 !important; - text-align: center; - padding: 0.3rem; -} - -@media screen and (max-width: 768px) { - .bannerbg { - display: flex; - flex-direction: column; - } -} - -.date { - font-weight: 700; -} diff --git a/src/components/countdown/index.tsx b/src/components/countdown/index.tsx new file mode 100644 index 0000000..2258646 --- /dev/null +++ b/src/components/countdown/index.tsx @@ -0,0 +1,66 @@ +"use client"; + +import { useState, useEffect } from "react"; +import styles from "./style.module.scss"; + +type CountdownProps = { + className?: string; +}; + +const Countdown = ({ className = "" }: CountdownProps) => { + const [days, setDays] = useState(0); + const [hours, setHours] = useState(0); + const [minutes, setMinutes] = useState(0); + const [seconds, setSeconds] = useState(0); + let countdownComponents : number[] = [days, hours, minutes, seconds]; + + useEffect(() => { + const target = new Date("10/02/2026 23:59:59"); + + const interval = setInterval(() => { + const now = new Date(); + const difference = target.getTime() - now.getTime(); + + if (difference <= 0) { + setDays(0); + setHours(0); + setMinutes(0); + setSeconds(0); + countdownComponents = [days, hours, minutes, seconds]; + clearInterval(interval); + } else { + setDays(Math.floor(difference / (1000 * 60 * 60 * 24))); + setHours( + Math.floor( + (difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) + ) + ); + setMinutes( + Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60)) + ); + setSeconds(Math.floor((difference % (1000 * 60)) / 1000)); + countdownComponents = [days, hours, minutes, seconds]; + } + }, 1000); + + return () => clearInterval(interval); + }, []); + + return ( +
+ {countdownComponents.map((comp, key) => { + const digits = String(comp).padStart(2, '0').split(''); + + return ( + + {digits[0]} + {digits[1]} + {key < 3 ? : : null} + + ); + })} +
+ ); +}; + +export default Countdown; diff --git a/src/components/countdown/style.module.scss b/src/components/countdown/style.module.scss new file mode 100644 index 0000000..f519abb --- /dev/null +++ b/src/components/countdown/style.module.scss @@ -0,0 +1,13 @@ +@use "../../styles/vars.scss" as v; // allows you to use pre-defined colors + +.date { + color: black; + font-size: 1.25rem; + font-weight: 700; + + .digit { + display: inline-block; + width: 1ch; + text-align: center; + } +} diff --git a/src/components/footer/styles.module.scss b/src/components/footer/styles.module.scss index 6cd93a1..d510885 100644 --- a/src/components/footer/styles.module.scss +++ b/src/components/footer/styles.module.scss @@ -8,7 +8,7 @@ $mmmw: 375px; // medium mobile max width .footer { width: 100%; height: 100%; - background-color: vars.$footer-blue; + background-color: vars.$proj-blue; color: vars.$white; z-index: 0; position: relative; @@ -224,4 +224,4 @@ $mmmw: 375px; // medium mobile max width } } } -} +} \ No newline at end of file diff --git a/src/components/navbar/Navbar.module.scss b/src/components/navbar/Navbar.module.scss index f0c82c1..3f32fb5 100644 --- a/src/components/navbar/Navbar.module.scss +++ b/src/components/navbar/Navbar.module.scss @@ -66,7 +66,7 @@ $stmw: 956px; // small tablet max width .logoText { font-size: 1.375rem; font-weight: 700; - color: vars.$proj-blue; + color: vars.$proj-blue-2; margin: 0; margin-left: 0.5rem; } @@ -146,7 +146,7 @@ $stmw: 956px; // small tablet max width // mobile menu is hidden by positioning under fixed navbar by moving the top margin up; we open it by sliding it out w/ transition and changing margin-top to 0 margin-top: -1 * $num-navItems * ($mobileNav-line-height + $navItem-margin-bottom); - border-bottom: $bottom-border-width solid vars.$proj-blue; + border-bottom: $bottom-border-width solid vars.$proj-blue-2; transition: margin-top 0.3s ease-in-out; a { @@ -192,4 +192,4 @@ $stmw: 956px; // small tablet max width } } } -} +} \ No newline at end of file diff --git a/src/components/navbar/index.tsx b/src/components/navbar/index.tsx index 4297c0f..009ea83 100644 --- a/src/components/navbar/index.tsx +++ b/src/components/navbar/index.tsx @@ -5,7 +5,7 @@ import { useEffect, useState } from "react"; import s from "./Navbar.module.scss"; import { Size, useWindowSize } from "../../utils/general"; -const ProjLogo = "/assets/proj_logo.svg"; +const ProjLogo = "/assets/navbar_proj_logo.svg"; // Nav link properties const navLinks = [ @@ -78,4 +78,4 @@ const NavigationBar: React.FC = () => { ); }; -export default NavigationBar; +export default NavigationBar; \ No newline at end of file diff --git a/src/sections/Hero/index.tsx b/src/sections/Hero/index.tsx index 6b8d483..252875f 100644 --- a/src/sections/Hero/index.tsx +++ b/src/sections/Hero/index.tsx @@ -2,45 +2,74 @@ import Image from "next/image"; import styles from "./style.module.scss"; import Description from "../description"; +import Countdown from "../../components/countdown"; +import { Size, useWindowSize } from "../../utils/general"; + +const ProjLogo = "/assets/proj_logo.svg"; +const CountdownImage = "/assets/countdown_image.png"; const Hero = () => { const projects_app = "https://acmurl.com/projects-app"; + const size: Size = useWindowSize(); + + // size.width !== undefined determines whether the viewport has rendered yet + const mobile = size.width !== undefined && size.width <= 920; + return ( -
-
-
-
-

ACM Projects

-

- ACM Projects is our quarterly projects program where students work - in a tight knit team. The program gives students the opportunity - to be hands-on outside of courses in fields such as AI, design, - and software engineering. The program culminates in a projects - showcase and the finished product looks great on resumes. We - welcome all skill levels to apply! -

-
- ACM Projects +
+
+ Countdown + +
+
+
+ Projects Logo +

ACM Projects

+
+

+ ACM Projects is our quarterly projects program where students work + in a tight knit team. The program gives students the opportunity + to be hands-on outside of courses in fields such as AI, design, + and software engineering. The program culminates in a projects + showcase and the finished product looks great on resumes. We + welcome all skill levels to apply! +

-
- Applications Due April 2nd, 11:59PM! -
-
+
+ Countdown + +
+
); }; -export default Hero; +export default Hero; \ No newline at end of file diff --git a/src/sections/Hero/style.module.scss b/src/sections/Hero/style.module.scss index a0ba2dc..c530a39 100644 --- a/src/sections/Hero/style.module.scss +++ b/src/sections/Hero/style.module.scss @@ -1,74 +1,198 @@ @use "../../styles/vars.scss" as v; // allows you to use pre-defined colors -.container { - min-height: 500px; +.pageContent { display: flex; - align-items: center; - justify-content: center; - justify-self: start; flex-direction: column; + justify-content: center; + align-items: center; + padding: 2.44rem 5.44rem; @media screen and (max-width: 768px) { align-items: flex-start; + padding-inline: 3rem; } -} -.hero { - margin: auto; - max-width: 1000px; - padding: 2rem; - font-size: 20px; - word-wrap: normal; - display: grid; - grid-template-columns: 1fr 1fr; - grid-template-areas: - "about image" - "button image"; - align-items: start; - justify-content: center; -} + @media screen and (max-width: 500px) { + padding-inline: 1.69rem; + } -@media screen and (max-width: 768px) { .hero { display: flex; - flex-direction: column; + justify-content: center; + align-items: center; + color: v.$black; + + @media screen and (max-width: 768px) { + display: flex; + flex-direction: column; + } + + .hero_main { + display: flex; + flex-direction: column; + font-size: 1.125rem; + + .title { + display: flex; + align-items: center; + gap: 1.25rem; + margin-bottom: 1.25rem; + + .titleLogo { + width: 8rem; + height: auto; + margin: 0; + } + + .titleText { + font-size: 5rem; + font-weight: 700; + margin: 0; + } + + @media screen and (max-width: 1500px) { + .titleLogo { + width: 6rem; + } + + .titleText { + font-size: 4rem; + } + } + + @media screen and (max-width: 1340px) { + gap: 0.8rem; + + .titleLogo { + width: 4rem; + } + + .titleText { + font-size: 3rem; + } + } + + @media screen and (max-width: 965px) { + gap: 0.6rem; + + .titleText { + font-size: 2.5rem; + } + } + } + + .description { + margin-bottom: 1.75rem; + } + + .button { + background-color: v.$proj-blue; + color: v.$white; + padding: 1rem 2.25rem; + border-radius: 0.625rem; + border-width: 0; + font-size: 1.2rem; + font-weight: 500; + cursor: pointer; + + @media screen and (max-width: 1340px) { + padding: 0.7rem 1.8rem; + font-size: 1rem; + } + + @media screen and (max-width: 768px) { + justify-content: center; + align-self: center; + } + } + } + + .countdownImageWrapper { + flex: 0 0 auto; + position: relative; + margin: 0 -5rem 0 -6rem; + + .countdownImage { + width: 42rem; + height: auto; + margin: -0.5rem 0 -10rem 0; + } + + .countdown { + position: absolute; + top: 7.5rem; + right: 16.1rem; + transform: perspective(1000px) rotateX(-43deg) rotateY(-43deg); + transform-style: preserve-3d; + } + + @media screen and (max-width: 1190px) { + .countdownImage { + width: 35rem; + } + + .countdown { + top: 6rem; + right: 13rem; + font-size: 1.2rem; + } + } + + @media screen and (max-width: 1055px) { + .countdownImage { + width: 30rem; + } + + .countdown { + top: 4.9rem; + right: 11.2rem; + font-size: 1rem; + } + } + } } } -.title { - font-size: 56px; - font-weight: 200; -} +@media screen and (max-width: 920px) { + .pageContent { + .hero { + flex-direction: column; -.hero_text { - grid-area: about; -} + .hero_main { + align-items: center; -.image { - grid-area: image; - border-radius: 10px; -} + .title { + .titleLogo { + display: none; + } -.button { - background-color: v.$acm-blue; - color: v.$white; - padding: 12px 30px; - border-radius: 10px; - font-size: 16px; - cursor: pointer; - border-width: 0; - grid-area: button; -} + .titleText { + font-size: 1.875rem; + } + } -.deadline { - padding-top: 1rem; - font-size: 16px; - font-weight: 700; -} + .description { + margin-bottom: 2.5rem; + text-align: center; + } -@media screen and (max-width: 768px) { - .button { - justify-content: center; - align-self: center; + .button { + padding: 0.625rem 2.5rem; + } + } + + .countdownImageWrapper { + .countdownImage { + width: 20rem; + margin: 0 0 -3rem 0; + } + + .countdown { + top: 3.4rem; + right: 7.4rem; + font-size: 0.7rem; + } + } + } } -} +} \ No newline at end of file diff --git a/src/styles/vars.scss b/src/styles/vars.scss index d401e69..55cbdeb 100644 --- a/src/styles/vars.scss +++ b/src/styles/vars.scss @@ -16,8 +16,8 @@ $purple: #816dff; $black: #333333; $acm-blue-30: #a8d3ff; $acm-blue: #62b0ff; -$proj-blue: #5777C0; -$footer-blue: #4E78C6; +$proj-blue: #4E78C6; +$proj-blue-2: #5777C0; // find the size relative to the viewport width between a min and max size // size is calculated using a linear function between two points diff --git a/tsconfig.json b/tsconfig.json index b09cc80..c196a09 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "es6", "lib": [ "dom", "dom.iterable", @@ -15,7 +15,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "react-jsx", + "jsx": "preserve", "incremental": true, "plugins": [ {