From d567f5459a44718568fd6ff9ab9db5115027c0dd Mon Sep 17 00:00:00 2001 From: Waters Church Date: Thu, 10 Sep 2026 16:31:46 -0400 Subject: [PATCH] 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 --- modules/pco-plan/client.js | 10 ++++++++-- modules/pco-plan/module.json | 22 +++++++++------------ modules/pco-plan/style.css | 37 +++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/modules/pco-plan/client.js b/modules/pco-plan/client.js index 7efd441..8e88a70 100644 --- a/modules/pco-plan/client.js +++ b/modules/pco-plan/client.js @@ -526,8 +526,14 @@ export default function create({ root, moduleApi }) { function render() { wrap.classList.toggle('is-offline', feedOffline); wrap.classList.toggle('tint-types', Boolean(cfg().tintByType)); - const keyColor = String(cfg().keyColor || '').trim(); - wrap.style.setProperty('--pp-key', /^[#a-zA-Z0-9(),.%\s-]+$/.test(keyColor) ? keyColor : '#4ea1ff'); + wrap.classList.toggle('header-gradient', cfg().headerGradient !== false); + 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(); if (!state) { headEl.hidden = true; diff --git a/modules/pco-plan/module.json b/modules/pco-plan/module.json index 56dc60c..38345ce 100644 --- a/modules/pco-plan/module.json +++ b/modules/pco-plan/module.json @@ -64,6 +64,10 @@ "Top bar": { "collapsed": false }, + "Colors": { + "collapsed": false, + "columns": 2 + }, "Show / hide": { "collapsed": true, "columns": 3, @@ -85,19 +89,11 @@ "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." }, - "tintByType": { - "type": "boolean", - "label": "Background color per item type (song / media / other)", - "default": false, - "group": "Top bar" - }, - "keyColor": { - "type": "string", - "label": "Song key color", - "default": "#4ea1ff", - "group": "Top bar", - "help": "Any CSS color, e.g. #4ea1ff or dodgerblue." - }, + "keyColor": { "type": "color", "label": "Song key", "default": "#4ea1ff", "group": "Colors" }, + "headerColor": { "type": "color", "label": "Section headers", "default": "#2ee59a", "group": "Colors" }, + "currentColor": { "type": "color", "label": "Current item", "default": "#2ee59a", "group": "Colors" }, + "headerGradient": { "type": "boolean", "label": "Fade header color to the right", "default": true, "group": "Colors" }, + "tintByType": { "type": "boolean", "label": "Tint items by type (song / media / other)", "default": false, "group": "Colors" }, "showTopBar": { "type": "boolean", "label": "Top bar", "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" }, diff --git a/modules/pco-plan/style.css b/modules/pco-plan/style.css index c73c935..a808d56 100644 --- a/modules/pco-plan/style.css +++ b/modules/pco-plan/style.css @@ -5,6 +5,8 @@ [data-module="pco-plan"] .pp-wrap { --pp-size: 14px; --pp-key: #4ea1ff; + --pp-header: var(--accent); + --pp-current: var(--accent); position: absolute; inset: 0; 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-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 - unmistakable at a glance — accent bar, tinted ground, spaced capitals. */ +/* Section headers: a band that runs edge to edge across the tile (negative + 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 { - margin-top: 0.9em; - padding: 0.5em 0.7em 0.45em; + margin: 0.9em -0.5em 0; + padding: 0.5em 1em 0.45em calc(1em + 3px); align-items: center; - border-left: 3px solid var(--accent); - border-radius: 0.4em; - background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 22%, transparent), color-mix(in srgb, var(--accent) 5%, transparent) 70%, transparent); + border-left: none; + border-radius: 0; + 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 { font-size: 0.85em; 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-current { - border-left-color: var(--accent); - background: color-mix(in srgb, var(--accent) 16%, transparent); + border-left-color: var(--pp-current); + background: color-mix(in srgb, var(--pp-current) 16%, transparent); opacity: 1; } @@ -159,7 +170,7 @@ text-align: right; 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; } @@ -196,7 +207,7 @@ display: none; padding: 0.05em 0.45em; border-radius: 999px; - background: var(--accent); + background: var(--pp-current); color: var(--bg); font-size: 0.65em; font-weight: 800;