diff --git a/src/app/components/SupporterMessage.tsx b/src/app/components/SupporterMessage.tsx
index 678b1bdd..7706e190 100644
--- a/src/app/components/SupporterMessage.tsx
+++ b/src/app/components/SupporterMessage.tsx
@@ -5,29 +5,41 @@ import confetti from "canvas-confetti";
export default function SupporterMessage({ tier }: { tier: string }) {
return (
-
-
+
{
// Get the bounding box of the element
const rect = (
e.target as HTMLElement
).getBoundingClientRect();
- // Calculate the origin based on the top center of the box
+ // Trigger confetti centered on the word "Pangolin"
confetti({
particleCount: 100,
spread: 70,
origin: {
- x: (rect.left + rect.width / 2) / window.innerWidth, // Horizontal center of the box
- y: rect.top / window.innerHeight // Top of the box
- }
+ x: (rect.left + rect.width / 2) / window.innerWidth,
+ y: rect.top / window.innerHeight
+ },
+ colors: ["#FFA500", "#FF4500", "#FFD700"]
});
}}
>
-
- Thank you for supporting Pangolin as a {tier}!
-
+ Pangolin
+
+ {/* SVG Star */}
+
+
+
+ {/* Popover */}
+
+ Thank you for supporting Pangolin as a {tier}!
);
diff --git a/src/app/globals.css b/src/app/globals.css
index cb32e061..db1d8feb 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -2,65 +2,63 @@
@tailwind components;
@tailwind utilities;
-
@layer base {
- :root {
- --background: 0 0% 100%;
- --foreground: 20 0.0% 10.0%;
- --card: 0 0% 100%;
- --card-foreground: 20 0.0% 10.0%;
- --popover: 0 0% 100%;
- --popover-foreground: 20 0.0% 10.0%;
- --primary: 24.6 95% 53.1%;
- --primary-foreground: 60 9.1% 97.8%;
- --secondary: 60 4.8% 95.9%;
- --secondary-foreground: 24 9.8% 10%;
- --muted: 60 4.8% 85.0%;
- --muted-foreground: 25 5.3% 44.7%;
- --accent: 60 4.8% 90%;
- --accent-foreground: 24 9.8% 10%;
- --destructive: 0 84.2% 60.2%;
- --destructive-foreground: 60 9.1% 97.8%;
- --border: 20 5.9% 80%;
- --input: 20 5.9% 75%;
- --ring: 24.6 95% 53.1%;
- --radius: 0.75rem;
- --chart-1: 12 76% 61%;
- --chart-2: 173 58% 39%;
- --chart-3: 197 37% 24%;
- --chart-4: 43 74% 66%;
- --chart-5: 27 87% 67%;
- }
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 20 0% 10%;
+ --card: 0 0% 100%;
+ --card-foreground: 20 0% 10%;
+ --popover: 0 0% 100%;
+ --popover-foreground: 20 0% 10%;
+ --primary: 24.6 95% 53.1%;
+ --primary-foreground: 60 9.1% 97.8%;
+ --secondary: 60 4.8% 95.9%;
+ --secondary-foreground: 24 9.8% 10%;
+ --muted: 60 4.8% 85%;
+ --muted-foreground: 25 5.3% 44.7%;
+ --accent: 60 4.8% 90%;
+ --accent-foreground: 24 9.8% 10%;
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 60 9.1% 97.8%;
+ --border: 20 5.9% 80%;
+ --input: 20 5.9% 75%;
+ --ring: 24.6 95% 53.1%;
+ --radius: 0.75rem;
+ --chart-1: 12 76% 61%;
+ --chart-2: 173 58% 39%;
+ --chart-3: 197 37% 24%;
+ --chart-4: 43 74% 66%;
+ --chart-5: 27 87% 67%;
+ }
- .dark {
- --background: 20 0.0% 10.0%;
- --foreground: 60 9.1% 97.8%;
- --card: 20 0.0% 10.0%;
- --card-foreground: 60 9.1% 97.8%;
- --popover: 20 0.0% 10.0%;
- --popover-foreground: 60 9.1% 97.8%;
- --primary: 20.5 90.2% 48.2%;
- --primary-foreground: 60 9.1% 97.8%;
- --secondary: 12 6.5% 15.0%;
- --secondary-foreground: 60 9.1% 97.8%;
- --muted: 12 6.5% 25.0%;
- --muted-foreground: 24 5.4% 63.9%;
- --accent: 12 2.5% 15.0%;
- --accent-foreground: 60 9.1% 97.8%;
- --destructive: 0 72.2% 50.6%;
- --destructive-foreground: 60 9.1% 97.8%;
- --border: 12 6.5% 30.0%;
- --input: 12 6.5% 35.0%;
- --ring: 20.5 90.2% 48.2%;
- --chart-1: 220 70% 50%;
- --chart-2: 160 60% 45%;
- --chart-3: 30 80% 55%;
- --chart-4: 280 65% 60%;
- --chart-5: 340 75% 55%;
- }
+ .dark {
+ --background: 20 0% 10%;
+ --foreground: 60 9.1% 97.8%;
+ --card: 20 0% 10%;
+ --card-foreground: 60 9.1% 97.8%;
+ --popover: 20 0% 10%;
+ --popover-foreground: 60 9.1% 97.8%;
+ --primary: 20.5 90.2% 48.2%;
+ --primary-foreground: 60 9.1% 97.8%;
+ --secondary: 12 6.5% 15%;
+ --secondary-foreground: 60 9.1% 97.8%;
+ --muted: 12 6.5% 25%;
+ --muted-foreground: 24 5.4% 63.9%;
+ --accent: 12 2.5% 15%;
+ --accent-foreground: 60 9.1% 97.8%;
+ --destructive: 0 72.2% 50.6%;
+ --destructive-foreground: 60 9.1% 97.8%;
+ --border: 12 6.5% 30%;
+ --input: 12 6.5% 35%;
+ --ring: 20.5 90.2% 48.2%;
+ --chart-1: 220 70% 50%;
+ --chart-2: 160 60% 45%;
+ --chart-3: 30 80% 55%;
+ --chart-4: 280 65% 60%;
+ --chart-5: 340 75% 55%;
+ }
}
-
@layer base {
* {
@apply border-border;
@@ -70,4 +68,3 @@
@apply bg-background text-foreground;
}
}
-
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 8d472673..9a6f7cb9 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -62,9 +62,15 @@ export default async function RootLayout({
{/* Footer */}
diff --git a/src/components/SupporterStatus.tsx b/src/components/SupporterStatus.tsx
index b7b45c40..a08fdf77 100644
--- a/src/components/SupporterStatus.tsx
+++ b/src/components/SupporterStatus.tsx
@@ -47,6 +47,7 @@ import {
CardTitle
} from "./ui/card";
import { Check, ExternalLink } from "lucide-react";
+import confetti from "canvas-confetti";
const formSchema = z.object({
githubUsername: z
@@ -100,6 +101,7 @@ export default function SupporterStatus() {
return;
}
+ // Trigger the toast
toast({
variant: "default",
title: "Valid Key",
@@ -107,6 +109,50 @@ export default function SupporterStatus() {
"Your supporter key has been validated. Thank you for your support!"
});
+ // Fireworks-style confetti
+ const duration = 5 * 1000; // 5 seconds
+ const animationEnd = Date.now() + duration;
+ const defaults = {
+ startVelocity: 30,
+ spread: 360,
+ ticks: 60,
+ zIndex: 0,
+ colors: ["#FFA500", "#FF4500", "#FFD700"] // Orange hues
+ };
+
+ function randomInRange(min: number, max: number) {
+ return Math.random() * (max - min) + min;
+ }
+
+ const interval = setInterval(() => {
+ const timeLeft = animationEnd - Date.now();
+
+ if (timeLeft <= 0) {
+ clearInterval(interval);
+ return;
+ }
+
+ const particleCount = 50 * (timeLeft / duration);
+
+ // Launch confetti from two random horizontal positions
+ confetti({
+ ...defaults,
+ particleCount,
+ origin: {
+ x: randomInRange(0.1, 0.3),
+ y: Math.random() - 0.2
+ }
+ });
+ confetti({
+ ...defaults,
+ particleCount,
+ origin: {
+ x: randomInRange(0.7, 0.9),
+ y: Math.random() - 0.2
+ }
+ });
+ }, 250);
+
setPurchaseOptionsOpen(false);
setKeyOpen(false);
@@ -177,7 +223,9 @@ export default function SupporterStatus() {
-
Please select the option that best suits you.
+
+ Please select the option that best suits you.
+
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 1978d23a..67762da1 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -5,59 +5,59 @@ const config: Config = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
- "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
+ "./src/app/**/*.{js,ts,jsx,tsx,mdx}"
],
theme: {
extend: {
colors: {
- background: 'hsl(var(--background))',
- foreground: 'hsl(var(--foreground))',
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
card: {
- DEFAULT: 'hsl(var(--card))',
- foreground: 'hsl(var(--card-foreground))'
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))"
},
popover: {
- DEFAULT: 'hsl(var(--popover))',
- foreground: 'hsl(var(--popover-foreground))'
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))"
},
primary: {
- DEFAULT: 'hsl(var(--primary))',
- foreground: 'hsl(var(--primary-foreground))'
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))"
},
secondary: {
- DEFAULT: 'hsl(var(--secondary))',
- foreground: 'hsl(var(--secondary-foreground))'
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))"
},
muted: {
- DEFAULT: 'hsl(var(--muted))',
- foreground: 'hsl(var(--muted-foreground))'
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))"
},
accent: {
- DEFAULT: 'hsl(var(--accent))',
- foreground: 'hsl(var(--accent-foreground))'
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))"
},
destructive: {
- DEFAULT: 'hsl(var(--destructive))',
- foreground: 'hsl(var(--destructive-foreground))'
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))"
},
- border: 'hsl(var(--border))',
- input: 'hsl(var(--input))',
- ring: 'hsl(var(--ring))',
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
chart: {
- '1': 'hsl(var(--chart-1))',
- '2': 'hsl(var(--chart-2))',
- '3': 'hsl(var(--chart-3))',
- '4': 'hsl(var(--chart-4))',
- '5': 'hsl(var(--chart-5))'
+ "1": "hsl(var(--chart-1))",
+ "2": "hsl(var(--chart-2))",
+ "3": "hsl(var(--chart-3))",
+ "4": "hsl(var(--chart-4))",
+ "5": "hsl(var(--chart-5))"
}
},
borderRadius: {
- lg: 'var(--radius)',
- md: 'calc(var(--radius) - 2px)',
- sm: 'calc(var(--radius) - 4px)'
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)"
}
}
},
- plugins: [require("tailwindcss-animate")],
+ plugins: [require("tailwindcss-animate")]
};
export default config;