A minimalist, elegant countdown timer built with React, TypeScript, and Tailwind CSS v4. This project demonstrates clean code principles, modern React patterns, and a focus on simplicity following the KISS (Keep It Simple, Stupid) principle.
- Simple Countdown: Enter any number of seconds and watch it count down
- Instant Reset: Start button immediately restarts the timer, even mid-countdown
- Clean UI: Minimalist dark theme with purple accents
- Real-time Updates: Smooth second-by-second countdown
- Zero Dependencies: Only essential React and build tools
- React 19 - Latest React with hooks (useState, useEffect)
- TypeScript - Type-safe component props and state
- Tailwind CSS v4 - Utility-first CSS with zero custom classes
- Vite - Lightning-fast HMR and builds
- Bun - Fast JavaScript runtime and package manager
src/
├── components/ # React components
│ └── CountdownTimer.tsx # Timer display component
├── App.tsx # Main app with input controls
├── main.tsx # React DOM entry point
└── index.css # Tailwind imports
- State Management: Simple useState for form and timer state
- Side Effects: useEffect for interval management
- Component Keys: Force remounting for timer reset
- Controlled Inputs: React-managed form inputs
- Cleanup Functions: Proper interval cleanup
- Node.js 18+ or Bun
- npm, yarn, or bun package manager
- Clone the repository:
git clone https://github.com/yourusername/countdown-timer.git
cd countdown-timer- Install dependencies:
bun install
# or npm install- Start the development server:
bun run dev
# or npm run dev- Open your browser and navigate to
http://localhost:5173
bun run dev # Start development server
bun run build # Build for production
bun run lint # Run ESLint
bun run preview # Preview production buildApp.tsx (55 lines)
- Manages input state
- Handles timer reset logic via key prop
- Renders input controls and timer
CountdownTimer.tsx (42 lines)
- Displays countdown in seconds
- Manages interval with useEffect
- Handles cleanup on unmount
// Key state forces React to recreate the component
const [timerKey, setTimerKey] = useState(0);
// Increment key = new component instance
<CountdownTimer key={timerKey} initialSeconds={60} />useEffect(() => {
const timer = setInterval(() => {
setSecondsLeft(prev => prev > 0 ? prev - 1 : 0);
}, 1000);
return () => clearInterval(timer); // Cleanup
}, [initialSeconds]);- Gradient Background: Purple to gray gradient
- Card Design: Rounded corners with shadow
- Large Display: 8xl font size for visibility
- Hidden Spinners: Clean number input without arrows
- Hover States: Interactive button feedback
This project is excellent for learning:
- React Hooks: Practical useState and useEffect usage
- Component Lifecycle: Understanding mount/unmount/update
- Event Handling: Form inputs and button clicks
- TypeScript Basics: Component props typing
- Tailwind CSS: Utility-first styling approach
- Clean Code: Avoiding premature abstraction
This project is open source and available under the MIT License.
This project values simplicity. Contributions should:
- Not add unnecessary abstraction
- Follow existing patterns
- Keep components under 100 lines
- Include clear comments for learning
Lance Lewandowski
- GitHub: @llewandowski
- Inspired by the need for simple, readable code examples
- Demonstrates that less code often means fewer bugs