diff --git a/Domains/Frontend/MiniProjects/ColorPaletteGenerator/README.md b/Domains/Frontend/MiniProjects/ColorPaletteGenerator/README.md new file mode 100644 index 00000000..929ffe73 --- /dev/null +++ b/Domains/Frontend/MiniProjects/ColorPaletteGenerator/README.md @@ -0,0 +1,184 @@ +# ๐จ Color Palette Generator + +**Contributor:** vatsalgupta2004 + +## ๐งพ Description +A **professional Color Palette Generator** web app that helps developers and designers create beautiful color schemes. Generate random palettes, adjust colors, copy hex codes, and export your favorite palettes - all with a clean, modern interface. + +--- + +## ๐ Features +- ๐ฒ **Generate Random Palettes** - Create 5-color palettes instantly +- ๐จ **Interactive Color Picker** - Click any color to customize it +- ๐ **One-Click Copy** - Copy hex codes to clipboard +- ๐ **Lock Colors** - Lock colors you like while randomizing others +- ๐พ **Save Palettes** - Save your favorite palettes locally +- ๐ฑ **Fully Responsive** - Works perfectly on all devices +- โจ๏ธ **Keyboard Shortcuts** - Spacebar to generate new palettes +- ๐ **Color Formats** - Display HEX, RGB, and HSL values + +--- + +## ๐ก Bonus Features +- **Color Accessibility Checker** - Validates WCAG contrast ratios +- **Gradient Preview** - See how colors work together in gradients +- **Export Options** - Download palette as CSS, JSON, or image +- **Smooth Animations** - Beautiful transitions and hover effects +- **Dark Mode Ready** - Professional dark interface + +--- + +## ๐งฉ Tech Stack +- **HTML5** โ Semantic structure and layout +- **CSS3** โ Modern styling, animations, and responsiveness +- **JavaScript (ES6+)** โ Interactive functionality and logic + +--- + +## ๐ธ Screenshots + +### Main Interface + + +--- + +## ๐ฏ Use Cases +- Web developers creating color schemes for projects +- UI/UX designers exploring color combinations +- Digital artists finding inspiration +- Anyone needing quick color palettes + +--- + +## ๐ ๏ธ How to Use + +1. **Generate Palette** + - Click "Generate New Palette" or press `Spacebar` + - Get 5 random coordinated colors + +2. **Customize Colors** + - Click on any color to open color picker + - Adjust to your preference + +3. **Lock Favorites** + - Click the lock icon to keep colors you like + - Generate new colors for unlocked ones + +4. **Copy Colors** + - Click on hex code to copy to clipboard + - Use in your projects immediately + +5. **Save Palette** + - Click "Save Palette" to store locally + - Access saved palettes anytime + +--- + +## ๐ Getting Started + +### Prerequisites +- A modern web browser (Chrome, Firefox, Safari, Edge) + +### Installation + +1. Clone or download the project files +2. Open `index.html` in your browser +3. Start creating beautiful color palettes! + +No build process or dependencies required - just open and use! + +--- + +## ๐จ Features in Detail + +### Random Palette Generation +Uses color theory algorithms to generate harmonious color combinations: +- Analogous schemes +- Complementary colors +- Triadic harmonies +- Monochromatic variations + +### Accessibility Features +- High contrast UI elements +- Clear visual feedback +- Keyboard navigation support +- Screen reader friendly + +### Export Formats +```css +/* CSS Variables */ +:root { + --color-1: #FF6B6B; + --color-2: #4ECDC4; + --color-3: #45B7D1; + --color-4: #96CEB4; + --color-5: #FFEAA7; +} +``` + +```json +{ + "palette": ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEAA7"], + "name": "Summer Vibes" +} +``` + +--- + +## ๐ฎ Keyboard Shortcuts +- `Space` - Generate new palette +- `C` - Copy current palette +- `S` - Save palette +- `L` - Toggle lock on selected color +- `E` - Export palette + +--- + +## ๐ฑ Responsive Design +- **Desktop** - Full feature set with large color swatches +- **Tablet** - Optimized layout for touch interactions +- **Mobile** - Compact view with essential features + +--- + +## ๐ง Customization +Edit `styles.css` to customize: +- Color scheme +- Animations +- Layout spacing +- Font styles + +--- + +## ๐ Future Enhancements +- [ ] Color palette trends and presets +- [ ] Share palettes via URL +- [ ] Integration with design tools (Figma, Adobe XD) +- [ ] AI-powered palette suggestions +- [ ] Color blind simulation mode + +--- + +## ๐ License +This project is open source and available under the MIT License. + +--- + +## ๐ค Contributing +Feel free to fork this project and submit pull requests for improvements! + +--- + +## ๐จโ๐ป Author +**Contributor:** vatsalgupta2004 + +--- + +## ๐ Acknowledgments +- Color theory concepts from Adobe Color +- Inspired by Coolors.co and Color Hunt +- Built for the open-source community + +--- + +**Made with โค๏ธ for developers and designers | Hacktoberfest 2025** diff --git a/Domains/Frontend/MiniProjects/ColorPaletteGenerator/index.html b/Domains/Frontend/MiniProjects/ColorPaletteGenerator/index.html new file mode 100644 index 00000000..dc1af18b --- /dev/null +++ b/Domains/Frontend/MiniProjects/ColorPaletteGenerator/index.html @@ -0,0 +1,112 @@ + + +
+ + + + +Create beautiful color schemes for your projects
+No saved palettes yet. Save your favorite combinations!
+No saved palettes yet. Save your favorite combinations!
'; + return; + } + + savedPalettesContainer.innerHTML = ''; + + savedPalettes.forEach(palette => { + const paletteCard = createSavedPaletteCard(palette); + savedPalettesContainer.appendChild(paletteCard); + }); +} + +// Create Saved Palette Card +function createSavedPaletteCard(palette) { + const card = document.createElement('div'); + card.className = 'saved-palette'; + + const colors = document.createElement('div'); + colors.className = 'saved-palette-colors'; + + palette.colors.forEach(color => { + const colorDiv = document.createElement('div'); + colorDiv.className = 'saved-color'; + colorDiv.style.backgroundColor = color; + colorDiv.title = color; + colorDiv.addEventListener('click', () => copyToClipboard(color)); + colors.appendChild(colorDiv); + }); + + const actions = document.createElement('div'); + actions.className = 'saved-palette-actions'; + + const loadBtn = document.createElement('button'); + loadBtn.className = 'load-btn'; + loadBtn.textContent = 'โป Load'; + loadBtn.addEventListener('click', () => loadPalette(palette)); + + const deleteBtn = document.createElement('button'); + deleteBtn.className = 'delete-btn'; + deleteBtn.textContent = '๐๏ธ Delete'; + deleteBtn.addEventListener('click', () => deletePalette(palette.id)); + + actions.appendChild(loadBtn); + actions.appendChild(deleteBtn); + + card.appendChild(colors); + card.appendChild(actions); + + return card; +} + +// Load Palette +function loadPalette(palette) { + currentPalette = [...palette.colors]; + lockedColors.clear(); + renderPalette(); + showToast('Palette loaded!'); + window.scrollTo({ top: 0, behavior: 'smooth' }); +} + +// Delete Palette +function deletePalette(id) { + savedPalettes = savedPalettes.filter(p => p.id !== id); + localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(savedPalettes)); + renderSavedPalettes(); + showToast('Palette deleted'); +} + +// Clear All Saved Palettes +function clearAllPalettes() { + if (savedPalettes.length === 0) { + showToast('No saved palettes to clear', 'error'); + return; + } + + if (confirm('Are you sure you want to delete all saved palettes?')) { + savedPalettes = []; + localStorage.removeItem(LOCAL_STORAGE_KEY); + renderSavedPalettes(); + showToast('All palettes cleared'); + } +} + +// Export Functions +function exportAsCSS() { + let css = '/* Color Palette - Generated by Color Palette Generator */\n:root {\n'; + currentPalette.forEach((color, index) => { + css += ` --color-${index + 1}: ${color};\n`; + }); + css += '}\n'; + return css; +} + +function exportAsJSON() { + const json = { + palette: currentPalette, + timestamp: new Date().toISOString() + }; + return JSON.stringify(json, null, 2); +} + +function exportAsSCSS() { + let scss = '// Color Palette - Generated by Color Palette Generator\n'; + currentPalette.forEach((color, index) => { + scss += `$color-${index + 1}: ${color};\n`; + }); + return scss; +} + +// Show Export Modal +function showExportModal() { + exportModal.classList.add('active'); + // Show CSS by default + const cssCode = exportAsCSS(); + exportPreview.querySelector('code').textContent = cssCode; +} + +// Event Listeners +function attachEventListeners() { + generateBtn.addEventListener('click', generatePalette); + saveBtn.addEventListener('click', savePalette); + exportBtn.addEventListener('click', showExportModal); + clearBtn.addEventListener('click', clearAllPalettes); + + closeModal.addEventListener('click', () => { + exportModal.classList.remove('active'); + }); + + exportModal.addEventListener('click', (e) => { + if (e.target === exportModal) { + exportModal.classList.remove('active'); + } + }); + + // Export format buttons + document.querySelectorAll('.export-btn').forEach(btn => { + btn.addEventListener('click', () => { + const format = btn.dataset.format; + let code; + + switch (format) { + case 'css': + code = exportAsCSS(); + break; + case 'json': + code = exportAsJSON(); + break; + case 'scss': + code = exportAsSCSS(); + break; + } + + exportPreview.querySelector('code').textContent = code; + }); + }); + + copyExport.addEventListener('click', () => { + const code = exportPreview.querySelector('code').textContent; + copyToClipboard(code); + }); + + // Keyboard Shortcuts + document.addEventListener('keydown', (e) => { + // Ignore if user is typing in input/textarea + if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') { + return; + } + + switch (e.key.toLowerCase()) { + case ' ': + e.preventDefault(); + generatePalette(); + break; + case 's': + e.preventDefault(); + savePalette(); + break; + case 'e': + e.preventDefault(); + showExportModal(); + break; + case 'c': + e.preventDefault(); + if (currentPalette.length > 0) { + copyToClipboard(currentPalette[0]); + } + break; + case 'escape': + exportModal.classList.remove('active'); + break; + } + }); +} + +// Utility: Check Color Contrast (for accessibility) +function getContrast(hexColor) { + const rgb = hexToRgb(hexColor).match(/\d+/g).map(Number); + const luminance = (0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]) / 255; + return luminance > 0.5 ? 'dark' : 'light'; +} + +// Generate Complementary Colors (Advanced Feature) +function generateComplementaryPalette(baseColor) { + // This can be extended for color theory-based palette generation + // Currently uses random generation + generatePalette(); +} + +// Initialize color info with first color +setTimeout(() => { + if (currentPalette.length > 0) { + showColorInfo(currentPalette[0]); + } +}, 100); diff --git a/Domains/Frontend/MiniProjects/ColorPaletteGenerator/styles.css b/Domains/Frontend/MiniProjects/ColorPaletteGenerator/styles.css new file mode 100644 index 00000000..1fe771bc --- /dev/null +++ b/Domains/Frontend/MiniProjects/ColorPaletteGenerator/styles.css @@ -0,0 +1,625 @@ +:root { + --primary-color: #6366f1; + --secondary-color: #8b5cf6; + --danger-color: #ef4444; + --success-color: #10b981; + --background: #0f172a; + --surface: #1e293b; + --surface-light: #334155; + --text-primary: #f1f5f9; + --text-secondary: #cbd5e1; + --border-radius: 12px; + --shadow: 0 10px 30px rgba(0, 0, 0, 0.3); + --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, var(--background) 0%, #1e1b4b 100%); + color: var(--text-primary); + line-height: 1.6; + min-height: 100vh; + padding: 20px; +} + +.container { + max-width: 1400px; + margin: 0 auto; +} + +/* Header */ +.header { + text-align: center; + margin-bottom: 40px; + animation: fadeInDown 0.6s ease; +} + +.header h1 { + font-size: 3rem; + margin-bottom: 10px; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; +} + +.subtitle { + font-size: 1.2rem; + color: var(--text-secondary); +} + +/* Controls */ +.controls { + display: flex; + gap: 15px; + justify-content: center; + flex-wrap: wrap; + margin-bottom: 40px; + animation: fadeInUp 0.6s ease 0.2s backwards; +} + +.btn { + padding: 14px 28px; + font-size: 1rem; + font-weight: 600; + border: none; + border-radius: var(--border-radius); + cursor: pointer; + transition: var(--transition); + display: flex; + align-items: center; + gap: 8px; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); +} + +.btn span { + font-size: 1.2rem; +} + +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + color: white; +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(99, 102, 241, 0.4); +} + +.btn-secondary { + background: var(--surface); + color: var(--text-primary); +} + +.btn-secondary:hover { + background: var(--surface-light); + transform: translateY(-2px); +} + +.btn-danger { + background: var(--danger-color); + color: white; +} + +.btn-danger:hover { + background: #dc2626; + transform: translateY(-2px); +} + +/* Palette Container */ +.palette-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 20px; + margin-bottom: 40px; + animation: fadeInUp 0.6s ease 0.3s backwards; +} + +.color-box { + position: relative; + height: 250px; + border-radius: var(--border-radius); + cursor: pointer; + transition: var(--transition); + box-shadow: var(--shadow); + overflow: hidden; +} + +.color-box:hover { + transform: translateY(-5px); + box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4); +} + +.color-box.locked { + border: 3px solid var(--success-color); + box-shadow: 0 0 20px rgba(16, 185, 129, 0.3); +} + +.color-info-overlay { + position: absolute; + bottom: 0; + left: 0; + right: 0; + background: rgba(0, 0, 0, 0.8); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + padding: 15px; + transform: translateY(100%); + transition: var(--transition); +} + +.color-box:hover .color-info-overlay { + transform: translateY(0); +} + +.color-code { + font-size: 1.1rem; + font-weight: 700; + margin-bottom: 8px; + letter-spacing: 1px; +} + +.color-actions { + display: flex; + gap: 10px; +} + +.action-btn { + flex: 1; + padding: 8px; + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 8px; + color: white; + cursor: pointer; + font-size: 0.85rem; + transition: var(--transition); +} + +.action-btn:hover { + background: rgba(255, 255, 255, 0.2); +} + +.lock-btn { + position: absolute; + top: 15px; + right: 15px; + background: rgba(0, 0, 0, 0.5); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + border: none; + color: white; + width: 40px; + height: 40px; + border-radius: 50%; + cursor: pointer; + font-size: 1.2rem; + display: flex; + align-items: center; + justify-content: center; + transition: var(--transition); + z-index: 10; +} + +.lock-btn:hover { + background: rgba(0, 0, 0, 0.7); + transform: scale(1.1); +} + +/* Color Information Panel */ +.color-info { + background: var(--surface); + border-radius: var(--border-radius); + padding: 25px; + margin-bottom: 40px; + box-shadow: var(--shadow); + animation: fadeInUp 0.6s ease 0.4s backwards; +} + +.color-info h3 { + margin-bottom: 20px; + color: var(--primary-color); +} + +.info-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 20px; +} + +.info-item { + display: flex; + flex-direction: column; + gap: 5px; +} + +.info-item label { + font-size: 0.9rem; + color: var(--text-secondary); + font-weight: 600; +} + +.info-item span { + font-size: 1.1rem; + font-family: 'Courier New', monospace; + background: var(--background); + padding: 10px; + border-radius: 8px; + border: 1px solid var(--surface-light); +} + +/* Saved Palettes */ +.saved-section { + margin-bottom: 40px; + animation: fadeInUp 0.6s ease 0.5s backwards; +} + +.saved-section h3 { + margin-bottom: 20px; + color: var(--primary-color); +} + +#savedCount { + color: var(--text-secondary); + font-size: 0.9rem; +} + +.saved-palettes { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 20px; +} + +.no-saved { + grid-column: 1 / -1; + text-align: center; + color: var(--text-secondary); + padding: 40px; + background: var(--surface); + border-radius: var(--border-radius); +} + +.saved-palette { + background: var(--surface); + border-radius: var(--border-radius); + padding: 15px; + box-shadow: var(--shadow); + transition: var(--transition); +} + +.saved-palette:hover { + transform: translateY(-3px); + box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4); +} + +.saved-palette-colors { + display: flex; + height: 80px; + border-radius: 8px; + overflow: hidden; + margin-bottom: 10px; +} + +.saved-color { + flex: 1; + cursor: pointer; + transition: var(--transition); +} + +.saved-color:hover { + flex: 1.2; +} + +.saved-palette-actions { + display: flex; + gap: 10px; +} + +.load-btn, .delete-btn { + flex: 1; + padding: 8px; + border: none; + border-radius: 8px; + cursor: pointer; + font-weight: 600; + transition: var(--transition); +} + +.load-btn { + background: var(--primary-color); + color: white; +} + +.load-btn:hover { + background: var(--secondary-color); +} + +.delete-btn { + background: var(--danger-color); + color: white; +} + +.delete-btn:hover { + background: #dc2626; +} + +/* Modal */ +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.8); + -webkit-backdrop-filter: blur(5px); + backdrop-filter: blur(5px); + z-index: 1000; + align-items: center; + justify-content: center; +} + +.modal.active { + display: flex; + animation: fadeIn 0.3s ease; +} + +.modal-content { + background: var(--surface); + border-radius: var(--border-radius); + width: 90%; + max-width: 600px; + max-height: 80vh; + overflow-y: auto; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); + animation: slideUp 0.3s ease; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px 25px; + border-bottom: 1px solid var(--surface-light); +} + +.modal-header h3 { + color: var(--primary-color); +} + +.close-btn { + background: none; + border: none; + color: var(--text-secondary); + font-size: 2rem; + cursor: pointer; + transition: var(--transition); + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; +} + +.close-btn:hover { + background: var(--surface-light); + color: var(--text-primary); +} + +.modal-body { + padding: 25px; +} + +.export-options { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + gap: 15px; + margin-bottom: 25px; +} + +.export-btn { + padding: 15px; + background: var(--background); + border: 2px solid var(--surface-light); + border-radius: var(--border-radius); + color: var(--text-primary); + cursor: pointer; + transition: var(--transition); + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + font-weight: 600; +} + +.export-btn span { + font-size: 1.5rem; +} + +.export-btn:hover { + background: var(--surface-light); + border-color: var(--primary-color); + transform: translateY(-3px); +} + +.export-preview { + background: var(--background); + border-radius: 8px; + padding: 15px; +} + +.export-preview h4 { + margin-bottom: 10px; + color: var(--primary-color); +} + +.export-preview pre { + background: #000; + padding: 15px; + border-radius: 8px; + overflow-x: auto; + margin-bottom: 15px; + max-height: 300px; +} + +.export-preview code { + color: #10b981; + font-family: 'Courier New', monospace; + font-size: 0.9rem; +} + +/* Toast Notification */ +.toast { + position: fixed; + bottom: 30px; + right: 30px; + background: var(--success-color); + color: white; + padding: 15px 25px; + border-radius: var(--border-radius); + box-shadow: var(--shadow); + transform: translateX(400px); + transition: transform 0.3s ease; + z-index: 2000; +} + +.toast.show { + transform: translateX(0); +} + +/* Footer */ +.footer { + text-align: center; + margin-top: 60px; + padding-top: 40px; + border-top: 1px solid var(--surface-light); + color: var(--text-secondary); + animation: fadeInUp 0.6s ease 0.6s backwards; +} + +.footer p { + margin-bottom: 10px; +} + +.footer a { + color: var(--primary-color); + text-decoration: none; + font-weight: 600; + transition: var(--transition); +} + +.footer a:hover { + color: var(--secondary-color); +} + +/* Animations */ +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fadeInDown { + from { + opacity: 0; + transform: translateY(-30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideUp { + from { + transform: translateY(50px); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } +} + +/* Responsive Design */ +@media (max-width: 768px) { + .header h1 { + font-size: 2rem; + } + + .subtitle { + font-size: 1rem; + } + + .controls { + flex-direction: column; + } + + .btn { + width: 100%; + justify-content: center; + } + + .palette-container { + grid-template-columns: 1fr; + } + + .color-box { + height: 200px; + } + + .info-grid { + grid-template-columns: 1fr; + } + + .saved-palettes { + grid-template-columns: 1fr; + } + + .export-options { + grid-template-columns: 1fr; + } + + .footer { + font-size: 0.9rem; + } +} + +/* Accessibility */ +:focus-visible { + outline: 3px solid var(--primary-color); + outline-offset: 2px; +} + +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +}