commit ae77418596bff48ebce410bf344bee19973015af Author: chris Date: Sat Jun 28 21:15:44 2025 -0400 inital commit diff --git a/colors.json b/colors.json new file mode 100644 index 0000000..13ba76a --- /dev/null +++ b/colors.json @@ -0,0 +1,123 @@ +[ + { + "family": "Reds", + "colors": [ + { "name": "Red", "hex": "#bd002b" }, + { "name": "Fire Red", "hex": "#FF4500" }, + { "name": "Cherry", "hex": "#DE3163" }, + { "name": "Tomato", "hex": "#FF6347" }, + { "name": "Maroon", "hex": "#800000" } + ] + }, + { + "family": "Oranges", + "colors": [ + { "name": "Orange", "hex": "#ff7600" }, + { "name": "Tangerine", "hex": "#F28500" }, + { "name": "Pumpkin", "hex": "#FF7518" }, + { "name": "Amber", "hex": "#FFBF00" }, + { "name": "Burnt Orange", "hex": "#CC5500" } + ] + }, + { + "family": "Yellows", + "colors": [ + { "name": "Yellow", "hex": "#f2e44b" }, + { "name": "Gold", "hex": "#FFD700" }, + { "name": "Mustard", "hex": "#FFDB58" }, + { "name": "Dandelion", "hex": "#FED85D" }, + { "name": "Sunflower", "hex": "#FFC512" } + ] + }, + { + "family": "Greens", + "colors": [ + { "name": "Lime", "hex": "#95d051" }, + { "name": "Grass Green", "hex": "#25a038" }, + { "name": "Forest Green", "hex": "#228B22" }, + { "name": "Mint", "hex": "#98FF98" }, + { "name": "Sea Green", "hex": "#2E8B57" } + ] + }, + { + "family": "Blues", + "colors": [ + { "name": "Light Blue", "hex": "#a5c4dd" }, + { "name": "Medium Blue", "hex": "#1b70bc" }, + { "name": "Royal Blue", "hex": "#00FFFF" }, + { "name": "Navy", "hex": "#4169E1" }, + { "name": "Sea Glass", "hex": "#008080" }, + { "name": "Caribbean Blue", "hex": "#56cbd6"} + ] + }, + { + "family": "Purples", + "colors": [ + { "name": "Lavender", "hex": "#bd002b" }, + { "name": "Lilac", "hex": "#dba8d0" }, + { "name": "Violet", "hex": "#8F00FF" }, + { "name": "Magenta", "hex": "#FF00FF" }, + { "name": "Plum", "hex": "#DDA0DD" } + ] + }, + { + "family": "Pinks", + "colors": [ + { "name": "Light Pink", "hex": "#FFC0CB" }, + { "name": "Rose", "hex": "#e47d97" }, + { "name": "Hot Pink", "hex": "#FF69B4" }, + { "name": "Peach", "hex": "#FFE5B4" }, + { "name": "Carnation", "hex": "#FFA6C9" } + ] + }, + { + "family": "Browns", + "colors": [ + { "name": "Chocolate", "hex": "#D2691E" }, + { "name": "Sienna", "hex": "#A0522D" }, + { "name": "Tan", "hex": "#D2B48C" }, + { "name": "Beige", "hex": "#F5F5DC" }, + { "name": "Coffee", "hex": "#6F4E37" } + ] + }, + { + "family": "Neutrals", + "colors": [ + { "name": "White", "hex": "#FFFFFF" }, + { "name": "Black", "hex": "#000000" }, + { "name": "Gray", "hex": "#808080" }, + { "name": "Charcoal", "hex": "#36454F" }, + { "name": "Silver", "hex": "#C0C0C0" } + ] + }, + { + "family": "Pastels", + "colors": [ + { "name": "Pastel Pink", "hex": "#FFD1DC" }, + { "name": "Baby Blue", "hex": "#89CFF0" }, + { "name": "Mint Cream", "hex": "#F5FFFA" }, + { "name": "Lavender Mist", "hex": "#E6E6FA" }, + { "name": "Pale Yellow", "hex": "#FFFFE0" } + ] + }, + { + "family": "Dark Tones", + "colors": [ + { "name": "Midnight Blue", "hex": "#191970" }, + { "name": "Dark Olive", "hex": "#556B2F" }, + { "name": "Deep Purple", "hex": "#301934" }, + { "name": "Dark Red", "hex": "#8B0000" }, + { "name": "Charcoal Gray", "hex": "#36454F" } + ] + }, + { + "family": "Brights", + "colors": [ + { "name": "Neon Green", "hex": "#39FF14" }, + { "name": "Electric Blue", "hex": "#7DF9FF" }, + { "name": "Fluorescent Orange", "hex": "#FFBF00" }, + { "name": "Hot Magenta", "hex": "#FF1DCE" }, + { "name": "Lime Yellow", "hex": "#DFFF00" } + ] + } +] diff --git a/index.html b/index.html new file mode 100644 index 0000000..417e66a --- /dev/null +++ b/index.html @@ -0,0 +1,21 @@ + + + + + + Beach Party Balloons Color Palette Picker + + + + +
+

Your Palette

+
+ +
+
+ + + + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..d20de2f --- /dev/null +++ b/script.js @@ -0,0 +1,182 @@ +let selectedPalette = []; + +fetch('colors.json') + .then(response => response.json()) + .then(data => { + const colorFamiliesContainer = document.getElementById('color-families'); + + data.forEach(family => { + const familyDiv = document.createElement('div'); + familyDiv.classList.add('color-family'); + familyDiv.innerHTML = `

${family.family}

`; + + const swatchContainer = document.createElement('div'); + swatchContainer.classList.add('swatch-container'); + + family.colors.forEach(color => { + const swatchWrapper = document.createElement('div'); + swatchWrapper.classList.add('swatch-wrapper'); + + const swatch = document.createElement('div'); + swatch.classList.add('color-swatch'); + swatch.dataset.color = color.hex; + + const backgroundDiv = document.createElement('div'); + backgroundDiv.classList.add('color-background'); + backgroundDiv.style.backgroundColor = color.hex; + + // Add light border if needed + if (isLightColor(color.hex)) { + backgroundDiv.style.border = '1px solid rgba(0, 0, 0, 0.2)'; + } + + swatch.appendChild(backgroundDiv); + + const shineImg = document.createElement('img'); + shineImg.classList.add('color-shine'); + shineImg.src = "shine.svg"; + shineImg.alt = ""; + swatch.appendChild(shineImg); + + const colorName = document.createElement('span'); + colorName.classList.add('color-name'); + colorName.textContent = color.name; + colorName.title = color.name; // Tooltip on hover + + swatch.addEventListener('click', () => { + const isSelected = selectedPalette.some(c => c.hex === color.hex); + if (isSelected) { + selectedPalette = selectedPalette.filter(c => c.hex !== color.hex); + } else { + selectedPalette.push({ name: color.name, hex: color.hex }); + } + backgroundDiv.classList.add('pop'); +backgroundDiv.addEventListener('animationend', () => { + backgroundDiv.classList.remove('pop'); +}, { once: true }); + + renderSelectedPalette(); + updateSwatchHighlights(); + }); + + swatchWrapper.appendChild(swatch); + swatchWrapper.appendChild(colorName); + swatchContainer.appendChild(swatchWrapper); + }); + + familyDiv.appendChild(swatchContainer); + colorFamiliesContainer.appendChild(familyDiv); + }); + + renderSelectedPalette(); + updateSwatchHighlights(); + }) + .catch(error => console.error('Error loading colors:', error)); + + function renderSelectedPalette() { + const paletteColorsContainer = document.getElementById('palette-colors'); + + // Capture the current height before DOM changes + const previousHeight = paletteColorsContainer.offsetHeight; + + // Clear and repopulate + paletteColorsContainer.innerHTML = ''; + + selectedPalette.forEach(color => { + const swatchWrapper = document.createElement('div'); + swatchWrapper.classList.add('swatch-wrapper'); + + const swatch = document.createElement('div'); + swatch.classList.add('color-swatch'); + swatch.dataset.color = color.hex; + + const backgroundDiv = document.createElement('div'); + backgroundDiv.classList.add('color-background'); + backgroundDiv.style.backgroundColor = color.hex; + + if (isLightColor(color.hex)) { + backgroundDiv.style.border = '1px solid rgba(0, 0, 0, 0.2)'; + } + + backgroundDiv.classList.add('chosen'); + swatch.appendChild(backgroundDiv); + + const shineImg = document.createElement('img'); + shineImg.classList.add('color-shine'); + shineImg.src = "shine.svg"; + shineImg.alt = ""; + swatch.appendChild(shineImg); + + swatch.addEventListener('click', () => { + selectedPalette = selectedPalette.filter(c => c.hex !== color.hex); + renderSelectedPalette(); + updateSwatchHighlights(); + }); + + const colorName = document.createElement('span'); + colorName.classList.add('color-name', 'highlighted-name'); + colorName.textContent = color.name; + + swatchWrapper.appendChild(swatch); + swatchWrapper.appendChild(colorName); + paletteColorsContainer.appendChild(swatchWrapper); + }); + + // Animate to new height + const newHeight = paletteColorsContainer.scrollHeight; + paletteColorsContainer.style.maxHeight = previousHeight + 'px'; + + // Trigger reflow to ensure animation + void paletteColorsContainer.offsetWidth; + + paletteColorsContainer.style.maxHeight = newHeight + 'px'; + } + + +function updateSwatchHighlights() { + const allSwatches = document.querySelectorAll('#color-families .color-swatch'); + + allSwatches.forEach(swatch => { + const color = swatch.dataset.color; + const background = swatch.querySelector('.color-background'); + const nameEl = swatch.parentElement.querySelector('.color-name'); + + const isSelected = selectedPalette.some(c => c.hex === color); + + if (isSelected) { + background.classList.add('chosen'); + nameEl.classList.add('highlighted-name'); + } else { + background.classList.remove('chosen'); + nameEl.classList.remove('highlighted-name'); + } + }); + } + +document.getElementById('clear-palette').addEventListener('click', () => { + selectedPalette = []; + renderSelectedPalette(); + updateSwatchHighlights(); +}); + +window.addEventListener('scroll', () => { + const palette = document.getElementById('selected-palette'); + if (window.scrollY > 0) { + palette.classList.add('stuck'); + } else { + palette.classList.remove('stuck'); + } +}); + +// Helper: determine if a color is visually light +function isLightColor(hex) { + const rgb = hex.replace('#', '').match(/.{1,2}/g).map(x => parseInt(x, 16)); + const brightness = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; + return brightness > 220; // Higher threshold = fewer borders +} + + +const checkmark = document.createElement('div'); +checkmark.classList.add('checkmark-overlay'); +checkmark.innerHTML = '✓'; // or use an SVG/icon +swatch.appendChild(checkmark); \ No newline at end of file diff --git a/shine.svg b/shine.svg new file mode 100644 index 0000000..62218e2 Binary files /dev/null and b/shine.svg differ diff --git a/style.css b/style.css new file mode 100644 index 0000000..bbbc3e5 --- /dev/null +++ b/style.css @@ -0,0 +1,269 @@ +body { + margin: 0; + padding: 10px; + box-sizing: border-box; + /* font-family: sans-serif; */ + font-family: "Autour One", serif; + } + + #selected-palette { + position: sticky; + top: 0; + background: #fff; + z-index: 100; + padding: 10px; + border-bottom: 2px solid #ccc; + transition: box-shadow 0.3s ease; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + + gap: 15px; + } + + /* Strong shadow when stuck */ + #selected-palette.stuck { + box-shadow: 16px 16px 15px rgba(0, 0, 0, 0.25); + border: 1px solid rgb(0, 0, 0); + border-radius: 7px; + } + + + + #palette-colors { + display: flex; + flex-wrap: wrap; + justify-content: center; + overflow: visible; + padding: 10px; + /* transition: padding 0.3s ease; */ + transition: max-height 0.3s ease, padding 0.3s ease; + } + + + #clear-palette { + margin-top: 20px; + padding: 8px 12px; + font-size: 0.9rem; + background: #8ae7db; + border: 1px solid #ccc; + border-radius: 15px; + cursor: pointer; + margin: auto; + + } + + #color-families { + display: flex; + flex-direction: column; + gap: 15px; + + } + .color-family { + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + padding-bottom: 20px; + border-bottom: 1px solid #ccc; + } + .swatch-container { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 10px 20px; /* add horizontal AND vertical gaps */ + } + + .color-family h3 { + text-align: center; + margin: 10px 0 5px; + font-size: 1rem; + font-weight: bold; + } + + + .swatch-wrapper { + display: inline-flex; + flex-direction: column; + align-items: center; + justify-content: space-around; + /* width: 60px; */ + margin: 0 5px; + padding: 5px; + max-width: min-content; + /* overflow-wrap: break-word; */ + + } + + /* .color-swatch { + width: 55px; + height: 65px; + border-radius: 50%; + position: relative; + cursor: pointer; + transition: transform 0.2s ease; + } */ + .color-swatch::before { + content: ''; + position: absolute; + top: 10%; + left: 20%; + width: 60%; + height: 40%; + border-radius: 50% / 30%; + background: linear-gradient( + 135deg, + rgba(255, 255, 255, 0.8), + rgba(255, 255, 255, 0) 70% + ); + pointer-events: none; + filter: blur(4px); + } + + .metallic-element[data-color="#FFD700"] { + background: linear-gradient(to bottom, #B88606, #79550E); + box-shadow: + inset 0 0 0 0 rgba(255, 255, 255, 0.3), + inset 0 0 0 1px rgba(0, 0, 0, 0.3), + inset 0 0 10px rgba(0, 0, 0, 0.2); + } + + /* .color-swatch::after { + content: ''; + position: absolute; + top: 2%; + left: 2%; + width: 96%; + height: 96%; + border-radius: 50%; + border: 1px solid rgba(255, 255, 255, 0.3); + pointer-events: none; + box-shadow: 0 0 8px 2px rgba(255, 255, 255, 0.2); + } + */ + .color-swatch { + width: 55px; + height: 65px; + border-radius: 50%; + position: relative; + cursor: pointer; + background: linear-gradient( + 145deg, + #bbb, /* dark shadow */ + #eee 30%, /* bright highlight */ + #ddd 50%, /* mid-tone */ + #fff 70%, /* brightest highlight */ + #bbb /* dark shadow */ + ); + box-shadow: + inset 2px 2px 6px rgba(255, 255, 255, 0.7), /* inner glossy highlight */ + 0 4px 8px rgba(0, 0, 0, 0.2); /* subtle drop shadow */ + transition: transform 0.3s ease; + } + + + .color-swatch:hover, + .color-swatch:active { + transform: scale(1.1); + box-shadow: 0 0 5px rgba(0,0,0,0.2); + } + + .color-swatch.chosen { + outline: 3px solid #333; + outline-offset: 1px; + } + + .color-background { + width: 100%; + height: 100%; + border-radius: 50%; + border: 2px solid rgba(0, 0, 0, 0.1); /* Light gray border */ + box-shadow: 1 1 1; + } + .color-shine { + position: absolute; + top: 10%; + left: 40%; + width: 20px; + height: 8px; + opacity: 0.5; + z-index: 10; + } + + .color-name { + font-size: 0.8rem; + text-align: center; + margin-top: 5px; + word-break: keep-all; /* Prevent breaking long words */ + /* white-space: nowrap; Keep names on a single line */ + /* overflow: hidden; /*Hide overflow text if necessary */ + text-overflow: ellipsis; /* Add ... when text is too long */ + max-width: 90%; + } + + #palette-colors .color-swatch { + width: 40px; + height: 48px; + } + + + /* .checkmark-overlay { + position: absolute; + top: 4px; + right: 4px; + font-size: 16px; + font-weight: bold; + color: white; + background: rgba(0, 0, 0, 0.6); + border-radius: 50%; + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + z-index: 20; + pointer-events: none; + } */ + + @media (max-width: 600px) { + + .swatch-wrapper { + width: 50px; + } + + .color-name { + font-size: 0.65rem; + } + + #selected-palette h2 { + font-size: 1.1rem; + } + } + + .color-name { + transition: all 0.3s ease; + } + + .color-name.highlighted-name { + text-decoration:underline; + font-weight: bold; + color: #111; + } + + @keyframes pop { + 0% { transform: scale(1); } + 50% { transform: scale(1.2); } + 100% { transform: scale(1); } + } + + .color-background.pop { + animation: pop 0.25s ease; + } + + .color-background.chosen { + /* transform: scale(1.1); */ + box-shadow: 0 0 10px rgba(0, 0, 0, 0.25); + } \ No newline at end of file