inital commit

This commit is contained in:
chris 2025-06-28 21:15:44 -04:00
commit ae77418596
5 changed files with 595 additions and 0 deletions

123
colors.json Normal file
View File

@ -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" }
]
}
]

21
index.html Normal file
View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Beach Party Balloons Color Palette Picker</title>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Autour+One&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body> <div id="selected-palette">
<h2>Your Palette</h2>
<div id="palette-colors"></div>
<button id="clear-palette">Clear Palette</button>
</div>
<div id="color-families"></div>
<script src="script.js"></script>
</body>
</html>

182
script.js Normal file
View File

@ -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 = `<h3>${family.family}</h3>`;
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);

BIN
shine.svg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

269
style.css Normal file
View File

@ -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);
}