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:
co-authored by
Claude Fable 5.1
parent
4c5d7956ab
commit
a71b14d755
@@ -209,6 +209,17 @@ function fieldFor(key, spec, value, passwordSet, moduleId) {
|
||||
field.append(span, select);
|
||||
read = () => select.value;
|
||||
selectEl = select;
|
||||
} 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';
|
||||
const hex = (v, fb) => (/^#[0-9a-fA-F]{6}$/.test(String(v ?? '').trim()) ? String(v).trim().toLowerCase() : fb);
|
||||
input.value = hex(value, hex(spec?.default, '#2ee59a'));
|
||||
field.append(span, input);
|
||||
read = () => input.value;
|
||||
} else {
|
||||
const span = document.createElement('span');
|
||||
span.textContent = label;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -626,6 +626,27 @@ body.fullscreen #grid { padding-bottom: 0; }
|
||||
}
|
||||
.field.check input { width: 15px; height: 15px; accent-color: var(--accent); }
|
||||
|
||||
/* color fields: label on the left, swatch on the right */
|
||||
.field.color-field {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.field.color-field > span { flex: 1; min-width: 0; }
|
||||
.field.color-field input[type="color"] {
|
||||
width: 44px;
|
||||
height: 26px;
|
||||
padding: 2px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
background: var(--bg);
|
||||
cursor: pointer;
|
||||
}
|
||||
.field.color-field input[type="color"]:focus { outline: none; border-color: var(--accent); }
|
||||
.field.color-field .field-help { flex-basis: 100%; }
|
||||
|
||||
/* ── modal dialogs (layout name prompt etc.) ───────────────────────── */
|
||||
|
||||
#modal-backdrop {
|
||||
|
||||
Reference in New Issue
Block a user