Add eyedropper color picker to brand color modal

Uses the native EyeDropper API (Chrome/Edge) to pick colors from
anywhere on screen. Button only shows in supported browsers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
John Mizerek 2026-03-10 17:29:42 -07:00
parent eda2ce2db4
commit dfe2313ec5

View file

@ -3647,6 +3647,7 @@
<input type="text" id="brandColorHex" value="${currentColor}" <input type="text" id="brandColorHex" value="${currentColor}"
style="width: 100px; padding: 8px; border: 1px solid var(--border); border-radius: 4px; font-family: monospace;" style="width: 100px; padding: 8px; border: 1px solid var(--border); border-radius: 4px; font-family: monospace;"
pattern="^#[0-9A-Fa-f]{6}$" maxlength="7"> pattern="^#[0-9A-Fa-f]{6}$" maxlength="7">
${'EyeDropper' in window ? '<button type="button" id="eyedropperDark" style="width:40px;height:40px;border:1px solid var(--border);border-radius:4px;cursor:pointer;background:var(--bg);display:flex;align-items:center;justify-content:center;font-size:18px;" title="Pick from screen">&#128065;</button>' : ''}
<div id="brandColorPreview" style="flex: 1; height: 40px; border-radius: 4px; background: linear-gradient(to bottom, ${currentColor}44, ${currentColor}00, ${currentColor}66);"></div> <div id="brandColorPreview" style="flex: 1; height: 40px; border-radius: 4px; background: linear-gradient(to bottom, ${currentColor}44, ${currentColor}00, ${currentColor}66);"></div>
</div> </div>
<div style="display: flex; gap: 8px; flex-wrap: wrap;"> <div style="display: flex; gap: 8px; flex-wrap: wrap;">
@ -3671,6 +3672,7 @@
<input type="text" id="brandColorLightHex" value="${currentLight}" <input type="text" id="brandColorLightHex" value="${currentLight}"
style="width: 100px; padding: 8px; border: 1px solid var(--border); border-radius: 4px; font-family: monospace;" style="width: 100px; padding: 8px; border: 1px solid var(--border); border-radius: 4px; font-family: monospace;"
placeholder="#F5F5F5" maxlength="7"> placeholder="#F5F5F5" maxlength="7">
${'EyeDropper' in window ? '<button type="button" id="eyedropperLight" style="width:40px;height:40px;border:1px solid var(--border);border-radius:4px;cursor:pointer;background:var(--bg);display:flex;align-items:center;justify-content:center;font-size:18px;" title="Pick from screen">&#128065;</button>' : ''}
<div id="brandColorLightPreview" style="flex: 1; height: 40px; border-radius: 4px; border: 1px solid var(--border); background: ${currentLight || '#fff'};"></div> <div id="brandColorLightPreview" style="flex: 1; height: 40px; border-radius: 4px; border: 1px solid var(--border); background: ${currentLight || '#fff'};"></div>
<button type="button" class="btn btn-secondary" style="font-size: 12px; padding: 6px 10px;" onclick="document.getElementById('brandColorLightHex').value='';document.getElementById('brandColorLightPreview').style.background='#fff';">Clear</button> <button type="button" class="btn btn-secondary" style="font-size: 12px; padding: 6px 10px;" onclick="document.getElementById('brandColorLightHex').value='';document.getElementById('brandColorLightPreview').style.background='#fff';">Clear</button>
</div> </div>
@ -3733,6 +3735,28 @@
lightPreview.style.background = val; lightPreview.style.background = val;
} }
}); });
// Eyedropper buttons (Chrome/Edge only)
if ('EyeDropper' in window) {
const pickColor = async (colorInput, hexInput, onPick) => {
try {
const dropper = new EyeDropper();
const result = await dropper.open();
const color = result.sRGBHex.toUpperCase();
colorInput.value = color;
hexInput.value = color;
if (onPick) onPick(color);
} catch (e) { /* user cancelled */ }
};
document.getElementById('eyedropperDark')?.addEventListener('click', () => {
pickColor(colorInput, hexInput, updatePreview);
});
document.getElementById('eyedropperLight')?.addEventListener('click', () => {
pickColor(lightInput, lightHex, (c) => { lightPreview.style.background = c; });
});
}
}, },
// Save brand color // Save brand color