Timers: the gear chooses what a card shows, not which timers; a 24-hour switch; a date that fits
Which timers appear is the header's Timers ▾ menu's job, so the gear's source switches (ProPresenter / LTC / module timers, the Clock on/off) are gone. In their place the Show group offers the card's elements — Names, Status lines, Detail lines, Seconds, Leading zeros, Source headings; without seconds a countdown reads in whole minutes, rounded up. The clock's format select is a 24-hour switch (an older layout's "12h" choice is honoured); the clock card has no CLOCK label; Short day and Short month appear once Date is on, and the date fits its card — one line when it can, else a break after the day and a size that fits the longer half. Solo tiles get the same element switches. Shell: the settings window's grab bar is the accent colour and the gear that opened it wears the same colour while it is open; showWhen works in a tile's gear as it does on the admin page. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
1db6c2c89f
commit
efbcf960dd
+27
-3
@@ -286,7 +286,7 @@ function buildTile(tile) {
|
||||
gear.innerHTML = GEAR_SVG;
|
||||
gear.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
toggleSettingsPopover(tile, el);
|
||||
toggleSettingsPopover(tile, el, gear);
|
||||
});
|
||||
head.appendChild(gear);
|
||||
}
|
||||
@@ -1108,6 +1108,7 @@ function tileSchema(tile, man) {
|
||||
function closeSettingsPopovers() {
|
||||
document.querySelectorAll('.tile-settings').forEach((p) => {
|
||||
p._cleanup?.();
|
||||
p._button?.classList.remove('is-open');
|
||||
p.remove();
|
||||
});
|
||||
}
|
||||
@@ -1143,7 +1144,8 @@ function clampPopover(pop) {
|
||||
pop.style.top = Math.min(Math.max(pad, pop.offsetTop), maxTop) + 'px';
|
||||
}
|
||||
|
||||
function toggleSettingsPopover(tile, el) {
|
||||
/** Open (or close) the settings window for `tile`, beside its element `el`; `button` is the gear that asked. */
|
||||
function toggleSettingsPopover(tile, el, button = null) {
|
||||
const existing = document.querySelector(`.tile-settings[data-tile-id="${tile.id}"]`);
|
||||
closeSettingsPopovers();
|
||||
if (existing) return;
|
||||
@@ -1156,6 +1158,11 @@ function toggleSettingsPopover(tile, el) {
|
||||
pop.dataset.tileId = tile.id;
|
||||
pop.setAttribute('role', 'dialog');
|
||||
pop.setAttribute('aria-label', `${tile.title || man.name} settings`);
|
||||
// The gear that opened it wears the window's colour while it is open.
|
||||
if (button) {
|
||||
button.classList.add('is-open');
|
||||
pop._button = button;
|
||||
}
|
||||
|
||||
// A slim bar to move it by — nothing else. No title (the window sits beside
|
||||
// the tile it belongs to) and no close button: a click anywhere else, or
|
||||
@@ -1168,6 +1175,7 @@ function toggleSettingsPopover(tile, el) {
|
||||
pop.append(bar, body);
|
||||
|
||||
const inputs = new Map();
|
||||
const shownWhen = []; // fields that appear only while another has a given value
|
||||
|
||||
/* Display choices apply as they change and save with the layout — nothing
|
||||
to confirm, so no Apply. Typing is debounced because applying means
|
||||
@@ -1446,6 +1454,8 @@ function toggleSettingsPopover(tile, el) {
|
||||
field.appendChild(help);
|
||||
}
|
||||
|
||||
if (typeof spec?.showWhen === 'string' && spec.showWhen) shownWhen.push({ field, key: spec.showWhen });
|
||||
|
||||
if (current && switchInput && key === current.toggleKey) {
|
||||
// The group's on/off lives in its title row, never in the body, and a
|
||||
// click on it must not fold a <details>.
|
||||
@@ -1461,7 +1471,21 @@ function toggleSettingsPopover(tile, el) {
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing to press: click away, press Escape, the ✕, or the gear again.
|
||||
// "Short day" appears once "Date" is on: a field with showWhen:"K" follows
|
||||
// K's switch, live — the same rule the admin page applies.
|
||||
if (shownWhen.length) {
|
||||
const refresh = () => {
|
||||
for (const rule of shownWhen) {
|
||||
const read = inputs.get(rule.key);
|
||||
rule.field.hidden = read ? !read() : false;
|
||||
}
|
||||
};
|
||||
refresh();
|
||||
body.addEventListener('change', refresh);
|
||||
body.addEventListener('input', refresh);
|
||||
}
|
||||
|
||||
// Nothing to press: click away, press Escape, or the gear again.
|
||||
// (The gear's own click stops propagating, so it toggles rather than
|
||||
// closing and reopening.)
|
||||
const closeOnClick = (e) => { if (!pop.contains(e.target)) closeSettingsPopovers(); };
|
||||
|
||||
+9
-6
@@ -306,6 +306,8 @@ body.menu-hidden #topbar {
|
||||
.tile-btn:hover { background: var(--border); color: var(--text); }
|
||||
.tile-btn.close:hover { color: var(--danger); }
|
||||
.tile-btn.active { color: var(--accent); }
|
||||
.tile-btn.is-open,
|
||||
.tile-btn.is-open:hover { background: var(--accent); color: var(--accent-text); }
|
||||
.tile-btn svg { width: 13px; height: 13px; display: block; }
|
||||
|
||||
/* controls a module adds to its own title bar (moduleApi.header) */
|
||||
@@ -554,15 +556,15 @@ body.fullscreen #grid { padding-bottom: 0; }
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
/* the grab bar: a slim strip with a grip mark, nothing to read or press */
|
||||
/* the grab bar: a slim accent strip with a grip mark, nothing to read or
|
||||
press — the gear that opened the window wears the same colour meanwhile */
|
||||
.tile-settings-bar {
|
||||
flex: none;
|
||||
height: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--accent);
|
||||
cursor: grab;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
@@ -573,11 +575,12 @@ body.fullscreen #grid { padding-bottom: 0; }
|
||||
width: 34px;
|
||||
height: 4px;
|
||||
border-radius: 2px;
|
||||
background: var(--muted);
|
||||
opacity: 0.55;
|
||||
background: var(--accent-text);
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.12s;
|
||||
}
|
||||
.tile-settings-bar:hover::before { opacity: 0.9; }
|
||||
.tile-settings-bar:hover::before { opacity: 1; }
|
||||
.tile-settings .field[hidden] { display: none; }
|
||||
.tile-settings-bar:active { cursor: grabbing; }
|
||||
.tile-settings-body {
|
||||
flex: 1;
|
||||
|
||||
Reference in New Issue
Block a user