Shell: grouped, collapsible, multi-column per-tile settings popover
The gear popover learns the admin form's conventions: an instanceSchema
field's `group` starts a labeled subsection, `help` puts a line of guidance
under a control, and a manifest `instanceGroups[name]` adds
{ collapsed, columns, help } for that group (rendered as <details> with a
grid body; container queries drop to two or one column in narrow tiles).
/api/modules now exposes instanceGroups. Lets a module keep a long
show/hide checklist per tile — where display choices belong — without
the popover turning into a scroll of thirty loose checkboxes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
20dc2deb2b
commit
01eac1bdc4
+50
-1
@@ -934,11 +934,54 @@ function toggleSettingsPopover(tile, el) {
|
||||
pop.className = 'tile-settings';
|
||||
const inputs = new Map();
|
||||
|
||||
// Fields render in schema order; a field's `group` starts a labeled
|
||||
// subsection that consecutive same-group fields share, and the manifest's
|
||||
// optional `instanceGroups[name]` adds { collapsed, columns, help } —
|
||||
// the same conventions as the admin page's config form.
|
||||
const groupMeta = man.instanceGroups && typeof man.instanceGroups === 'object' ? man.instanceGroups : {};
|
||||
let groupName = null;
|
||||
let container = pop;
|
||||
|
||||
for (const [key, spec] of Object.entries(man.instanceSchema)) {
|
||||
const type = spec?.type || 'string';
|
||||
const label = spec?.label || key;
|
||||
const current = key in (tile.settings || {}) ? tile.settings[key] : spec?.default;
|
||||
|
||||
const g = spec?.group || '';
|
||||
if (g !== groupName) {
|
||||
groupName = g;
|
||||
if (g) {
|
||||
const meta = groupMeta[g] && typeof groupMeta[g] === 'object' ? groupMeta[g] : {};
|
||||
const folds = meta.collapsed !== undefined;
|
||||
const group = document.createElement(folds ? 'details' : 'div');
|
||||
group.className = 'field-group';
|
||||
if (folds) group.open = !meta.collapsed;
|
||||
const title = document.createElement(folds ? 'summary' : 'div');
|
||||
title.className = 'field-group-title';
|
||||
title.textContent = g;
|
||||
group.appendChild(title);
|
||||
const body = document.createElement('div');
|
||||
body.className = 'field-group-body';
|
||||
const cols = Math.min(4, Math.trunc(Number(meta.columns)) || 0);
|
||||
if (cols > 1) {
|
||||
body.classList.add('is-columns');
|
||||
body.style.setProperty('--cols', String(cols));
|
||||
}
|
||||
if (meta.help) {
|
||||
const help = document.createElement('div');
|
||||
help.className = 'field-group-help';
|
||||
help.textContent = meta.help;
|
||||
body.appendChild(help);
|
||||
}
|
||||
group.appendChild(body);
|
||||
pop.appendChild(group);
|
||||
pop.classList.add('has-groups');
|
||||
container = body;
|
||||
} else {
|
||||
container = pop;
|
||||
}
|
||||
}
|
||||
|
||||
const field = document.createElement('label');
|
||||
field.className = 'field' + (type === 'boolean' ? ' check' : '');
|
||||
|
||||
@@ -970,7 +1013,13 @@ function toggleSettingsPopover(tile, el) {
|
||||
field.append(span, input);
|
||||
inputs.set(key, () => (type === 'number' ? Number(input.value) : input.value));
|
||||
}
|
||||
pop.appendChild(field);
|
||||
if (spec?.help) {
|
||||
const help = document.createElement('small');
|
||||
help.className = 'field-help';
|
||||
help.textContent = spec.help;
|
||||
field.appendChild(help);
|
||||
}
|
||||
container.appendChild(field);
|
||||
}
|
||||
|
||||
const actions = document.createElement('div');
|
||||
|
||||
Reference in New Issue
Block a user