pco-plan: edge-to-edge headers, tile colors for headers / current item / key, gradient switch

Section headers lose the bracket look (no accent bar, no rounded corners)
and span the full tile width, with text still aligned to the other rows.
A "Colors" group in the gear menu holds swatch pickers for the song key,
section headers and the current item, a switch for fading the header color
to the right (on by default), and the item-type tint. Colors apply as CSS
custom properties on the tile.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-09-10 16:31:46 -04:00
co-authored by Claude Fable 5.1
parent a71b14d755
commit d567f5459a
3 changed files with 41 additions and 28 deletions
+8 -2
View File
@@ -526,8 +526,14 @@ export default function create({ root, moduleApi }) {
function render() { function render() {
wrap.classList.toggle('is-offline', feedOffline); wrap.classList.toggle('is-offline', feedOffline);
wrap.classList.toggle('tint-types', Boolean(cfg().tintByType)); wrap.classList.toggle('tint-types', Boolean(cfg().tintByType));
const keyColor = String(cfg().keyColor || '').trim(); wrap.classList.toggle('header-gradient', cfg().headerGradient !== false);
wrap.style.setProperty('--pp-key', /^[#a-zA-Z0-9(),.%\s-]+$/.test(keyColor) ? keyColor : '#4ea1ff'); const color = (value, fallback) => {
const s = String(value || '').trim();
return /^[#a-zA-Z0-9(),.%\s-]+$/.test(s) && s ? s : fallback;
};
wrap.style.setProperty('--pp-key', color(cfg().keyColor, '#4ea1ff'));
wrap.style.setProperty('--pp-header', color(cfg().headerColor, '#2ee59a'));
wrap.style.setProperty('--pp-current', color(cfg().currentColor, '#2ee59a'));
renderStatus(); renderStatus();
if (!state) { if (!state) {
headEl.hidden = true; headEl.hidden = true;
+9 -13
View File
@@ -64,6 +64,10 @@
"Top bar": { "Top bar": {
"collapsed": false "collapsed": false
}, },
"Colors": {
"collapsed": false,
"columns": 2
},
"Show / hide": { "Show / hide": {
"collapsed": true, "collapsed": true,
"columns": 3, "columns": 3,
@@ -85,19 +89,11 @@
"group": "Top bar", "group": "Top bar",
"help": "Placeholders: {series} series name · {part} plan title / part number · {serviceType} · {date} · {shortDate} · {time} service start time · {length} planned length · {items} item count. Use • between items (an item whose placeholders are empty or hidden is dropped) and | to start a second line." "help": "Placeholders: {series} series name · {part} plan title / part number · {serviceType} · {date} · {shortDate} · {time} service start time · {length} planned length · {items} item count. Use • between items (an item whose placeholders are empty or hidden is dropped) and | to start a second line."
}, },
"tintByType": { "keyColor": { "type": "color", "label": "Song key", "default": "#4ea1ff", "group": "Colors" },
"type": "boolean", "headerColor": { "type": "color", "label": "Section headers", "default": "#2ee59a", "group": "Colors" },
"label": "Background color per item type (song / media / other)", "currentColor": { "type": "color", "label": "Current item", "default": "#2ee59a", "group": "Colors" },
"default": false, "headerGradient": { "type": "boolean", "label": "Fade header color to the right", "default": true, "group": "Colors" },
"group": "Top bar" "tintByType": { "type": "boolean", "label": "Tint items by type (song / media / other)", "default": false, "group": "Colors" },
},
"keyColor": {
"type": "string",
"label": "Song key color",
"default": "#4ea1ff",
"group": "Top bar",
"help": "Any CSS color, e.g. #4ea1ff or dodgerblue."
},
"showTopBar": { "type": "boolean", "label": "Top bar", "default": true, "group": "Show / hide" }, "showTopBar": { "type": "boolean", "label": "Top bar", "default": true, "group": "Show / hide" },
"showSeries": { "type": "boolean", "label": "Series name", "default": true, "group": "Show / hide" }, "showSeries": { "type": "boolean", "label": "Series name", "default": true, "group": "Show / hide" },
"showPart": { "type": "boolean", "label": "Part # / plan title", "default": true, "group": "Show / hide" }, "showPart": { "type": "boolean", "label": "Part # / plan title", "default": true, "group": "Show / hide" },
+24 -13
View File
@@ -5,6 +5,8 @@
[data-module="pco-plan"] .pp-wrap { [data-module="pco-plan"] .pp-wrap {
--pp-size: 14px; --pp-size: 14px;
--pp-key: #4ea1ff; --pp-key: #4ea1ff;
--pp-header: var(--accent);
--pp-current: var(--accent);
position: absolute; position: absolute;
inset: 0; inset: 0;
display: flex; display: flex;
@@ -103,18 +105,27 @@
[data-module="pco-plan"] .tint-types .pp-row.is-media:hover { background: color-mix(in srgb, var(--warn) 15%, transparent); } [data-module="pco-plan"] .tint-types .pp-row.is-media:hover { background: color-mix(in srgb, var(--warn) 15%, transparent); }
[data-module="pco-plan"] .tint-types .pp-row.is-item:hover { background: color-mix(in srgb, var(--text) 8%, transparent); } [data-module="pco-plan"] .tint-types .pp-row.is-item:hover { background: color-mix(in srgb, var(--text) 8%, transparent); }
/* Section headers: a full-width band so a new part of the service is /* Section headers: a band that runs edge to edge across the tile (negative
unmistakable at a glance — accent bar, tinted ground, spaced capitals. */ margins cancel the list padding) so a new part of the service is
unmistakable — tile-chosen color, solid or fading to the right. The
left padding keeps the text aligned with the other rows' text. */
[data-module="pco-plan"] .pp-row.is-header { [data-module="pco-plan"] .pp-row.is-header {
margin-top: 0.9em; margin: 0.9em -0.5em 0;
padding: 0.5em 0.7em 0.45em; padding: 0.5em 1em 0.45em calc(1em + 3px);
align-items: center; align-items: center;
border-left: 3px solid var(--accent); border-left: none;
border-radius: 0.4em; border-radius: 0;
background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 22%, transparent), color-mix(in srgb, var(--accent) 5%, transparent) 70%, transparent); background: color-mix(in srgb, var(--pp-header) 22%, transparent);
}
[data-module="pco-plan"] .pp-row.is-header:first-child { margin-top: 0; }
[data-module="pco-plan"] .pp-row + .pp-row.is-header { margin-top: 0.9em; }
[data-module="pco-plan"] .pp-row.is-header:hover { background: color-mix(in srgb, var(--pp-header) 28%, transparent); }
[data-module="pco-plan"] .header-gradient .pp-row.is-header {
background: linear-gradient(90deg, color-mix(in srgb, var(--pp-header) 30%, transparent), color-mix(in srgb, var(--pp-header) 6%, transparent) 70%, transparent);
}
[data-module="pco-plan"] .header-gradient .pp-row.is-header:hover {
background: linear-gradient(90deg, color-mix(in srgb, var(--pp-header) 36%, transparent), color-mix(in srgb, var(--pp-header) 8%, transparent) 70%, transparent);
} }
[data-module="pco-plan"] .pp-row.is-header:first-child { margin-top: 0.15em; }
[data-module="pco-plan"] .pp-row.is-header:hover { background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 26%, transparent), color-mix(in srgb, var(--accent) 7%, transparent) 70%, transparent); }
[data-module="pco-plan"] .pp-row.is-header .pp-title { [data-module="pco-plan"] .pp-row.is-header .pp-title {
font-size: 0.85em; font-size: 0.85em;
font-weight: 800; font-weight: 800;
@@ -133,8 +144,8 @@
[data-module="pco-plan"] .pp-row.is-done:hover { opacity: 0.8; } [data-module="pco-plan"] .pp-row.is-done:hover { opacity: 0.8; }
[data-module="pco-plan"] .pp-row.is-current { [data-module="pco-plan"] .pp-row.is-current {
border-left-color: var(--accent); border-left-color: var(--pp-current);
background: color-mix(in srgb, var(--accent) 16%, transparent); background: color-mix(in srgb, var(--pp-current) 16%, transparent);
opacity: 1; opacity: 1;
} }
@@ -159,7 +170,7 @@
text-align: right; text-align: right;
white-space: nowrap; white-space: nowrap;
} }
[data-module="pco-plan"] .pp-row.is-current .pp-col-time { color: var(--accent); font-weight: 700; } [data-module="pco-plan"] .pp-row.is-current .pp-col-time { color: var(--pp-current); font-weight: 700; }
[data-module="pco-plan"] .pp-col-main { flex: 1; min-width: 0; } [data-module="pco-plan"] .pp-col-main { flex: 1; min-width: 0; }
@@ -196,7 +207,7 @@
display: none; display: none;
padding: 0.05em 0.45em; padding: 0.05em 0.45em;
border-radius: 999px; border-radius: 999px;
background: var(--accent); background: var(--pp-current);
color: var(--bg); color: var(--bg);
font-size: 0.65em; font-size: 0.65em;
font-weight: 800; font-weight: 800;