A professional, feature-rich counter application built with React and Vite. This project demonstrates modern React patterns, clean component architecture, and production-ready code practices.
- Counter Operations: Increment, decrement, and reset
- Value Limits: Minimum (0) and maximum (10) boundaries
- Visual Feedback: Color-coded display and status messages
- Disabled States: Buttons disable at limits for better UX
- LocalStorage Persistence: Counter value persists across page reloads
- Keyboard Navigation:
Arrow Up→ IncrementArrow Down→ DecrementEscape→ Reset
- Responsive Design: Fully responsive across all device sizes
- Accessibility: ARIA labels and keyboard support
- CSS Animations: Smooth transitions and visual feedback
counter-app/
├── src/
│ ├── components/ # React components
│ │ ├── Counter.jsx # Main counter logic
│ │ ├── CounterDisplay.jsx
│ │ ├── CounterControls.jsx
│ │ └── CounterMessage.jsx
│ ├── styles/ # CSS styles
│ │ ├── global.css
│ │ └── Counter.css
│ ├── hooks/ # Custom React hooks
│ ├── utils/ # Utility functions
│ ├── App.jsx # Root component
│ └── main.jsx # Application entry point
├── public/ # Static assets
├── package.json
├── vite.config.js
└── README.md
- Node.js (v16 or higher)
- npm or yarn
- Clone the repository
git clone https://github.com/yourusername/counter-app.git
cd counter-app- Install dependencies
npm install
# or
yarn install- Start the development server
npm run dev
# or
yarn dev- Open your browser
Navigate to
http://localhost:5173
npm run dev- Start development servernpm run build- Build for productionnpm run preview- Preview production buildnpm run lint- Run ESLintnpm run format- Format code with Prettier
- Manages counter state with
useState - Implements LocalStorage persistence with
useEffect - Handles keyboard events
- Contains all business logic
- Displays current count
- Applies dynamic styling based on value
- Pure visual component
- Contains action buttons
- Manages button disabled states
- Handles user interactions
- Shows contextual messages
- Displays limit warnings
- Conditional rendering
// Single source of truth
const [count, setCount] = useState(() => {
// Initialize from LocalStorage
const savedCount = localStorage.getItem('counter-value')
return savedCount ? parseInt(savedCount, 10) : 0
})// Save to LocalStorage on every change
useEffect(() => {
localStorage.setItem('counter-value', count.toString())
}, [count]):root {
--primary-color: #2563eb;
--spacing-md: 1rem;
--border-radius-md: 0.5rem;
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
}- Mobile-first approach
- Flexbox and Grid layouts
- Media queries for tablet/desktop
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}CounterControls.propTypes = {
onIncrement: PropTypes.func.isRequired,
isDecrementDisabled: PropTypes.bool.isRequired,
// ... other prop validations
}- React Hooks rules
- React refresh plugin
- Best practices enforcement
- Clean separation of concerns
- Single responsibility principle
- Reusable components
Edit MIN_VALUE and MAX_VALUE constants in Counter.jsx:
const MIN_VALUE = 0
const MAX_VALUE = 10Update CSS variables in src/styles/global.css:
:root {
--primary-color: #your-color;
--success-color: #your-color;
--danger-color: #your-color;
}- Multiple Counters: See
CounterList.jsxexample - Undo/Redo: Implement with stack-based state
- Themes: Add theme switching with Context API
| Device | Layout | Features |
|---|---|---|
| Mobile | Single column | Touch-friendly buttons |
| Tablet | Compact layout | Optimized spacing |
| Desktop | Full layout | Keyboard shortcuts |
- ARIA Labels: All interactive elements have descriptive labels
- Keyboard Navigation: Full keyboard support
- Focus Management: Visible focus indicators
- Screen Reader: Semantic HTML structure
- Code Splitting: Vite automatically handles this
- Lazy Loading: Ready for future component splitting
- Optimized Build: Production builds are minified and optimized
- Efficient Renders: Memoization-ready component structure
The project is structured to easily add tests:
// Example test structure
describe('Counter', () => {
it('should increment count', () => {
// Test implementation
})
it('should not exceed max value', () => {
// Test implementation
})
})# Install Vercel CLI
npm i -g vercel
# Deploy
vercel# Build project
npm run build
# Deploy build folder
netlify deploy --prod --dir=dist# Install gh-pages
npm install --save-dev gh-pages
# Add to package.json
"homepage": "https://username.github.io/counter-app",
"scripts": {
"predeploy": "npm run build",
"deploy": "gh-pages -d dist"
}
# Deploy
npm run deployThis project demonstrates:
- ✅ State management with
useState - ✅ Side effects with
useEffect - ✅ Component composition
- ✅ Props and PropTypes
- ✅ Event handling
- ✅ Conditional rendering
- ✅ ES6+ features
- ✅ Arrow functions
- ✅ Template literals
- ✅ Destructuring
- ✅ Modules
- ✅ CSS Variables
- ✅ Flexbox/Grid
- ✅ Responsive design
- ✅ Accessibility
- ✅ LocalStorage API
Built with to demonstrate professional React development practices
If you find this project helpful, please give it a ⭐️!

