Shell: color field type (swatch picker) in tile settings and admin config

Renders <input type="color"> with the label beside it; the stored value is
always a #rrggbb string (3-digit hex widened, anything else falls back to
the schema default). Same styling in the gear popover and the admin form.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-09-10 16:31:46 -04:00
co-authored by Claude Fable 5.1
parent 4c5d7956ab
commit a71b14d755
4 changed files with 53 additions and 1 deletions
+18
View File
@@ -919,6 +919,14 @@ function unmountModule(tile) {
/* ── per-tile settings popover ──────────────────────────────────────── */
/** `<input type="color">` only accepts #rrggbb — anything else falls back. */
function colorHex(value, fallback) {
const s = String(value ?? '').trim();
if (/^#[0-9a-fA-F]{6}$/.test(s)) return s.toLowerCase();
if (/^#[0-9a-fA-F]{3}$/.test(s)) return ('#' + s.slice(1).split('').map((c) => c + c).join('')).toLowerCase();
return fallback;
}
function closeSettingsPopovers() {
document.querySelectorAll('.tile-settings').forEach((p) => p.remove());
}
@@ -1004,6 +1012,16 @@ function toggleSettingsPopover(tile, el) {
select.value = String(current ?? '');
field.append(span, select);
inputs.set(key, () => select.value);
} else if (type === 'color') {
// A swatch picker; the value is always a #rrggbb string.
field.classList.add('color-field');
const span = document.createElement('span');
span.textContent = label;
const input = document.createElement('input');
input.type = 'color';
input.value = colorHex(current, colorHex(spec?.default, '#2ee59a'));
field.append(span, input);
inputs.set(key, () => input.value);
} else {
const span = document.createElement('span');
span.textContent = label;