Skip to content

Commit

Permalink
Feature - Added FAQ section (#157)
Browse files Browse the repository at this point in the history
* Changed white theme color for text bubble bg color

* Changed light-blue in theme

* Added text colors to theme

* Changed FAQ accordion to match text bubble styles

* Added FAQ header

* add global colors

* Changed colors to match new theme colors

* Created custom accordion button

* Added plus and dash svg's for accodion buttons

* Removed accordion button component

* Added double border to speech bubbles

* Removed comments in FAQ

* Removed unused classes in FAQ.module.scss

* Centered accordion for mobile

* Added faq anteaters on floaties

* Side anteaters are now sticky

* Added framer motion dep

* Created AnteaterFloatie.tsx to use framer motion

* AnteaterFloaties bounce when clicked

* Anteaters float with scroll

* Removed test paragraph

* Added ripple effect on click

* Changed spacing of anteaters

* Changed margins to fit mobile again

* Reverted package and pnpm-lock

* Reverted package.json

* Changed FAQ div to use Bootstrap container

* Changed h4 to span using Bootstrap utils

* Imported only Container component in FAQ

* Removed unused import in FAQAccordion

* Updated indentation in page and corrected hack email

* Changed mobile text padding for text bubbles

* Updated font weights of faq, left-right margins match application buttons, removed unnused variable

* Removed unused comment

---------

Co-authored-by: Albert Wang <[email protected]>
  • Loading branch information
IanWearsHat and waalbert authored Oct 8, 2024
1 parent b0b9c0e commit 613cdba
Show file tree
Hide file tree
Showing 13 changed files with 329 additions and 90 deletions.
2 changes: 1 addition & 1 deletion apps/site/src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const Home = () => {
<Landing />
<GetInvolved />
{/* <Sponsors /> */}
{/* <FAQ /> */}
<FAQ />
</div>
);
};
Expand Down
95 changes: 95 additions & 0 deletions apps/site/src/app/(home)/sections/FAQ/AnteaterFloatie.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"use client";

import { useRef, useState } from "react";
import Image from "next/image";
import { ImageProps } from "next/image";

import { motion, useScroll, useSpring, useTransform } from "framer-motion";

import Ripple from "./Ripple";

const rippleSize = 300;

const AnteaterFloatie = ({ src, alt, className }: ImageProps) => {
const ref = useRef(null);

const [ripples, setRipples] = useState<
{ id: number; rippleX: number; rippleY: number }[]
>([]);

const { scrollYProgress } = useScroll({
target: ref,
offset: ["start end", "end end"],
});
const y = useSpring(scrollYProgress, { bounce: 0.2 + Math.random() * 0.5 });
const yScaled = useTransform(y, (value) => value * 250);

const [isClicked, setIsClicked] = useState(false);

const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
const rect = event.currentTarget.getBoundingClientRect();

let rippleHeight = rect.top;

const parentRect =
event.currentTarget.parentElement?.parentElement?.getBoundingClientRect();
if (parentRect) {
rippleHeight +=
-parentRect.top + yScaled.get() + (0.5 - y.get()) * rippleSize - 60;
}

const rippleX = rect.left - 150 + (rect.right - rect.left) / 2;
const rippleY = rippleHeight;

setRipples((prev) => [...prev, { id: Date.now(), rippleX, rippleY }]);
};

const handleRippleComplete = (id: number) => {
setRipples((prev) => prev.filter((ripple) => ripple.id !== id));
};

return (
<div ref={ref}>
<motion.div
style={{ y: yScaled }}
animate={{ rotate: [3.5, -3.5, 3.5], scale: isClicked ? 0.85 : 1 }}
transition={{
rotate: {
repeat: Infinity,
duration: 7,
ease: "easeInOut",
},
scale: { type: "spring", bounce: 0.7 },
}}
className={className}
>
<Image
src={src}
alt={alt}
onMouseDown={(event) => {
handleClick(event);
setIsClicked(true);
}}
onMouseUp={(event) => {
handleClick(event);
setIsClicked(false);
}}
onMouseLeave={() => {
setIsClicked(false);
}}
/>
</motion.div>

{ripples.map((ripple) => (
<Ripple
key={ripple.id}
x={ripple.rippleX}
y={ripple.rippleY}
onComplete={() => handleRippleComplete(ripple.id)}
/>
))}
</div>
);
};

export default AnteaterFloatie;
157 changes: 88 additions & 69 deletions apps/site/src/app/(home)/sections/FAQ/FAQ.module.scss
Original file line number Diff line number Diff line change
@@ -1,121 +1,140 @@
@use "zothacks-theme" as theme;
@use "bootstrap-utils" as utils;

.faq {
position: relative;
display: flex;
flex-direction: column;
width: 80%;
$mobile-item-padding-y: 26px;
$mobile-item-padding-x: 32px;

padding-bottom: 1.875rem;
background-color: theme.$beige;
}
$item-padding-y: 32px;
$item-padding-x: 48px;

.container {
position: relative;
padding-top: 6rem;
padding-bottom: 6rem;
display: flex;
justify-content: center;
justify-content: space-evenly;
width: 100vw;
}

.title {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
.left-anteater {
display: none;
}

.vertical-line {
position: absolute;
justify-self: flex-start;

height: 100%;
width: 45px;
border-right: 3px solid rgba(theme.$red, 0.45);
.right-anteater {
display: none;
}

.body {
margin-left: 40px;
margin-right: 10px;
.accordion-border {
margin-bottom: 8px;
}

.accordion {
--bs-accordion-btn-icon-width: 14px;
--bs-accordion-btn-icon: url("~@/assets/icons/plus-lg.svg");
--bs-accordion-btn-active-icon: url("~@/assets/icons/dash-lg.svg");
--bs-accordion-bg: none;
.question-body {
background-color: theme.$white;
border: 6px solid theme.$white;
box-shadow: inset 0 0 0 6px theme.$black;
border-radius: 16px;

& > * > * {
font-weight: 600;
}
}

.accordion-border {
border-bottom: 2px solid theme.$light-blue;
border-top: 2px solid theme.$light-blue;
.answer-body {
background-color: theme.$light-green;
border: 6px solid theme.$light-green;
box-shadow: inset 0 0 0 6px theme.$lighter-black;
border-radius: 16px;

margin-top: 8px;

& > * {
margin: 0;
font-weight: 500;
}

& > * > * {
font-weight: 500;
}
}

.star-lg {
position: absolute;
left: -60px;
top: -120px;
transform: rotate(-25deg);
filter: drop-shadow(0px 4px 2px rgba(0, 0, 0, 0.25));
.header-body {
padding: $mobile-item-padding-y $mobile-item-padding-x;
}

width: 200px;
height: 200px;
visibility: hidden;
.faq-header, .faq-header > * {
font-weight: 600;
}

.star-sm {
position: absolute;
right: -25px;
top: -60px;
transform: rotate(15deg);
filter: drop-shadow(0px 4px 2px rgba(0, 0, 0, 0.25));
.light-blue-text {
color: theme.$light-blue;
}

width: 120px;
height: 120px;
.purple-text {
color: theme.$purple;
}

.eraser {
position: absolute;
left: -80px;
bottom: -110px;
filter: drop-shadow(0px 4px 2px rgba(0, 0, 0, 0.25));
.accordion {
--bs-accordion-body-padding-y: #{$mobile-item-padding-y};
--bs-accordion-body-padding-x: #{$mobile-item-padding-x};

width: 220px;
height: 220px;
--bs-accordion-btn-padding-y: #{$mobile-item-padding-y};
--bs-accordion-btn-padding-x: #{$mobile-item-padding-x};

--bs-accordion-btn-icon-width: 32px;
--bs-accordion-btn-icon: url("~@/assets/icons/plus.svg");
--bs-accordion-btn-active-icon: url("~@/assets/icons/dash.svg");
--bs-accordion-bg: none;
}

@include utils.media-breakpoint-up(sm) {
.body {
margin-left: 60px;
}

.vertical-line {
width: 70px;
}
}

@include utils.media-breakpoint-up(md) {
.body {
margin-left: 110px;
}

.vertical-line {
border-right: 4px solid rgba(theme.$red, 0.45);
width: 116px;
.header-body {
padding: $item-padding-y $item-padding-x;
}

.accordion {
--bs-accordion-body-padding-y: #{$item-padding-y};
--bs-accordion-body-padding-x: #{$item-padding-x};

--bs-accordion-btn-padding-y: #{$item-padding-y};
--bs-accordion-btn-padding-x: #{$item-padding-x};
}

.accordion-border {
border-bottom-width: 3px;
border-top-width: 3px;
margin-left: 10px;
margin-right: 10px;
}

.star-lg {
visibility: visible;
.left-anteater {
display: block;
position: sticky;

top: 0;
margin-bottom: 250px;
z-index: 2;
}

.star-sm {
visibility: hidden;
.right-anteater {
display: block;
position: sticky;

margin-top: 20%;
margin-bottom: 250px;
top: 25%;

z-index: 2;
}

.eraser {
visibility: hidden;
.container {
padding-right: 30px;
}
}
50 changes: 39 additions & 11 deletions apps/site/src/app/(home)/sections/FAQ/FAQ.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import Container from "react-bootstrap/Container";
import { PortableText } from "@portabletext/react";

import { getQuestions } from "./getQuestions";
import FAQAccordion from "./FAQAccordion";

import Image from "next/image";
import { PortableText } from "@portabletext/react";
import styles from "./FAQ.module.scss";

import star from "@/assets/images/star.png";
import eraser from "@/assets/images/eraser.png";
import leftAnteater from "@/assets/images/left-faq-anteater.svg";
import rightAnteater from "@/assets/images/right-faq-anteater.svg";
import AnteaterFloatie from "./AnteaterFloatie";

const FAQ = async () => {
const questions = await getQuestions();
Expand All @@ -18,14 +20,40 @@ const FAQ = async () => {

return (
<section className={styles.container}>
<div className={styles.faq}>
<div className={styles["vertical-line"]} />
<Image src={star} alt="star" className={styles["star-lg"]} />
<Image src={star} alt="star" className={styles["star-sm"]} />
<Image src={eraser} alt="eraser" className={styles["eraser"]} />
<h2 className={styles.title}>FAQ</h2>
<AnteaterFloatie
src={leftAnteater}
alt="left anteater on floatie"
className={styles["left-anteater"]}
/>

<Container as="div" className="m-0">
<div
className={`${styles["accordion-border"]} ${styles["answer-body"]} ${styles["header-body"]}`}
>
<span className={styles["faq-header"] + " h4"}>
<h2 className="visually-hidden">FAQ</h2>
<span className={styles["light-blue-text"]}>FAQ!</span> Here's
answers to our most commonly asked questions!
</span>

<p>
If you don't find what you're looking for, reach out to our team at{" "}
<a
className={styles["purple-text"]}
href="mailto:[email protected]"
>
[email protected]
</a>
</p>
</div>
<FAQAccordion faq={faq} />
</div>
</Container>

<AnteaterFloatie
src={rightAnteater}
alt="left anteater on floatie"
className={styles["right-anteater"]}
/>
</section>
);
};
Expand Down
6 changes: 4 additions & 2 deletions apps/site/src/app/(home)/sections/FAQ/FAQAccordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ const FAQAccordion: React.FC<FAQAccordion> = ({ faq }) => {
className={styles["accordion-border"]}
eventKey={_key}
>
<Accordion.Header as="h3" className={styles.body}>
<Accordion.Header as="h4" className={styles["question-body"]}>
{question}
</Accordion.Header>
<Accordion.Body className={styles.body}>{answer}</Accordion.Body>
<Accordion.Body className={styles["answer-body"]}>
{answer}
</Accordion.Body>
</Accordion.Item>
))}
</Accordion>
Expand Down
Loading

0 comments on commit 613cdba

Please sign in to comment.