Shell: tile settings are switches, and the popover ends where it should

Every boolean (and `switch`) in a tile's gear popover renders as the same
toggle the admin page uses for its module switches — 34×19 track, accent
when on, border track and muted knob when off — with the label on the
left and the switch on the right, so the two surfaces read the same. On
means shown or enabled, off hidden or disabled; the label names the thing.
A real checkbox still sits under the track: Tab reaches it, Space flips it
(with a focus ring), clicking the label text toggles it, and the existing
live-commit wiring reads it unchanged. `switch`-typed instance fields,
which previously fell through to a text input, take the same path.

The popover's bottom was 20 px of nothing: the last field kept its 10 px
margin under the popover's own 10 px padding once the Apply/Cancel row
went. The last child now drops its margin, top and bottom match (11 px
each, border included), and in column layouts the grid gap alone spaces
the rows.

Class names, for the admin page to mirror: `.field.check` (the row),
`.check-label`, `.switch`, `.switch .track`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-09-13 13:03:58 -04:00
co-authored by Claude Fable 5.1
parent c46f98818e
commit 0fd052e49d
2 changed files with 72 additions and 7 deletions
+15 -3
View File
@@ -1176,14 +1176,26 @@ function toggleSettingsPopover(tile, el) {
}
}
const isSwitch = type === 'boolean' || type === 'switch';
const field = document.createElement('label');
field.className = 'field' + (type === 'boolean' ? ' check' : '');
field.className = 'field' + (isSwitch ? ' check' : '');
if (type === 'boolean') {
if (isSwitch) {
// A switch: on is shown/enabled, off is hidden/disabled — the label
// names what it turns on. A real checkbox stays underneath (keyboard,
// label clicks and `change` all keep working); the track is the look.
const text = document.createElement('span');
text.className = 'check-label';
text.textContent = label;
const toggle = document.createElement('span');
toggle.className = 'switch';
const input = document.createElement('input');
input.type = 'checkbox';
input.checked = Boolean(current);
field.append(input, document.createTextNode(label));
const track = document.createElement('span');
track.className = 'track';
toggle.append(input, track);
field.append(text, toggle);
inputs.set(key, () => input.checked);
live(input);
} else if (type === 'select' && Array.isArray(spec.options)) {