feat: FAQ buttons and nav links

This commit is contained in:
ascpixi 2025-11-14 21:00:03 -05:00
parent 765c33e98c
commit 0027f2cceb
4 changed files with 159 additions and 82 deletions

View file

@ -3,51 +3,64 @@ import FaqButton from './components/FaqButton.js';
import Step from './components/Step.js';
import StoryCard from './components/StoryCard.js';
import GameCard from './components/GameCard.js';
import NavbarLink from './components/NavbarLink.tsx';
function App() {
const scrollToSection = (sectionId: string) => {
const element = document.getElementById(sectionId);
if (element) {
element.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
};
document.body.addEventListener("click", console.log);
return (
<div className="w-full min-h-screen flex flex-col overflow-x-hidden">
<div className="absolute top-0 left-0 w-1/3 z-10">
<div className="absolute top-0 left-0 w-1/3 z-10 pointer-events-none">
<img
src="/backgrounds/corner-cloud.png"
alt=""
className="w-full h-full object-cover"
className="w-full h-full object-cover select-none"
/>
</div>
<div className="w-full h-screen">
<header className="relative h-[115px] bg-[#45b4f5] flex justify-end items-center pr-16">
<nav className="flex gap-12 items-center text-white text-5xl font-bold font-amatic">
<button className="hover:opacity-80 transition-opacity">Steps</button>
<button className="hover:opacity-80 transition-opacity">Map</button>
<button className="hover:opacity-80 transition-opacity">Previous events</button>
<button className="hover:opacity-80 transition-opacity">FAQ</button>
<NavbarLink onClick={() => scrollToSection('steps')}>Steps</NavbarLink>
<NavbarLink onClick={() => scrollToSection('map')}>Map</NavbarLink>
<NavbarLink onClick={() => scrollToSection('previous-events')}>Previous events</NavbarLink>
<NavbarLink onClick={() => scrollToSection('faq')}>FAQ</NavbarLink>
</nav>
</header>
<section className="relative h-full flex items-end pb-32 2xl:pb-48 px-6 md:px-16 lg:px-24 2xl:px-32 bg-[url(/backgrounds/blue-sky.png)] bg-center bg-cover">
<div className="absolute top-0 left-0 w-full h-full">
<img src="/backgrounds/sky-shine.png" alt="" className="w-full h-full object-cover" />
<div className="absolute top-0 left-0 w-full h-full pointer-events-none">
<img src="/backgrounds/sky-shine.png" alt="" className="w-full h-full object-cover select-none" />
</div>
<div className="absolute bottom-[32px] right-[140px] w-full h-full">
<div className="absolute bottom-[32px] right-[140px] w-full h-full pointer-events-none">
{/* fishy on the right. His name is frederick. */}
<div className="absolute top-[64px] right-[140px] w-1/6 animate-fish-swim-2">
<img src="/characters/fish-2.png" alt="Fish named Frederick" className="w-full h-full object-cover" />
<img src="/characters/fish-2.png" alt="Fish named Frederick" className="w-full h-full object-cover select-none" />
</div>
{/* fishy on the left. His name is gubson */}
<div className="absolute top-[32px] right-[300px] w-1/6 animate-fish-swim-1">
<img src="/characters/fish-1.png" alt="Fish named Gubson" className="w-full h-full object-cover" />
<img src="/characters/fish-1.png" alt="Fish named Gubson" className="w-full h-full object-cover select-none" />
</div>
</div>
<div className="absolute bottom-[160px] left-0 w-full h-full animate-cloud-float-right">
<img src="/backgrounds/bottom-cloud.png" alt="" />
<div className="absolute bottom-[160px] left-0 w-full h-full animate-cloud-float-right pointer-events-none">
<img src="/backgrounds/bottom-cloud.png" alt="" className="select-none" />
</div>
<div className="absolute -bottom-[50px] left-0 w-full h-[120px]">
<img src="/decorative/vines.png" alt="" className="w-full h-full object-cover object-top" />
<div className="absolute -bottom-[50px] left-0 w-full h-[120px] pointer-events-none">
<img src="/decorative/vines.png" alt="" className="w-full h-full object-cover object-top select-none" />
</div>
<div className="flex flex-col lg:flex-row justify-between items-center w-full gap-8 pb-24 z-10">
@ -57,7 +70,7 @@ function App() {
<img
src="/decorative/hack-club-flag.png"
alt="Hack Club"
className="w-[151px] h-[53px] object-cover transform rotate-[-4.8deg]"
className="w-[151px] h-[53px] object-cover transform rotate-[-4.8deg] select-none"
/>
</div>
@ -96,7 +109,7 @@ function App() {
<div
className="bg-[#f9e2ca] border-4 border-[#d5a16c] rounded-[20px] px-4 md:px-8 py-4 flex items-center gap-3 md:gap-6 w-full transform rotate-[-1.2deg] shadow-[0_8px_20px_rgba(0,0,0,0.25)]"
>
<img src="/icons/email.svg" alt="" className="w-6 h-5 flex-shrink-0" />
<img src="/icons/email.svg" alt="" className="w-6 h-5 flex-shrink-0 select-none" />
<input
type="email"
className="text-[#854d16] text-2xl md:text-4xl font-bold truncate bg-transparent border-none outline-none flex-1 cursor-text font-amatic"
@ -105,10 +118,11 @@ function App() {
/>
</div>
<button
className="bg-[#fca147] border-[5px] border-[rgba(0,0,0,0.2)] rounded-[20px] px-8 md:px-14 py-4 hover:scale-105 transition-transform w-full md:w-auto transform rotate-[1.5deg] shadow-[0_8px_20px_rgba(0,0,0,0.25)] cursor-pointer"
className="bg-[#fca147] border-[5px] border-[rgba(0,0,0,0.2)] rounded-[20px] px-8 md:px-14 py-4 hover:scale-105 transition-transform w-full md:w-auto transform rotate-[1.5deg] shadow-[0_8px_20px_rgba(0,0,0,0.25)] cursor-pointer active:scale-95"
type="button"
onClick={() => {
console.log('RSVP clicked');
// TODO: Implement RSVPs
alert("Sorry, RSVPs are unavailable for now. Stay tuned!");
}}
>
<p
@ -134,7 +148,7 @@ function App() {
<img
src="/ui/arrow.png"
alt=""
className="w-[45px] md:w-[55px] h-[33px] md:h-[41px] translate-y-6 rotate-[6.2deg] z-50"
className="w-[45px] md:w-[55px] h-[33px] md:h-[41px] translate-y-6 rotate-[6.2deg] z-50 select-none"
/>
</div>
@ -149,38 +163,38 @@ function App() {
</div>
</section>
<div className="absolute bottom-0 left-0 w-full">
<img src="/backgrounds/landing-grass.png" alt="" className="w-full h-full object-cover" />
<div className="absolute bottom-0 left-0 w-full pointer-events-none">
<img src="/backgrounds/landing-grass.png" alt="" className="w-full h-full object-cover select-none" />
</div>
</div>
<section className="relative pt-[13vw] pb-96 bg-[url(/backgrounds/underwater-gradient.png)] bg-cover">
<div className="absolute top-0 left-0 w-screen h-[200px] bg-gradient-to-b from-[#004b2a] to-transparent"></div>
<div className="absolute top-[30px] left-0 w-full scale-125">
<img src="/decorative/vines.png" alt="" className="w-full h-full object-cover" />
<div className="absolute top-0 left-0 w-screen h-[200px] bg-gradient-to-b from-[#004b2a] to-transparent pointer-events-none"></div>
<div className="absolute top-[30px] left-0 w-full scale-125 pointer-events-none">
<img src="/decorative/vines.png" alt="" className="w-full h-full object-cover select-none" />
</div>
<div className="absolute bottom-[500px] left-0 w-full h-[800px] -z-10">
<img src="/decorative/clouds-3.png" alt="" className="w-full h-full object-cover" />
<div className="absolute bottom-[500px] left-0 w-full h-[800px] -z-10 pointer-events-none">
<img src="/decorative/clouds-3.png" alt="" className="w-full h-full object-cover select-none" />
</div>
<div className="absolute bottom-0 left-0 w-full h-[613px] -z-10">
<img src="/backgrounds/seafloor.png" alt="" className="w-full h-full object-cover" />
<div className="absolute bottom-0 left-0 w-full h-[613px] -z-10 pointer-events-none">
<img src="/backgrounds/seafloor.png" alt="" className="w-full h-full object-cover select-none" />
</div>
<div className="absolute bottom-[400px] left-32 w-[569px] h-[676px]">
<div className="absolute bottom-[400px] left-32 w-[569px] h-[676px] pointer-events-none">
<img
src="/characters/astronaut.png"
alt=""
className="w-full h-full object-cover transform rotate-[172deg] scale-y-[-1]"
className="w-full h-full object-cover transform rotate-[172deg] scale-y-[-1] select-none"
/>
</div>
<div className="absolute top-[500px] right-32 w-[352px] h-[354px]">
<img src="/decorative/cog.png" alt="" className="w-full h-full object-cover rounded-full" />
<div className="absolute top-[500px] right-32 w-[352px] h-[354px] pointer-events-none">
<img src="/decorative/cog.png" alt="" className="w-full h-full object-cover rounded-full select-none" />
</div>
<div className="relative z-10 flex flex-col gap-24 items-center px-12 max-w-7xl mx-auto">
<div id="steps" className="relative z-10 flex flex-col gap-24 items-center px-12 max-w-7xl mx-auto">
<Step
stepNumber={1}
title="Sign up for a Campfire near you"
@ -214,42 +228,43 @@ function App() {
</section>
<section className="relative h-[900px] px-8">
<div className="absolute top-0 left-0 w-full h-full -translate-y-96 from-transparent to-[#022994] bg-gradient-to-b">
<img src="/decorative/clouds-3.png" alt="" className="w-full h-full object-cover" />
<div className="absolute top-0 left-0 w-full h-full -translate-y-96 from-transparent to-[#022994] bg-gradient-to-b pointer-events-none">
<img src="/decorative/clouds-3.png" alt="" className="w-full h-full object-cover select-none" />
</div>
<div className="relative w-full h-full z-50 -translate-y-32 bg-no-repeat bg-center bg-contain bg-[url(/backgrounds/world-map.png)]">
<div id="map" className="relative w-full h-full z-50 -translate-y-32 bg-no-repeat bg-center bg-contain bg-[url(/backgrounds/world-map.png)]">
</div>
</section>
<section className="relative py-24 bg-[#384fbc] -translate-y-100 bg-cover bg-center -z-10 pt-130 pb-60 bg-[url(/backgrounds/blue-gradient.png)]">
<div className="absolute bottom-0 left-0 w-full">
<div className="absolute bottom-0 left-0 w-full pointer-events-none">
<img
src="/decorative/clouds-1.png"
alt=""
className="w-full h-full object-contain"
className="w-full h-full object-contain select-none"
/>
</div>
<div className="absolute bottom-0 left-0 w-[80vw]">
<div className="absolute bottom-0 left-0 w-[80vw] pointer-events-none">
<img
src="/decorative/moon-composite.png"
alt=""
className="w-full h-full object-contain transform rotate-[346deg]"
className="w-full h-full object-contain transform rotate-[346deg] select-none"
/>
</div>
<div className="absolute bottom-[64px] translate-y-full scale-105 left-0 w-full">
<div className="absolute bottom-[64px] translate-y-full scale-105 left-0 w-full pointer-events-none">
<img
src="/decorative/puzzle-composite.png"
alt=""
className="w-full h-full object-cover"
className="w-full h-full object-cover select-none"
/>
</div>
<div className="relative z-10 flex flex-col gap-12 items-center px-32 max-w-7xl mx-auto -translate-y-56">
<h2
<h2
id="previous-events"
className="text-[#d7cfeb] text-6xl font-bold text-center mb-8 font-amatic"
style={{
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
@ -321,27 +336,28 @@ function App() {
</div>
</div>
<div className="absolute bottom-[-250px] scale-105 left-0 w-full">
<div className="absolute bottom-[-250px] scale-105 left-0 w-full pointer-events-none">
<img
src="/decorative/puzzle-cloud-bottom.png"
alt=""
className="w-full h-full object-cover"
className="w-full h-full object-cover select-none"
/>
</div>
</section>
<section className="relative bg-[#384fbc] pb-32 pt-64 -translate-y-96 -z-30">
<div className="absolute w-full h-full -z-10">
<div className="absolute w-full h-full -z-10 pointer-events-none">
<img
src="/decorative/speech-bubble-bg.png"
alt=""
className="w-full h-full"
className="w-full h-full select-none"
/>
</div>
<div className="relative z-10 px-32">
<h2
className="text-[#d7cfeb] text-[128px] font-normal text-center mb-16 font-amatic"
<h2
id="faq"
className="text-[#d7cfeb] text-[128px] font-bold text-center mb-16 font-amatic"
style={{
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
}}
@ -351,13 +367,13 @@ function App() {
<div className="flex gap-10 justify-center items-end">
<div className="relative">
<div className="absolute inset-0 w-[608px] h-[1491px]">
<img src="/ui/faq-participant-bg.svg" alt="" className="w-full h-full object-cover" />
<div className="absolute inset-0 w-[608px] h-[1491px] pointer-events-none">
<img src="/ui/faq-participant-bg.svg" alt="" className="w-full h-full object-cover select-none" />
</div>
<div className="relative z-10 flex flex-col gap-10 items-center px-16 pt-8 w-[608px]">
<p
className="text-[#d7cfeb] text-6xl font-normal text-center mb-4 font-amatic"
className="text-[#d7cfeb] text-6xl font-bold text-center mb-4 font-amatic"
style={{
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
}}
@ -365,23 +381,33 @@ function App() {
Participant
</p>
<FaqQuestion className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqQuestion question="Am I Eligible?" className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqQuestion question="But I've never hacked before!" className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqQuestion question="All this, for free?" className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqQuestion question="What do I need to bring?" className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqButton className="bg-[#091e8b] shadow-[8px_8px_0px_0px_#0a1861] flex items-start px-5 py-12 h-[168px] w-[467px]" />
<FaqQuestion question="What is a game jam?">
A game jam is an event where you build a game from scratch in a short time period! It's all about creativity, teamwork, and having fun while learning new skills.
</FaqQuestion>
<FaqQuestion question="Am I Eligible?">
If you're a high schooler (or younger), you're eligible! No prior experience required - just bring your enthusiasm and willingness to learn.
</FaqQuestion>
<FaqQuestion question="But I've never hacked before!">
Perfect! Game jams are designed for beginners. You'll have workshops, mentors, and teammates to help you every step of the way.
</FaqQuestion>
<FaqQuestion question="All this, for free?">
Yes! Everything is completely free - venue, food, swag, workshops, and prizes. Hack Club covers all costs so you can focus on creating.
</FaqQuestion>
<FaqQuestion question="What do I need to bring?">
Just bring yourself, a laptop, charger, and any personal items you need. We'll provide food, drinks, and everything else!
</FaqQuestion>
<FaqButton content="Check out the parent guide" />
</div>
</div>
<div className="relative">
<div className="absolute inset-0 w-[608px] h-[1505px]">
<img src="/ui/faq-organizer-bg.svg" alt="" className="w-full h-full object-cover" />
<div className="absolute inset-0 w-[608px] h-[1505px] pointer-events-none">
<img src="/ui/faq-organizer-bg.svg" alt="" className="w-full h-full object-cover select-none" />
</div>
<div className="relative z-10 flex flex-col gap-10 items-center px-16 pt-9 w-[608px]">
<p
className="text-[#d7cfeb] text-6xl font-normal text-center mb-4 font-amatic"
className="text-[#d7cfeb] text-6xl font-bold text-center mb-4 font-amatic"
style={{
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
}}
@ -389,12 +415,22 @@ function App() {
Organizer
</p>
<FaqQuestion question="Can I organize a Campfire in my city?" className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqQuestion question="What are the steps to organizing?" className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqQuestion question="Do we get funding?" className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqQuestion question="Do we get volunteer hours?" className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqQuestion question="Can I join an organizing team?" className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] w-[467px]" />
<FaqButton content="Apply to be an organizer" className="bg-[#091e8b] shadow-[8px_8px_0px_0px_#0a1861] flex items-start px-5 py-12 h-[168px] w-[467px]" />
<FaqQuestion question="Can I organize a Campfire in my city?">
Absolutely! We're always looking for passionate organizers. If you're ready to bring the magic of game development to your community, we'd love to help.
</FaqQuestion>
<FaqQuestion question="What are the steps to organizing?">
First, apply through our organizer form. Then we'll guide you through venue booking, team building, workshop planning, and day-of coordination.
</FaqQuestion>
<FaqQuestion question="Do we get funding?">
Yes! Hack Club provides funding for venue, food, swag, and other event costs. We want to remove financial barriers for amazing events.
</FaqQuestion>
<FaqQuestion question="Do we get volunteer hours?">
Many schools accept organizing hours as community service. Check with your school's requirements - we can provide documentation.
</FaqQuestion>
<FaqQuestion question="Can I join an organizing team?">
Of course! Many cities have organizing teams. Reach out to organizers in your area or apply to join an existing team.
</FaqQuestion>
<FaqButton content="Apply to be an organizer" />
</div>
</div>
</div>
@ -405,7 +441,7 @@ function App() {
<img
src="/backgrounds/footer-background.png"
alt=""
className="w-full"
className="w-full select-none"
/>
<div className="absolute bottom-0 left-0 w-full h-[190px] bg-[#0f371d] flex items-center justify-center">

View file

@ -1,16 +1,15 @@
interface FaqButtonProps {
className?: string;
content?: string;
content: string;
}
function FaqButton({ className = "", content = "Check out the parent guide" }: FaqButtonProps) {
function FaqButton({ content }: FaqButtonProps) {
return (
<div className={className}>
<div className="bg-[#091e8b] shadow-[8px_8px_0px_0px_#0a1861] flex items-start px-5 py-12 h-[168px] w-[467px]">
<div className="flex gap-1 items-center">
<div className="relative w-12 h-12 overflow-hidden">
<img
alt=""
className="absolute -inset-1 w-full h-full object-cover"
className="absolute -inset-1 w-full h-full object-cover select-none"
src="/icons/plus.svg"
/>
</div>

View file

@ -1,16 +1,38 @@
import { useState } from 'react';
interface FaqQuestionProps {
className?: string;
question?: string;
question: string;
children: React.ReactNode;
}
function FaqQuestion({ className = "", question = "What is a game jam?" }: FaqQuestionProps) {
function FaqQuestion({ question, children }: FaqQuestionProps) {
const [isExpanded, setIsExpanded] = useState(false);
const toggleExpanded = () => {
setIsExpanded(!isExpanded);
};
return (
<div className={className}>
<p
className="text-white text-5xl text-center font-bold leading-none w-full font-amatic"
<div className="w-[467px] cursor-pointer" onClick={toggleExpanded}>
<div className="bg-[#8d3f34] shadow-[8px_8px_0px_0px_#733a32] flex flex-col items-center justify-center px-12 py-0 h-[168px] transition-all duration-200 hover:scale-105">
<p
className="text-white text-5xl text-center font-bold leading-none w-full font-amatic"
>
{question}
</p>
</div>
<div
className={`overflow-hidden transition-all duration-300 ease-in-out ${
isExpanded ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
}`}
>
{question}
</p>
<div className="bg-[#6b2f26] shadow-[8px_8px_0px_0px_#5a251e] px-12 py-8 -mt-2">
<p className="text-white text-3xl font-normal leading-relaxed font-amatic">
{children}
</p>
</div>
</div>
</div>
);
}

View file

@ -0,0 +1,20 @@
interface NavbarLinkProps {
children: string;
onClick: () => void;
}
function NavbarLink({ children, onClick }: NavbarLinkProps) {
return (
<button
className="relative hover:opacity-80 transition-opacity cursor-pointer group"
onClick={onClick}
>
<span className="relative">
{children}
<span className="absolute left-0 -bottom-1 w-0 h-[3px] bg-white transition-all duration-300 ease-out group-hover:w-full"></span>
</span>
</button>
);
}
export default NavbarLink;