Skip to content

Commit 9754920

Browse files
committed
custom color feature
1 parent 40394be commit 9754920

File tree

4 files changed

+173
-25
lines changed

4 files changed

+173
-25
lines changed

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
A customizable countdown timer designed specifically for hackathons, ensuring participants stay on track and aware of their remaining time.
44

5-
## 🚀 Features
5+
🚀 **Try it now:** [Hackathon Countdown](https://codewithsimon.github.io/hackathon-countdown/)
6+
7+
## ✨ Features
68

79
🎯 **Customizable Details:** Add hackathon name, organizer, venue, and an end message.
810

@@ -14,6 +16,7 @@ A customizable countdown timer designed specifically for hackathons, ensuring pa
1416

1517
🌈 **Custom Colors:** Change the countdown colors to match your theme.
1618

19+
1720
## 📸 Screenshot
1821

1922
![Screenshot](Screenshot.png)
@@ -22,8 +25,28 @@ A customizable countdown timer designed specifically for hackathons, ensuring pa
2225

2326
🔗 **Online Access**
2427

25-
Use the countdown timer directly via this link: Hackathon Countdown
28+
Use the countdown timer directly via this link: [Hackathon Countdown](https://codewithsimon.github.io/hackathon-countdown/)
2629

2730
🛠️ **Self-Hosting**
2831

29-
Want to customize it further? Fork this repository and modify it as per your needs.
32+
Want to customize it further? Fork this repository and modify it as per your needs.
33+
34+
```bash
35+
# Clone the repository
36+
git clone https://github.com/your-username/hackathon-countdown.git
37+
38+
# Navigate into the directory
39+
cd hackathon-countdown
40+
41+
# Install dependencies (if any)
42+
npm install # or yarn install
43+
44+
# Run locally
45+
npm run dev # or yarn start
46+
47+
```
48+
***
49+
50+
Contributions and suggestions are always welcome! 🚀
51+
52+
**If you like this project, please star this repository!**

Screenshot.png

-46.2 KB
Loading

index.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
<meta charset="UTF-8" />
55
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7-
<title>Vite + React + TS</title>
7+
<meta property="og:title" content="Hackathon Countdown Timer" />
8+
<meta property="og:description" content="A customizable countdown timer designed specifically for hackathons." />
9+
<meta property="og:image" content="https://raw.githubusercontent.com/codewithsimon/hackathon-countdown/refs/heads/main/Screenshot.png" />
10+
<meta property="og:url" content="https://codewithsimon.github.io/hackathon-countdown/" />
11+
<meta property="og:type" content="website" />
12+
<title>Hackathon Countdown | @codewithsimon</title>
813
</head>
914
<body>
1015
<div id="root"></div>

src/App.tsx

Lines changed: 141 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState, useEffect, useRef } from 'react';
2-
import { Play, Pause, RotateCcw, Edit2, Moon, Sun, Trophy, Upload } from 'lucide-react';
2+
import { Play, Pause, RotateCcw, Edit2, Moon, Sun, Trophy, Upload, Palette } from 'lucide-react';
33

44
interface TimeConfig {
55
hours: number;
@@ -13,26 +13,63 @@ interface HackathonDetails {
1313
venue: string;
1414
endMessage: string;
1515
logo: string;
16+
colors: {
17+
light: {
18+
from: string;
19+
to: string;
20+
};
21+
dark: {
22+
from: string;
23+
to: string;
24+
};
25+
};
1626
}
1727

1828
function App() {
1929
const [timeLeft, setTimeLeft] = useState<TimeConfig>({ hours: 0, minutes: 0, seconds: 0 });
2030
const [isRunning, setIsRunning] = useState(false);
2131
const [isEditing, setIsEditing] = useState(false);
22-
const [isDarkMode, setIsDarkMode] = useState(true);
32+
const [isDarkMode, setIsDarkMode] = useState(false);
2333
const [isEnded, setIsEnded] = useState(false);
2434
const [initialTime, setInitialTime] = useState<TimeConfig>({ hours: 0, minutes: 0, seconds: 0 });
2535
const [hackathonDetails, setHackathonDetails] = useState<HackathonDetails>({
26-
name: "HackIndia",
36+
name: "Hackathon",
2737
organizer: "Tech Community",
2838
venue: "Innovation Hub",
2939
endMessage: "Time's up! Great work everyone! 🎉",
30-
logo: ""
40+
logo: "",
41+
colors: {
42+
light: {
43+
from: "#074799",
44+
to: "#009990"
45+
},
46+
dark: {
47+
from: "#074799",
48+
to: "#009990"
49+
}
50+
}
3151
});
3252
const [isEditingDetails, setIsEditingDetails] = useState(false);
53+
const [isEditingColors, setIsEditingColors] = useState(false);
3354
const timerRef = useRef<NodeJS.Timeout>();
3455
const fileInputRef = useRef<HTMLInputElement>(null);
3556

57+
useEffect(() => {
58+
// Update CSS variables when colors change
59+
const root = document.documentElement;
60+
if (isDarkMode) {
61+
root.style.setProperty('--gradient-from', hackathonDetails.colors.dark.from);
62+
root.style.setProperty('--gradient-to', hackathonDetails.colors.dark.to);
63+
root.style.setProperty('--card-from', `${hackathonDetails.colors.light.from}33`); // 20% opacity
64+
root.style.setProperty('--card-to', `${hackathonDetails.colors.light.to}33`); // 20% opacity
65+
} else {
66+
root.style.setProperty('--gradient-from', hackathonDetails.colors.light.from);
67+
root.style.setProperty('--gradient-to', hackathonDetails.colors.light.to);
68+
root.style.setProperty('--card-from', '#ffffff1a'); // 10% white
69+
root.style.setProperty('--card-to', '#ffffff1a');
70+
}
71+
}, [isDarkMode, hackathonDetails.colors]);
72+
3673
useEffect(() => {
3774
if (isRunning) {
3875
timerRef.current = setInterval(() => {
@@ -88,6 +125,11 @@ function App() {
88125
setIsEditingDetails(false);
89126
};
90127

128+
const handleColorsSubmit = (e: React.FormEvent) => {
129+
e.preventDefault();
130+
setIsEditingColors(false);
131+
};
132+
91133
const handleLogoUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
92134
const file = e.target.files?.[0];
93135
if (file) {
@@ -101,17 +143,8 @@ function App() {
101143

102144
const formatNumber = (num: number) => num.toString().padStart(2, '0');
103145

104-
const containerClasses = `min-h-screen transition-colors duration-500 ${
105-
isDarkMode
106-
? 'bg-gradient-to-br from-black to-gray-900'
107-
: 'bg-gradient-to-br from-[#074799] to-[#009990]'
108-
}`;
109-
110-
const cardClasses = `transform transition-all duration-500 ${
111-
isDarkMode
112-
? 'bg-gradient-to-br from-[#074799]/50 to-[#009990]/50 border-white/10'
113-
: 'bg-white/10 border-white/20'
114-
} backdrop-blur-lg rounded-2xl p-8 w-full max-w-5xl shadow-xl border`;
146+
const containerClasses = "min-h-screen transition-colors duration-500 bg-gradient-to-br from-[var(--gradient-from)] to-[var(--gradient-to)]";
147+
const cardClasses = "transform transition-all duration-500 bg-gradient-to-br from-[var(--card-from)] to-[var(--card-to)] backdrop-blur-lg rounded-2xl p-8 w-full max-w-5xl shadow-xl border border-white/10";
115148

116149
if (isEnded) {
117150
return (
@@ -151,12 +184,20 @@ function App() {
151184
<div className={containerClasses + " flex items-center justify-center p-4"}>
152185
<div className={cardClasses}>
153186
<div className="flex justify-between items-center mb-8">
154-
<button
155-
onClick={() => setIsDarkMode(!isDarkMode)}
156-
className="text-white/70 hover:text-white transition-colors"
157-
>
158-
{isDarkMode ? <Sun size={24} /> : <Moon size={24} />}
159-
</button>
187+
<div className="flex gap-4">
188+
<button
189+
onClick={() => setIsDarkMode(!isDarkMode)}
190+
className="text-white/70 hover:text-white transition-colors"
191+
>
192+
{isDarkMode ? <Sun size={24} /> : <Moon size={24} />}
193+
</button>
194+
<button
195+
onClick={() => setIsEditingColors(!isEditingColors)}
196+
className="text-white/70 hover:text-white transition-colors"
197+
>
198+
<Palette size={24} />
199+
</button>
200+
</div>
160201
<div className="flex gap-4">
161202
<button
162203
onClick={() => fileInputRef.current?.click()}
@@ -181,6 +222,85 @@ function App() {
181222
</div>
182223
</div>
183224

225+
{isEditingColors && (
226+
<form onSubmit={handleColorsSubmit} className="mb-8 p-4 bg-black/20 rounded-lg border border-white/10">
227+
<div className="grid grid-cols-2 gap-6">
228+
<div className="space-y-4">
229+
<h3 className="text-white font-semibold mb-2">Light Mode Colors</h3>
230+
<div>
231+
<label className="block text-white/70 text-sm mb-1">From Color</label>
232+
<input
233+
type="color"
234+
value={hackathonDetails.colors.light.from}
235+
onChange={(e) => setHackathonDetails(prev => ({
236+
...prev,
237+
colors: {
238+
...prev.colors,
239+
light: { ...prev.colors.light, from: e.target.value }
240+
}
241+
}))}
242+
className="w-full h-10 rounded cursor-pointer"
243+
/>
244+
</div>
245+
<div>
246+
<label className="block text-white/70 text-sm mb-1">To Color</label>
247+
<input
248+
type="color"
249+
value={hackathonDetails.colors.light.to}
250+
onChange={(e) => setHackathonDetails(prev => ({
251+
...prev,
252+
colors: {
253+
...prev.colors,
254+
light: { ...prev.colors.light, to: e.target.value }
255+
}
256+
}))}
257+
className="w-full h-10 rounded cursor-pointer"
258+
/>
259+
</div>
260+
</div>
261+
<div className="space-y-4">
262+
<h3 className="text-white font-semibold mb-2">Dark Mode Colors</h3>
263+
<div>
264+
<label className="block text-white/70 text-sm mb-1">From Color</label>
265+
<input
266+
type="color"
267+
value={hackathonDetails.colors.dark.from}
268+
onChange={(e) => setHackathonDetails(prev => ({
269+
...prev,
270+
colors: {
271+
...prev.colors,
272+
dark: { ...prev.colors.dark, from: e.target.value }
273+
}
274+
}))}
275+
className="w-full h-10 rounded cursor-pointer"
276+
/>
277+
</div>
278+
<div>
279+
<label className="block text-white/70 text-sm mb-1">To Color</label>
280+
<input
281+
type="color"
282+
value={hackathonDetails.colors.dark.to}
283+
onChange={(e) => setHackathonDetails(prev => ({
284+
...prev,
285+
colors: {
286+
...prev.colors,
287+
dark: { ...prev.colors.dark, to: e.target.value }
288+
}
289+
}))}
290+
className="w-full h-10 rounded cursor-pointer"
291+
/>
292+
</div>
293+
</div>
294+
</div>
295+
<button
296+
type="submit"
297+
className="w-full mt-6 bg-white/10 hover:bg-white/20 text-white py-2 rounded-lg transition-colors"
298+
>
299+
Save Colors
300+
</button>
301+
</form>
302+
)}
303+
184304
{hackathonDetails.logo && (
185305
<div className="flex justify-center mb-8">
186306
<img

0 commit comments

Comments
 (0)