Configurable theme, change default to blue

This commit is contained in:
Joey Yakimowich-Payne 2026-01-13 11:04:52 -07:00
commit ec318e9e9a
No known key found for this signature in database
GPG key ID: DDF6AF5B21B407D4
8 changed files with 46 additions and 25 deletions

View file

@ -31,7 +31,7 @@ export const GameScreen: React.FC<GameScreenProps> = ({
// Timer styling logic
const isUrgent = timeLeft < 5 && timeLeft > 0;
const timerBorderColor = isUrgent ? 'border-red-500' : 'border-white';
const timerTextColor = isUrgent ? 'text-red-500' : 'text-[#46178f]';
const timerTextColor = isUrgent ? 'text-red-500' : 'text-theme-primary';
const timerAnimation = isUrgent ? 'animate-ping' : '';
return (
@ -123,7 +123,7 @@ export const GameScreen: React.FC<GameScreenProps> = ({
{isClient && hasAnswered && (
<motion.div
initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
className="absolute inset-0 bg-[#46178f]/95 flex flex-col items-center justify-center z-50 p-8 text-center"
className="absolute inset-0 bg-theme-primary/95 flex flex-col items-center justify-center z-50 p-8 text-center"
>
<motion.div
animate={{ scale: [1, 1.2, 1] }}

View file

@ -35,23 +35,23 @@ export const Landing: React.FC<LandingProps> = ({ onGenerate, onCreateManual, on
className="bg-white text-gray-900 p-8 rounded-[2rem] shadow-[0_10px_0_rgba(0,0,0,0.1)] max-w-md w-full border-4 border-white/50"
>
<div className="flex justify-center mb-6">
<div className="bg-[#46178f] p-4 rounded-3xl rotate-3 shadow-lg">
<div className="bg-theme-primary p-4 rounded-3xl rotate-3 shadow-lg">
<BrainCircuit size={48} className="text-white" />
</div>
</div>
<h1 className="text-5xl font-black mb-2 text-[#46178f] tracking-tight">Kaboot</h1>
<h1 className="text-5xl font-black mb-2 text-theme-primary tracking-tight">Kaboot</h1>
<p className="text-gray-500 font-bold mb-6">The AI Quiz Party</p>
<div className="flex bg-gray-100 p-2 rounded-2xl mb-8">
<button
onClick={() => setMode('HOST')}
className={`flex-1 py-3 rounded-xl font-black text-lg transition-all duration-200 ${mode === 'HOST' ? 'bg-white shadow-md text-[#46178f] scale-105' : 'text-gray-400 hover:text-gray-600'}`}
className={`flex-1 py-3 rounded-xl font-black text-lg transition-all duration-200 ${mode === 'HOST' ? 'bg-white shadow-md text-theme-primary scale-105' : 'text-gray-400 hover:text-gray-600'}`}
>
Host
</button>
<button
onClick={() => setMode('JOIN')}
className={`flex-1 py-3 rounded-xl font-black text-lg transition-all duration-200 ${mode === 'JOIN' ? 'bg-white shadow-md text-[#46178f] scale-105' : 'text-gray-400 hover:text-gray-600'}`}
className={`flex-1 py-3 rounded-xl font-black text-lg transition-all duration-200 ${mode === 'JOIN' ? 'bg-white shadow-md text-theme-primary scale-105' : 'text-gray-400 hover:text-gray-600'}`}
>
Join
</button>
@ -65,7 +65,7 @@ export const Landing: React.FC<LandingProps> = ({ onGenerate, onCreateManual, on
placeholder="Topic (e.g. 'Space')"
value={topic}
onChange={(e) => setTopic(e.target.value)}
className="w-full p-4 text-xl font-bold border-2 border-gray-200 rounded-2xl focus:border-[#46178f] focus:ring-4 focus:ring-[#46178f]/20 outline-none transition-all placeholder:font-medium text-center"
className="w-full p-4 text-xl font-bold border-2 border-gray-200 rounded-2xl focus:border-theme-primary focus:ring-4 focus:ring-theme-primary/20 outline-none transition-all placeholder:font-medium text-center"
disabled={isLoading}
/>
<button
@ -85,7 +85,7 @@ export const Landing: React.FC<LandingProps> = ({ onGenerate, onCreateManual, on
<button
onClick={onCreateManual}
className="w-full bg-white border-2 border-[#46178f] text-[#46178f] py-3 rounded-2xl text-lg font-black hover:bg-purple-50 shadow-[0_4px_0_#46178f] active:shadow-none active:translate-y-[4px] transition-all flex items-center justify-center gap-2"
className="w-full bg-white border-2 border-theme-primary text-theme-primary py-3 rounded-2xl text-lg font-black hover:bg-theme-hover shadow-[0_4px_0_var(--theme-primary)] active:shadow-none active:translate-y-[4px] transition-all flex items-center justify-center gap-2"
>
<PenTool size={20} /> Create Manually
</button>
@ -97,14 +97,14 @@ export const Landing: React.FC<LandingProps> = ({ onGenerate, onCreateManual, on
placeholder="Game PIN"
value={pin}
onChange={(e) => setPin(e.target.value)}
className="w-full p-4 text-xl font-bold border-2 border-gray-200 rounded-2xl focus:border-[#46178f] focus:ring-4 focus:ring-[#46178f]/20 outline-none text-center"
className="w-full p-4 text-xl font-bold border-2 border-gray-200 rounded-2xl focus:border-theme-primary focus:ring-4 focus:ring-theme-primary/20 outline-none text-center"
/>
<input
type="text"
placeholder="Nickname"
value={name}
onChange={(e) => setName(e.target.value)}
className="w-full p-4 text-xl font-bold border-2 border-gray-200 rounded-2xl focus:border-[#46178f] focus:ring-4 focus:ring-[#46178f]/20 outline-none text-center"
className="w-full p-4 text-xl font-bold border-2 border-gray-200 rounded-2xl focus:border-theme-primary focus:ring-4 focus:ring-theme-primary/20 outline-none text-center"
/>
<button
type="submit"

View file

@ -20,7 +20,7 @@ export const Lobby: React.FC<LobbyProps> = ({ quizTitle, players, gamePin, role,
<header className="flex flex-col md:flex-row justify-between items-center bg-white/10 p-6 rounded-[2rem] backdrop-blur-md mb-8 gap-6 border-4 border-white/20 shadow-xl">
<div className="flex flex-col items-center md:items-start">
<span className="text-white/80 font-bold uppercase tracking-widest text-sm mb-1">Game PIN</span>
<div className="text-5xl md:text-6xl font-black bg-white text-[#46178f] px-8 py-2 rounded-full shadow-[0_6px_0_rgba(0,0,0,0.2)] tracking-wider">
<div className="text-5xl md:text-6xl font-black bg-white text-theme-primary px-8 py-2 rounded-full shadow-[0_6px_0_rgba(0,0,0,0.2)] tracking-wider">
{gamePin}
</div>
</div>
@ -77,7 +77,7 @@ export const Lobby: React.FC<LobbyProps> = ({ quizTitle, players, gamePin, role,
<button
onClick={onStart}
disabled={realPlayers.length === 0}
className="bg-white text-[#46178f] px-16 py-5 rounded-full text-3xl font-black hover:scale-105 active:scale-95 transition-all shadow-[0_8px_0_rgba(0,0,0,0.2)] disabled:opacity-50 disabled:cursor-not-allowed disabled:shadow-none disabled:translate-y-2"
className="bg-white text-theme-primary px-16 py-5 rounded-full text-3xl font-black hover:scale-105 active:scale-95 transition-all shadow-[0_8px_0_rgba(0,0,0,0.2)] disabled:opacity-50 disabled:cursor-not-allowed disabled:shadow-none disabled:translate-y-2"
>
Start Game
</button>
@ -89,7 +89,7 @@ export const Lobby: React.FC<LobbyProps> = ({ quizTitle, players, gamePin, role,
initial={{ scale: 0.5 }}
animate={{ scale: 1 }}
transition={{ type: 'spring', bounce: 0.6 }}
className="bg-white text-[#46178f] p-8 rounded-[2rem] shadow-[0_10px_0_rgba(0,0,0,0.1)] mb-8"
className="bg-white text-theme-primary p-8 rounded-[2rem] shadow-[0_10px_0_rgba(0,0,0,0.1)] mb-8"
>
<User size={80} strokeWidth={2.5} />
</motion.div>

View file

@ -88,7 +88,7 @@ export const Podium: React.FC<PodiumProps> = ({ players, onRestart }) => {
<button
onClick={onRestart}
className="flex items-center gap-3 bg-white text-[#46178f] px-10 py-4 rounded-2xl text-2xl font-black hover:scale-105 transition shadow-[0_8px_0_rgba(0,0,0,0.2)] active:shadow-none active:translate-y-[8px]"
className="flex items-center gap-3 bg-white text-theme-primary px-10 py-4 rounded-2xl text-2xl font-black hover:scale-105 transition shadow-[0_8px_0_rgba(0,0,0,0.2)] active:shadow-none active:translate-y-[8px]"
>
<RotateCcw size={28} /> Play Again
</button>

View file

@ -59,7 +59,7 @@ export const QuizCreator: React.FC<QuizCreatorProps> = ({ onFinalize, onCancel }
return (
<div className="min-h-screen bg-gray-100 text-gray-900 p-4 md:p-8 flex flex-col items-center">
<div className="max-w-4xl w-full bg-white rounded-[2rem] shadow-xl overflow-hidden border-4 border-white">
<div className="bg-[#46178f] p-8 text-white flex justify-between items-center relative overflow-hidden">
<div className="bg-theme-primary p-8 text-white flex justify-between items-center relative overflow-hidden">
<div className="relative z-10">
<h2 className="text-4xl font-black font-display">Create Quiz</h2>
<p className="opacity-80 font-bold">Build your masterpiece</p>
@ -83,7 +83,7 @@ export const QuizCreator: React.FC<QuizCreatorProps> = ({ onFinalize, onCancel }
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
className="w-full p-4 border-4 border-gray-200 rounded-2xl text-2xl font-bold focus:border-[#46178f] outline-none transition-colors"
className="w-full p-4 border-4 border-gray-200 rounded-2xl text-2xl font-bold focus:border-theme-primary outline-none transition-colors"
placeholder="e.g., The Ultimate Trivia"
/>
</div>
@ -92,7 +92,7 @@ export const QuizCreator: React.FC<QuizCreatorProps> = ({ onFinalize, onCancel }
{questions.map((q, idx) => (
<div key={q.id} className="border-4 border-gray-100 p-4 rounded-2xl bg-gray-50 flex justify-between items-center group hover:border-gray-200 transition">
<div className="flex items-center gap-4">
<span className="bg-[#46178f] text-white w-10 h-10 flex items-center justify-center rounded-full font-black">
<span className="bg-theme-primary text-white w-10 h-10 flex items-center justify-center rounded-full font-black">
{idx + 1}
</span>
<span className="font-bold text-lg">{q.text}</span>

View file

@ -52,7 +52,7 @@ export const Scoreboard: React.FC<ScoreboardProps> = ({ players, onNext, isHost,
dataKey="score"
position="right"
offset={15}
style={{ fontSize: '24px', fontWeight: '900', fill: '#46178f', fontFamily: 'Fredoka' }}
style={{ fontSize: '24px', fontWeight: '900', fill: 'var(--theme-primary)', fontFamily: 'Fredoka' }}
/>
</Bar>
</BarChart>
@ -63,7 +63,7 @@ export const Scoreboard: React.FC<ScoreboardProps> = ({ players, onNext, isHost,
{isHost ? (
<button
onClick={onNext}
className="bg-white text-[#46178f] px-12 py-4 rounded-2xl text-2xl font-black shadow-[0_8px_0_rgba(0,0,0,0.2)] hover:scale-105 active:shadow-none active:translate-y-[8px] transition-all"
className="bg-white text-theme-primary px-12 py-4 rounded-2xl text-2xl font-black shadow-[0_8px_0_rgba(0,0,0,0.2)] hover:scale-105 active:shadow-none active:translate-y-[8px] transition-all"
>
Next
</button>

View file

@ -5,8 +5,8 @@ export const COLORS = {
blue: 'bg-blue-600',
yellow: 'bg-yellow-600',
green: 'bg-green-600',
purple: 'bg-[#46178f]',
purpleLight: 'bg-[#864cbf]',
purple: 'bg-theme-primary',
purpleLight: 'bg-theme-primary/70',
};
export const SHAPES = {
@ -25,9 +25,8 @@ export const QUESTION_TIME = 20; // seconds
export const POINTS_PER_QUESTION = 1000;
export const PLAYER_COLORS = [
'#46178f',
'#2563eb',
'#e21b3c',
'#1368ce',
'#26890c',
'#ffa602',
'#d89e00',
@ -37,4 +36,5 @@ export const PLAYER_COLORS = [
'#ff6b6b',
'#4ecdc4',
'#45b7d1',
'#8b5cf6',
];

View file

@ -5,12 +5,33 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Kaboot</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
theme: {
primary: 'var(--theme-primary)',
'primary-dark': 'var(--theme-primary-dark)',
hover: 'var(--theme-hover-bg)',
}
}
}
}
}
</script>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@300;400;600;700&family=Montserrat:wght@400;700;900&display=swap" rel="stylesheet">
<style>
:root {
--theme-primary: #2563eb;
--theme-primary-dark: #1e40af;
--theme-primary-darker: #1e3a5f;
--theme-hover-bg: #eff6ff;
}
body {
font-family: 'Montserrat', sans-serif;
/* Richer purple gradient */
background: linear-gradient(180deg, #46178f 0%, #25094f 100%);
background: linear-gradient(180deg, var(--theme-primary) 0%, var(--theme-primary-darker) 100%);
color: white;
overflow-x: hidden;
min-height: 100vh;