From 7a44b25d4bed25ffdab4be8bc80f902493b70707 Mon Sep 17 00:00:00 2001 From: Waters Church Date: Mon, 14 Sep 2026 15:20:38 -0400 Subject: [PATCH] Shell: tile settings in a window beside the tile; schemas per tile kind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gear popover lived inside its tile, so a tile could be too small for its own settings, and the settings sat on top of the thing they change. It is now a small window: placed beside the tile (right when there is room, else left, else over it), clamped to the viewport, moved by a grab bar, closed by clicking away, Escape, the ✕ or the gear. Settings still apply as they change — that is the point of putting the window beside the tile. With it, four pieces of contract the module work needs: - A picker entry may carry its own `instanceSchema` / `instanceGroups`: tiles added from it get settings that fit that tile, nothing else. A tile showing one ProPresenter timer has no use for a clock's format switches. - `instanceGroups[name].toggle` puts a group's on/off switch in its title row and dims the body while it is off — the admin page's convention, in the popover. - `select` and `multiselect` in tile settings may take `optionsRoute`; `multiselect` also `columns` and `allByDefault` (nothing saved until someone flips a switch, so options that turn up later are on too). - `template`: a text with placeholders built by dragging or clicking the variables a module offers into it. And the + picker's descriptions are tooltips now — the list stays a list. Co-Authored-By: Claude Fable 5.1 --- docs/MODULE-GUIDE.md | 32 +++- public/shell.js | 338 +++++++++++++++++++++++++++++++++++++------ public/style.css | 107 ++++++++++++-- server.js | 5 + 4 files changed, 419 insertions(+), 63 deletions(-) diff --git a/docs/MODULE-GUIDE.md b/docs/MODULE-GUIDE.md index 5b7dc1c..d12e328 100644 --- a/docs/MODULE-GUIDE.md +++ b/docs/MODULE-GUIDE.md @@ -104,7 +104,7 @@ the app); its settings are kept for a later reinstall. Both schemas map field names to specs: ``` -{ "type": "string" | "text" | "number" | "boolean" | "switch" | "select" | "multiselect" | "color" | "password" | "endpoint", +{ "type": "string" | "text" | "number" | "boolean" | "switch" | "select" | "multiselect" | "template" | "color" | "password" | "endpoint", "label": "Shown next to the field", "default": , "group": "Section heading", // optional; see below @@ -128,7 +128,17 @@ default; the tile applies it as a CSS custom property — see `pco-plan`). `multiselect` is several picks from one list — the same `options` / `optionsRoute` as `select`, rendered as one switch per option and stored as an array of values. A saved value the list no longer offers stays checked and -marked, so nothing is dropped behind the admin's back (admin config only). +marked, so nothing is dropped behind anyone's back. In a tile's gear popover +it also takes `columns` (2–4) and `allByDefault: true`: a tile that has never +chosen shows every option on and saves nothing until someone flips one, so +options that turn up later are on as well (give it no `default` then). +`select` and `multiselect` may use `optionsRoute` in `instanceSchema` too — +the popover GETs `/api/modules/` like the admin page does. + +`template` (tile settings) is a text with placeholders, built by dragging or +clicking the variables the module offers into it: `"variables": [ { "value": +"{series}", "label": "Series" }, … ]`. Keep `help` to the joining rules; the +chips carry the names. `text` is a multi-line string — a `