Skip to content

Commit 33ef122

Browse files
authored
Implement theme toggle functionality
Added theme state management and updated styles based on theme.
1 parent c51960c commit 33ef122

1 file changed

Lines changed: 57 additions & 32 deletions

File tree

src/App.jsx

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React, { useState, useMemo, useRef, useCallback, useEffect } from 'react';
22
import {
33
Play, Pause, Microscope,
4-
ArrowRight, Eraser, ChevronRight, Activity, Grid, MousePointer2,
5-
Edit3, Hash, Upload, Image as ImageIcon, Maximize,
6-
Calculator, TrendingUp, Type
4+
ArrowRight, Eraser, Activity, Grid, MousePointer2,
5+
Hash, Upload, Image as ImageIcon, Sun, Moon,
6+
Calculator
77
} from 'lucide-react';
88

99
// --- MATH & LOGIC ENGINE ---
@@ -69,6 +69,9 @@ const ACTIVATIONS = {
6969
export default function DeepLabCNN() {
7070
// --- STATE ---
7171

72+
// Theme State (Default to 'dark')
73+
const [theme, setTheme] = useState('dark');
74+
7275
// Dimensions
7376
const [gridSize, setGridSize] = useState(14);
7477
const [kernelSize, setKernelSize] = useState(3);
@@ -79,7 +82,7 @@ export default function DeepLabCNN() {
7982

8083
// Model Parameters
8184
const [stride, setStride] = useState(1);
82-
const [padding, setPadding] = useState(0);
85+
const [padding, setPadding] = useState(0); // Always 0 (Valid)
8386
const [activation, setActivation] = useState('relu');
8487

8588
// Filter State
@@ -322,16 +325,21 @@ export default function DeepLabCNN() {
322325
// Adjusted pixel size: 20 for interactive (bigger)
323326
const pixelSize = isInteractive ? 20 : 22;
324327

328+
const lightThemeGridBg = 'bg-slate-200';
329+
const darkThemeGridBg = 'bg-black';
330+
const gridBg = theme === 'light' ? lightThemeGridBg : darkThemeGridBg;
331+
const gridBorder = theme === 'light' ? 'border-slate-400' : 'border-slate-700';
332+
325333
return (
326334
<div className="flex flex-col items-center gap-2 relative group/grid">
327335
<div className="relative p-px" style={{
328336
padding: usePadding > 0 ? `${(usePadding/dim)*100}%` : '0',
329-
border: usePadding > 0 ? '1px dashed #475569' : 'none'
337+
border: usePadding > 0 ? '1px dashed var(--color-border)' : 'none'
330338
}}>
331339
{usePadding > 0 && <div className="absolute -top-4 left-0 text-[8px] text-slate-500">Padding: {usePadding}px</div>}
332340

333341
<div
334-
className="relative bg-black border border-slate-700 shadow-lg select-none overflow-hidden"
342+
className={`relative ${gridBg} ${gridBorder} border shadow-lg select-none overflow-hidden`}
335343
style={{
336344
width: dim * pixelSize + 'px',
337345
height: dim * pixelSize + 'px',
@@ -401,21 +409,38 @@ export default function DeepLabCNN() {
401409
};
402410

403411
const mathInfo = getMathDetails();
412+
413+
const themeClasses = {
414+
dark: 'bg-slate-950 text-slate-200 border-slate-800',
415+
light: 'bg-white text-slate-900 border-slate-200',
416+
};
417+
const cardClasses = theme === 'dark' ? 'bg-slate-900 border-slate-800' : 'bg-slate-50 border-slate-200';
418+
const topBarClasses = theme === 'dark' ? 'bg-slate-900' : 'bg-slate-100';
419+
404420

405421
return (
406-
<div className="min-h-screen bg-slate-950 text-slate-200 font-sans selection:bg-blue-500 selection:text-white">
422+
<div className={`min-h-screen font-sans selection:bg-blue-500 selection:text-white ${themeClasses[theme]}`}>
407423

408424
{/* Top Bar */}
409-
<div className="h-20 border-b border-slate-800 flex items-center px-6 bg-slate-900 sticky top-0 z-20 overflow-x-auto">
425+
<div className={`h-20 border-b ${theme === 'dark' ? 'border-slate-800' : 'border-slate-300'} flex items-center px-6 ${topBarClasses} sticky top-0 z-20 overflow-x-auto`}>
410426
<div className="flex items-center gap-3 mr-8 shrink-0">
411427
<div className="bg-blue-600 p-1.5 rounded-lg">
412428
<Microscope className="w-5 h-5 text-white" />
413429
</div>
414-
<h1 className="font-bold text-lg tracking-tight">DeepLab CNN<span className="font-normal text-slate-500">v1.0</span></h1>
430+
<h1 className="font-bold text-lg tracking-tight">DeepLab <span className="font-normal text-slate-500">v1.0</span></h1>
415431
</div>
416432

417433
<div className="flex-1 flex items-center justify-end gap-6 text-sm shrink-0">
418-
434+
435+
{/* Theme Toggle */}
436+
<button
437+
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
438+
className={`flex items-center px-3 py-1.5 rounded-full border text-xs transition-all ${theme === 'dark' ? 'bg-slate-800 border-slate-700 text-yellow-400' : 'bg-slate-200 border-slate-300 text-indigo-600'}`}
439+
title="Toggle Theme"
440+
>
441+
{theme === 'dark' ? <Sun className="w-4 h-4" /> : <Moon className="w-4 h-4" />}
442+
</button>
443+
419444
{/* Values Toggle */}
420445
<button
421446
onClick={() => setShowValues(!showValues)}
@@ -460,13 +485,13 @@ export default function DeepLabCNN() {
460485
</div>
461486

462487
{/* Activation & Graph */}
463-
<div className="flex items-center gap-3 bg-slate-800/50 p-1.5 rounded-lg border border-slate-800">
488+
<div className={`flex items-center gap-3 p-1.5 rounded-lg border ${theme === 'dark' ? 'bg-slate-800/50 border-slate-800' : 'bg-slate-200 border-slate-300'}`}>
464489
<div className="flex flex-col">
465490
<span className="text-[10px] text-slate-500 uppercase font-bold mb-1">Activation</span>
466491
<select
467492
value={activation}
468493
onChange={(e) => setActivation(e.target.value)}
469-
className="bg-slate-900 border border-slate-700 text-xs rounded py-1 px-1 outline-none text-slate-300 w-20"
494+
className={`border ${theme === 'dark' ? 'bg-slate-900 border-slate-700 text-slate-300' : 'bg-white border-slate-300 text-slate-800'} text-xs rounded py-1 px-1 outline-none w-20`}
470495
>
471496
<option value="relu">ReLU</option>
472497
<option value="sigmoid">Sigmoid</option>
@@ -483,12 +508,12 @@ export default function DeepLabCNN() {
483508
<div className="flex flex-col lg:flex-row h-[calc(100vh-80px)]">
484509

485510
{/* LEFT COLUMN: INPUT & MATH */}
486-
<div className="w-full lg:w-1/3 border-r border-slate-800 flex flex-col bg-slate-900 overflow-y-auto">
511+
<div className={`w-full lg:w-1/3 border-r ${theme === 'dark' ? 'border-slate-800 bg-slate-900' : 'border-slate-300 bg-slate-100'} flex flex-col overflow-y-auto`}>
487512

488513
{/* Drawing Area */}
489-
<div className="p-6 border-b border-slate-800">
514+
<div className={`p-6 border-b ${theme === 'dark' ? 'border-slate-800' : 'border-slate-300'}`}>
490515
<div className="flex justify-between items-center mb-4">
491-
<h2 className="text-slate-100 font-semibold flex items-center gap-2">
516+
<h2 className={`font-semibold flex items-center gap-2 ${theme === 'dark' ? 'text-slate-100' : 'text-slate-800'}`}>
492517
<ImageIcon className="w-4 h-4 text-blue-500" /> Input Layer
493518
</h2>
494519
<div className="flex gap-2 items-center">
@@ -520,11 +545,11 @@ export default function DeepLabCNN() {
520545
highlightRegion={getInputHighlight()}
521546
isInteractive={true}
522547
showNums={showValues}
523-
usePadding={padding === 1 ? Math.floor(kernelSize/2)*20 : 0} // Visual Padding Size
548+
usePadding={0}
524549
/>
525550
<div className="absolute inset-0 flex items-center justify-center pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity duration-500">
526551
{!inputGrid.some(x=>x>0) && !isDrawing && (
527-
<div className="flex flex-col items-center text-slate-500 bg-slate-900/90 px-4 py-2 rounded-xl backdrop-blur border border-slate-800">
552+
<div className={`flex flex-col items-center ${theme === 'dark' ? 'text-slate-500 bg-slate-900/90 border-slate-800' : 'text-slate-600 bg-slate-200/90 border-slate-300'} px-4 py-2 rounded-xl backdrop-blur border`}>
528553
<MousePointer2 className="w-5 h-5 mb-1" />
529554
<span className="font-mono text-xs">Draw Here</span>
530555
</div>
@@ -535,37 +560,37 @@ export default function DeepLabCNN() {
535560
</div>
536561

537562
{/* Math Explainer Panel */}
538-
<div className="flex-1 p-6 bg-slate-900/50 overflow-y-auto">
539-
<h2 className="text-slate-100 font-semibold flex items-center gap-2 mb-4">
563+
<div className={`flex-1 p-6 ${theme === 'dark' ? 'bg-slate-900/50' : 'bg-slate-100/50'} overflow-y-auto`}>
564+
<h2 className={`font-semibold flex items-center gap-2 mb-4 ${theme === 'dark' ? 'text-slate-100' : 'text-slate-800'}`}>
540565
<Calculator className="w-4 h-4 text-amber-500" /> Convolution Math
541566
</h2>
542567

543568
{mathInfo ? (
544569
<div className="space-y-4 animate-in fade-in duration-300">
545-
<div className="text-xs text-slate-400 bg-slate-800 p-2 rounded border border-slate-700">
570+
<div className={`text-xs p-2 rounded border ${theme === 'dark' ? 'text-slate-400 bg-slate-800 border-slate-700' : 'text-slate-600 bg-slate-200 border-slate-300'}`}>
546571
Analyzing: <span className="text-amber-400 font-bold">{mathInfo.filterName}</span> at ({hoveredPixel.x}, {hoveredPixel.y})
547572
</div>
548573

549574
<div className="space-y-1">
550575
{mathInfo.calculations.slice(0, 9).map((calc, i) => (
551576
<div key={i} className="flex items-center text-xs font-mono">
552577
<span className="text-slate-500 w-4">({i})</span>
553-
<span className={`w-12 text-right ${calc.isPadding ? 'text-slate-600 italic' : 'text-blue-400'}`}>
578+
<span className={`w-12 text-right ${calc.isPadding ? 'text-slate-600 italic' : (theme === 'dark' ? 'text-blue-400' : 'text-blue-700')}`}>
554579
{calc.isPadding ? '0 (pad)' : calc.val.toFixed(2)}
555580
</span>
556581
<span className="px-2 text-slate-600">×</span>
557-
<span className="w-8 text-right text-emerald-400">{calc.weight}</span>
582+
<span className={`w-8 text-right ${theme === 'dark' ? 'text-emerald-400' : 'text-emerald-700'}`}>{calc.weight}</span>
558583
<span className="px-2 text-slate-600">=</span>
559-
<span className="text-white">{calc.product.toFixed(2)}</span>
584+
<span className={`${theme === 'dark' ? 'text-white' : 'text-slate-900'}`}>{calc.product.toFixed(2)}</span>
560585
</div>
561586
))}
562587
{mathInfo.calculations.length > 9 && <div className="text-xs text-slate-600 pl-4">...and {mathInfo.calculations.length - 9} more</div>}
563588
</div>
564589

565-
<div className="border-t border-slate-700 pt-2 mt-2">
590+
<div className={`border-t ${theme === 'dark' ? 'border-slate-700' : 'border-slate-300'} pt-2 mt-2`}>
566591
<div className="flex justify-between text-sm">
567592
<span className="text-slate-400">Sum:</span>
568-
<span className="font-mono text-white">{mathInfo.total.toFixed(2)}</span>
593+
<span className={`font-mono ${theme === 'dark' ? 'text-white' : 'text-slate-800'}`}>{mathInfo.total.toFixed(2)}</span>
569594
</div>
570595
<div className="flex justify-between text-sm font-bold text-amber-400 mt-1">
571596
<span>{activation.toUpperCase()}(Sum):</span>
@@ -574,7 +599,7 @@ export default function DeepLabCNN() {
574599
</div>
575600
</div>
576601
) : (
577-
<div className="flex flex-col items-center justify-center h-32 text-slate-500 text-xs text-center border-2 border-dashed border-slate-800 rounded-xl">
602+
<div className={`flex flex-col items-center justify-center h-32 text-xs text-center border-2 border-dashed rounded-xl ${theme === 'dark' ? 'text-slate-500 border-slate-800' : 'text-slate-400 border-slate-400'}`}>
578603
<MousePointer2 className="w-6 h-6 mb-2 opacity-20" />
579604
Hover over a feature map pixel<br/>to see the math.
580605
</div>
@@ -584,7 +609,7 @@ export default function DeepLabCNN() {
584609
</div>
585610

586611
{/* RIGHT COLUMN: PIPELINE */}
587-
<div className="flex-1 overflow-y-auto bg-slate-950 p-6">
612+
<div className={`flex-1 overflow-y-auto ${theme === 'dark' ? 'bg-slate-950' : 'bg-slate-200'} p-6`}>
588613

589614
{/* STEP 1: CONVOLUTION */}
590615
<section className="mb-10">
@@ -593,7 +618,7 @@ export default function DeepLabCNN() {
593618
<Activity className="w-5 h-5 text-emerald-500" />
594619
</div>
595620
<div>
596-
<h2 className="text-lg font-medium text-slate-200">Convolution Layer</h2>
621+
<h2 className={`text-lg font-medium ${theme === 'dark' ? 'text-slate-200' : 'text-slate-800'}`}>Convolution Layer</h2>
597622
<p className="text-xs text-slate-500 font-mono">
598623
Kernel: {kernelSize}x{kernelSize} | Stride: {stride} | Pad: {padding}
599624
</p>
@@ -607,15 +632,15 @@ export default function DeepLabCNN() {
607632
<div
608633
key={idx}
609634
onMouseEnter={() => setSelectedFilterIdx(idx)}
610-
className={`bg-slate-900 border rounded-xl p-4 flex flex-col items-center transition-colors group cursor-crosshair ${hoveredPixel?.layer === 'conv' && hoveredPixel.filterIndex === idx ? 'border-blue-500 ring-1 ring-blue-500 bg-blue-900/10' : 'border-slate-800 hover:border-slate-600'}`}
635+
className={`border rounded-xl p-4 flex flex-col items-center transition-colors group cursor-crosshair ${theme === 'dark' ? 'bg-slate-900 border-slate-800 hover:border-slate-600' : 'bg-white border-slate-200 hover:border-slate-400'} ${hoveredPixel?.layer === 'conv' && hoveredPixel.filterIndex === idx ? 'border-blue-500 ring-1 ring-blue-500 bg-blue-900/10' : ''}`}
611636
>
612637
<div className="flex justify-between items-center w-full mb-3">
613638
<h3 className="text-xs font-semibold uppercase tracking-wider text-slate-400">{filter.name}</h3>
614639
{/* Kernel Preview Mini */}
615-
<div className="bg-slate-800 border border-slate-700 p-1 rounded shadow-sm group-hover:border-slate-500 transition-colors" title="Kernel Weights">
616-
<div className={`grid gap-px bg-slate-600 border border-slate-600`} style={{ gridTemplateColumns: `repeat(${filter.kernel.length}, 1fr)` }}>
640+
<div className={`border p-1 rounded shadow-sm transition-colors ${theme === 'dark' ? 'bg-slate-800 border-slate-700 group-hover:border-slate-500' : 'bg-slate-200 border-slate-300 group-hover:border-slate-500'}`} title="Kernel Weights">
641+
<div className={`grid gap-px ${theme === 'dark' ? 'bg-slate-600 border-slate-600' : 'bg-slate-400 border-slate-400'}`} style={{ gridTemplateColumns: `repeat(${filter.kernel.length}, 1fr)` }}>
617642
{filter.kernel.flat().map((k, i) => (
618-
<div key={i} className={`w-2 h-2 ${k > 0 ? 'bg-white' : k < 0 ? 'bg-black' : 'bg-slate-400'}`} />
643+
<div key={i} className={`w-2 h-2 ${k > 0 ? 'bg-white' : k < 0 ? 'bg-black' : (theme === 'dark' ? 'bg-slate-400' : 'bg-slate-600')}`} />
619644
))}
620645
</div>
621646
</div>

0 commit comments

Comments
 (0)