Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - Added FAQ section #157

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9909e07
Changed white theme color for text bubble bg color
IanWearsHat Sep 27, 2024
c263f63
Changed light-blue in theme
IanWearsHat Sep 27, 2024
7da6fea
Added text colors to theme
IanWearsHat Sep 29, 2024
09a2844
Changed FAQ accordion to match text bubble styles
IanWearsHat Sep 29, 2024
ffeddf5
Added FAQ header
IanWearsHat Sep 29, 2024
bf22c32
add global colors
waalbert Sep 30, 2024
abf5fc7
Merge branch 'feat/global-colors' of https://github.com/HackAtUCI/zot…
IanWearsHat Sep 30, 2024
70931bb
Changed colors to match new theme colors
IanWearsHat Sep 30, 2024
0407e94
Created custom accordion button
IanWearsHat Sep 30, 2024
3347c9e
Added plus and dash svg's for accodion buttons
IanWearsHat Sep 30, 2024
804a827
Removed accordion button component
IanWearsHat Sep 30, 2024
21348f2
Added double border to speech bubbles
IanWearsHat Sep 30, 2024
03911c5
Removed comments in FAQ
IanWearsHat Oct 1, 2024
24e660b
Removed unused classes in FAQ.module.scss
IanWearsHat Oct 1, 2024
f50816a
Centered accordion for mobile
IanWearsHat Oct 1, 2024
2c0dc43
Added faq anteaters on floaties
IanWearsHat Oct 1, 2024
86d5afe
Side anteaters are now sticky
IanWearsHat Oct 1, 2024
83a5554
Added framer motion dep
IanWearsHat Oct 1, 2024
c6bf74b
Created AnteaterFloatie.tsx to use framer motion
IanWearsHat Oct 1, 2024
e986a0e
AnteaterFloaties bounce when clicked
IanWearsHat Oct 1, 2024
95f9a81
Anteaters float with scroll
IanWearsHat Oct 1, 2024
d18b09c
Removed test paragraph
IanWearsHat Oct 1, 2024
1a83746
Added ripple effect on click
IanWearsHat Oct 2, 2024
53b2a3c
Changed spacing of anteaters
IanWearsHat Oct 2, 2024
d99229f
Changed margins to fit mobile again
IanWearsHat Oct 2, 2024
e06bffd
Reverted package and pnpm-lock
IanWearsHat Oct 4, 2024
00f055c
Reverted package.json
IanWearsHat Oct 4, 2024
a4572ce
Changed FAQ div to use Bootstrap container
IanWearsHat Oct 4, 2024
6d3bc20
Changed h4 to span using Bootstrap utils
IanWearsHat Oct 4, 2024
f139c0e
Merge branch 'main' into feature/add-faqs-from-sanity
IanWearsHat Oct 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/site/src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const Home = () => {
<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;
135 changes: 63 additions & 72 deletions apps/site/src/app/(home)/sections/FAQ/FAQ.module.scss
Original file line number Diff line number Diff line change
@@ -1,121 +1,112 @@
@use "zothacks-theme" as theme;
@use "bootstrap-utils" as utils;

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

$answer-font-size: 16px;
$question-font-size: 20px;

padding-bottom: 1.875rem;
background-color: theme.$beige;
.light-blue-text {
color: theme.$light-blue;
}

.purple-text {
color: theme.$purple;
}

.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;
.accordion-border {
margin-left: 10px;
margin-right: 10px;
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;
}

.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;

.star-lg {
position: absolute;
left: -60px;
top: -120px;
transform: rotate(-25deg);
filter: drop-shadow(0px 4px 2px rgba(0, 0, 0, 0.25));
margin-top: 8px;

width: 200px;
height: 200px;
visibility: hidden;
& > * {
margin: 0;
}
}

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

width: 120px;
height: 120px;
.header-body {
padding: $item-padding-y $item-padding-x;
}

.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: #{$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};

width: 220px;
height: 220px;
--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;
}
.left-anteater {
display: block;
position: sticky;

.accordion-border {
border-bottom-width: 3px;
border-top-width: 3px;
top: 0;
margin-bottom: 250px;
z-index: 2;
}

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

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

.star-sm {
visibility: hidden;
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";
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="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
7 changes: 5 additions & 2 deletions apps/site/src/app/(home)/sections/FAQ/FAQAccordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import Accordion from "react-bootstrap/Accordion";
import styles from "./FAQ.module.scss";
import { AccordionButton } from "react-bootstrap";

interface FAQAccordion {
faq: {
Expand All @@ -20,10 +21,12 @@ const FAQAccordion: React.FC<FAQAccordion> = ({ faq }) => {
className={styles["accordion-border"]}
eventKey={_key}
>
<Accordion.Header as="h3" className={styles.body}>
<Accordion.Header as="h3" 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
Loading