Calendar analog clock with ticks and numerals; tiles without background

Firmware 0.2.16: the analog clock uses index strokes with 12/3/6/9
numerals on large cards and shows a calendar block (weekday, big day,
short month) beside the dial on single tiles; wide cards keep the digital
time and date. New palette key 'none' hides only the card fill and
border: geometry, padding and the pressed flash stay identical. Skeleton
frames and the render self-test honour the transparency.

App 0.2.15: 'Geen' in the background palette with a dashed mockup tile,
min_firmware 0.2.16 for such layouts, demo layout with the bare calendar
clock (--wide for the double-width clock). README and AGENTS note that
every push is a release and bumps the add-on version.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-13 09:52:33 +02:00
parent 84d9aa8f3e
commit 437b8c55b4
20 changed files with 185 additions and 24 deletions
+4
View File
@@ -18,6 +18,8 @@ ATTRS = frozenset('brightness percentage current_position current_temperature te
TILE_BACKGROUNDS = {
'auto': {'label': 'Standaard', 'color': None},
# No card behind the tile: contents keep their size and place on the screen background.
'none': {'label': 'Geen', 'color': None},
'red': {'label': 'Rood', 'color': '#FADADD'},
'orange': {'label': 'Oranje', 'color': '#FFE1C6'},
'yellow': {'label': 'Geel', 'color': '#FFF0C2'},
@@ -76,6 +78,8 @@ def entity_id(value):
def min_firmware(layout):
"""Oldest firmware that still accepts this layout; None when any version works."""
if any(t.get('options', {}).get('background') == 'none' for t in layout['tiles']):
return (0, 2, 16)
if any(t['entity'].split('.')[0] in NEW_DOMAINS for t in layout['tiles']):
return (0, 2, 14)
if len(layout['tiles']) > 10:
+3 -1
View File
@@ -298,6 +298,8 @@ function renderPreview() {
const name = tile.name || entityName(tile.entity);
const background=inventory.backgrounds?.[tile.options?.background]?.color;
if(background)card.style.backgroundColor=background;
// "Geen": no card on the screen; the mockup keeps a dashed outline as drop target.
if (tile.options?.background === "none") card.classList.add("bare");
if (place.wide) card.classList.add("wide");
card.append(domainBadge(tile.entity), node("strong", name));
card.dataset.index = index;
@@ -437,7 +439,7 @@ function renderTileSheet() {
button.setAttribute("aria-pressed", String((tile.options?.background || "auto") === key));
const sample = node("span", undefined, "palette-sample");
if (choice.color) sample.style.backgroundColor = choice.color;
else sample.classList.add("palette-auto");
else sample.classList.add(key === "none" ? "palette-none" : "palette-auto");
button.append(sample, node("span", choice.label));
button.onclick = () => {
tile.options = { ...tile.options, background: key };
+2
View File
@@ -844,6 +844,8 @@ pre {
.palette-choice:focus-visible { outline: 3px solid #1674ae; outline-offset: 2px; }
.palette-sample { width: 36px; height: 28px; border-radius: 7px; border: 1px solid #0002; }
.palette-auto { background: linear-gradient(135deg, #fff 50%, #e5e7eb 50%); }
.palette-none { background: linear-gradient(135deg, transparent 46%, #8b95a1 46%, #8b95a1 54%, transparent 54%), #e7e7e7; border-style: dashed; }
.preview-tile.bare { background: transparent; border: 1px dashed #c3c9d0; }
.tile-palette small { color: #52616e; }
/* Tile settings sheet and in-preview removal. */