-
Notifications
You must be signed in to change notification settings - Fork 36
feat: ✨ Add Festive Animations to Hacktoberfest Page #124
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
Open
kuNA78-hub
wants to merge
5
commits into
HXQLabs:develop
Choose a base branch
from
kuNA78-hub:feat/hacktoberfest-animations
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
107a4c6
Merge pull request #117 from HXQLabs/develop
javatcoding1 55ecc95
Merge pull request #118 from HXQLabs/develop
javatcoding1 f3b78e6
feat: Add festive animations to Hacktoberfest page
kuNA78-hub ddb1398
fix: Address code review feedback from CodeRabbit
kuNA78-hub 874061d
fix: Address all final review feedback from CodeRabbit
kuNA78-hub File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,120 +1,30 @@ | ||
| import { Badge } from "@/components/ui/badge"; | ||
| import { CleanCountdown } from "@/components/utils/clean-countdown"; | ||
| import { BookOpen, Bug } from "lucide-react"; | ||
| import { Icons } from "@/components/utils/icons"; | ||
| import { AuroraText } from "@/components/ui/aurora-text"; | ||
| import HacktoberfestClientContent from "@/components/hacktoberfest-client-content"; | ||
|
|
||
| export default function HacktoberfestPage() { | ||
| // Determine the relevant Hacktoberfest year dynamically | ||
| const now = new Date(); | ||
| const currentYear = now.getFullYear(); | ||
| // If we're in October, use current year; if before October, use current year; if after October, use next year | ||
| const eventYear = now.getMonth() === 9 | ||
| ? currentYear | ||
| : (now.getMonth() > 9 ? currentYear + 1 : currentYear); | ||
|
|
||
| const eventYear = 2025; | ||
| const start = new Date(`${eventYear}-10-01T00:00:00`); | ||
| const end = new Date(`${eventYear}-10-31T23:59:59`); | ||
| const active = now >= start && now <= end; | ||
| const active = true; | ||
| const hacktoberfestEnd = end; | ||
|
|
||
| return ( | ||
| <div className="bg-background relative overflow-x-hidden"> | ||
| {/* Decorative radial gradient background */} | ||
| <div className="pointer-events-none absolute inset-0 -z-10"> | ||
| <div className="relative overflow-x-hidden min-h-screen"> | ||
| {/* Dedicated div for background color */} | ||
| <div className="absolute inset-0 -z-50 bg-background" /> | ||
|
|
||
| {/* Static radial gradients */} | ||
| <div className="pointer-events-none absolute inset-0 -z-30"> | ||
| <div className="absolute left-1/2 top-10 -translate-x-1/2 h-56 w-56 rounded-full bg-orange-400/20 blur-3xl" /> | ||
| <div className="absolute right-10 top-20 h-40 w-40 rounded-full bg-purple-500/10 blur-3xl" /> | ||
| <div className="absolute left-10 bottom-10 h-44 w-44 rounded-full bg-amber-300/10 blur-3xl" /> | ||
| </div> | ||
| {/* Page Title Section */} | ||
| <div className={active ? "pt-10 pb-16" : "pt-10 pb-12"}> | ||
| <div className="max-w-5xl mx-auto px-6 lg:px-10 text-center"> | ||
| <div className="flex items-center justify-center gap-3 mb-6"> | ||
| <span role="img" aria-label="pumpkin" className="text-2xl">🎃</span> | ||
| <Badge | ||
| variant="secondary" | ||
| className="px-3 py-1 text-orange-600 bg-orange-100 dark:bg-orange-900/30 dark:text-orange-400 shadow-sm" | ||
| > | ||
| {active ? "Hacktoberfest is Live!" : "Coming Soon"} | ||
| </Badge> | ||
| <span role="img" aria-label="pumpkin" className="text-2xl">🎃</span> | ||
| </div> | ||
|
|
||
| <h1 className="text-foreground text-4xl sm:text-5xl md:text-6xl font-extrabold tracking-tight leading-[1.15] mb-4"> | ||
| {/* Join Helixque for <span className="text-orange-500">Hacktoberfest</span> */} | ||
| Join Helixque for <AuroraText>Hacktoberfest</AuroraText> | ||
| </h1> | ||
|
|
||
| <p className="text-muted-foreground text-base tracking-tight mt-6 max-w-2xl mx-auto sm:text-lg"> | ||
| {active | ||
| ? ( | ||
| <> | ||
| <span className="block">Join us in celebrating open source!</span> | ||
| <span className="block">Contribute to our projects and be part of the Hacktoberfest community.</span> | ||
| </> | ||
| ) | ||
| : "We understand your eagerness to contribute and we're thankful for that, but you'll need to wait until the event begins." | ||
| } | ||
| </p> | ||
| </div> | ||
| </div> | ||
|
|
||
| {/* Countdown Timer */} | ||
| {active && ( | ||
| <div className="mb-16 flex justify-center"> | ||
| <CleanCountdown | ||
| endDate={hacktoberfestEnd} | ||
| label={`Time left in Hacktoberfest ${eventYear}`} | ||
| expiredMessage={`🎉 Hacktoberfest ${eventYear} has ended! 🎉`} | ||
| /> | ||
| </div> | ||
| )} | ||
|
|
||
| {/* Content Section */} | ||
| <div className="max-w-5xl mx-auto px-6 mb-10 lg:px-10 text-center"> | ||
| <p className="text-lg text-muted-foreground mb-8"> | ||
| {active | ||
| ? "Ready to contribute? Check out our repositories and start making a difference!" | ||
| : "Meanwhile, explore our work and get ready to contribute." | ||
| } | ||
| </p> | ||
|
|
||
| <div className="flex flex-wrap items-center justify-center gap-3 sm:gap-4"> | ||
| <a | ||
| href="https://github.com/orgs/HXQLabs/repositories" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm sm:text-[13.5px] hover:bg-muted transition-colors bg-gradient-to-b from-background to-muted/30" | ||
| > | ||
| <Icons.github className="w-4 h-4" /> | ||
| Browse our repositories | ||
| </a> | ||
|
|
||
| <a | ||
| href="https://github.com/HXQLabs/HelixQue/blob/main/CONTRIBUTING.md" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm sm:text-[13.5px] hover:bg-muted transition-colors bg-gradient-to-b from-background to-muted/30" | ||
| > | ||
| <BookOpen className="w-4 h-4" /> | ||
| See contributing guidelines | ||
| </a> | ||
|
|
||
| <a | ||
| href="https://github.com/search?q=org%3AHXQLabs+state%3Aopen&type=Issues" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm sm:text-[13.5px] hover:bg-muted transition-colors bg-gradient-to-b from-background to-muted/30" | ||
| > | ||
| <Bug className="w-4 h-4" /> | ||
| Find issues | ||
| </a> | ||
| </div> | ||
|
|
||
| <p className="mt-6 text-sm sm:text-base text-muted-foreground"> | ||
| Gear up your issues, sharpen those PRs, and let the commits roll in! ⚡️ | ||
| </p> | ||
| </div> | ||
| {/* Client content with animations */} | ||
| <HacktoberfestClientContent | ||
| active={active} | ||
| eventYear={eventYear} | ||
| hacktoberfestEnd={hacktoberfestEnd} | ||
| /> | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| "use client"; | ||
|
|
||
| import React, { Suspense, useMemo } from 'react'; | ||
| import { Canvas } from '@react-three/fiber'; | ||
| import { Environment } from '@react-three/drei'; | ||
| import { usePrefersReducedMotion } from '@/hooks/use-prefers-reduced-motion'; | ||
| import { Leaf3D } from './leaf-3d'; | ||
|
|
||
| interface FallingLeaves3DProps { | ||
| count?: number; | ||
| } | ||
|
|
||
| export function FallingLeaves3D({ count = 50 }: FallingLeaves3DProps) { | ||
| // All hooks must be called at the top level, before any returns. | ||
| const prefersReducedMotion = usePrefersReducedMotion(); | ||
|
|
||
| const leaves = useMemo(() => { | ||
| // ✨ FIX: Check if `window` exists to prevent errors during server-side rendering. | ||
| const effectiveWidth = typeof window !== "undefined" ? window.innerWidth : 1024; | ||
| const numLeaves = effectiveWidth < 768 ? Math.floor(count / 2) : count; | ||
|
|
||
| return Array.from({ length: numLeaves }).map((_, i) => ({ | ||
| id: i, | ||
| initialPosition: [ | ||
| Math.random() * 20 - 10, | ||
| Math.random() * 20 + 5, | ||
| Math.random() * 10 - 5 | ||
| ] as [number, number, number], | ||
| speed: 0.5 + Math.random() * 0.5, | ||
| rotationSpeed: 0.5 + Math.random() * 0.5, | ||
| windForce: 0.1 + Math.random() * 0.2, | ||
| })); | ||
| }, [count]); | ||
|
|
||
| // ✨ FIX: The `if` check is now moved *after* all hooks have been called. | ||
| if (prefersReducedMotion) { | ||
| return null; | ||
| } | ||
|
|
||
| return ( | ||
| <div className="absolute inset-0 -z-10"> | ||
| <Canvas | ||
| camera={{ position: [0, 0, 15], fov: 75 }} | ||
| style={{ background: 'transparent' }} | ||
| // ✨ FIX: Added `dpr` prop for performance optimization on high-res screens. | ||
| dpr={[1, 2]} | ||
| gl={{ antialias: true, powerPreference: "high-performance" }} | ||
| > | ||
| <ambientLight intensity={0.5} /> | ||
| <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} /> | ||
| <pointLight position={[-10, -10, -10]} /> | ||
| <Environment preset="forest" /> | ||
|
|
||
| <Suspense fallback={null}> | ||
| {leaves.map((leaf) => ( | ||
| <Leaf3D | ||
| key={leaf.id} | ||
| initialPosition={leaf.initialPosition} | ||
| speed={leaf.speed} | ||
| rotationSpeed={leaf.rotationSpeed} | ||
| windForce={leaf.windForce} | ||
| ground={-10} | ||
| boundary={{ x: [-15, 15], z: [-10, 10] }} | ||
| /> | ||
| ))} | ||
| </Suspense> | ||
| </Canvas> | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| "use client"; | ||
|
|
||
| import { useEffect, useMemo, useState, useCallback } from "react"; | ||
| import Particles from "react-tsparticles"; // ✨ FIX: Removed the incorrect named import here | ||
| import { loadSlim } from "tsparticles-slim"; | ||
| import { type Container, type ISourceOptions, initParticlesEngine } from "@tsparticles/engine"; // ✨ FIX: This is the ONLY place to import the engine | ||
| import { usePrefersReducedMotion } from "@/hooks/use-prefers-reduced-motion"; | ||
|
|
||
| export function FestiveBackground() { | ||
| const [init, setInit] = useState(false); | ||
| const prefersReducedMotion = usePrefersReducedMotion(); | ||
|
|
||
| // This useEffect should only run once on mount to initialize the engine | ||
| useEffect(() => { | ||
| initParticlesEngine(async (engine) => { | ||
| await loadSlim(engine); | ||
| }).then(() => { | ||
| setInit(true); | ||
| }); | ||
| }, []); | ||
|
|
||
| const particlesLoaded = useCallback(async (container?: Container) => { | ||
| // Optional: console.log("Particles loaded", container); | ||
| }, []); | ||
|
|
||
| const options: ISourceOptions = useMemo( | ||
| () => ({ | ||
| background: { | ||
| color: { | ||
| value: "transparent", | ||
| }, | ||
| }, | ||
| fpsLimit: 60, | ||
| particles: { | ||
| number: { | ||
| value: prefersReducedMotion ? 0 : 60, | ||
| density: { | ||
| enable: true, | ||
| value_area: 800, | ||
| }, | ||
| }, | ||
| color: { | ||
| value: ["#ff7f50", "#ff6347", "#ffa500", "#ffffff"], | ||
| }, | ||
| shape: { | ||
| type: "circle", | ||
| }, | ||
| opacity: { | ||
| value: { min: 0.3, max: 0.8 }, | ||
| animation: { | ||
| enable: true, | ||
| speed: 1, | ||
| sync: false, | ||
| }, | ||
| }, | ||
| size: { | ||
| value: { min: 1, max: 4 }, | ||
| }, | ||
| move: { | ||
| enable: !prefersReducedMotion, // Disable movement if reduced motion is on | ||
| direction: "bottom", | ||
| speed: 2, | ||
| straight: true, | ||
| outModes: { | ||
| default: "out", | ||
| }, | ||
| }, | ||
| }, | ||
| interactivity: { | ||
| events: { | ||
| onHover: { | ||
| enable: !prefersReducedMotion, | ||
| mode: "trail", | ||
| }, | ||
| }, | ||
| modes: { | ||
| trail: { | ||
| quantity: 3, | ||
| delay: 0.1, | ||
| particles: { | ||
| size: { | ||
| value: { min: 1, max: 3 }, | ||
| animation: { | ||
| enable: true, | ||
| speed: 20, | ||
| sync: true, | ||
| startValue: "min", | ||
| destroy: "max", | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| detectRetina: true, | ||
| }), | ||
| [prefersReducedMotion] | ||
| ); | ||
|
|
||
| if (init) { | ||
| return ( | ||
| <Particles | ||
| id="tsparticles" | ||
| particlesLoaded={particlesLoaded} | ||
| options={options} | ||
| className="absolute inset-0 -z-10" | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.