Dashboard Studio 1.6.0: app icon, clock weather, icon-only tab rail

- App store icon (icon.png) and favicon, drawn by tools/make_icon.py
- Clock can show a weather entity with today's high and low from
  weather.get_forecasts
- Side menu gets an icon-only rail style (now the default): full height,
  centered icons, active marker, names as hover/focus tooltips; phones
  keep a labelled bottom tab bar

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 22:31:00 +01:00
parent 9e7e7beaa0
commit 4187c8f38d
12 changed files with 177 additions and 15 deletions
+42 -7
View File
@@ -352,6 +352,14 @@ body.editing .w:hover .w-resize, body.editing .w.selected .w-resize { opacity: 1
.clock { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100%; text-align: center; }
.clock .time { font-size: clamp(30px, min(38cqh, 22cqw), 96px); font-weight: 700; letter-spacing: -0.03em; line-height: 1; }
.clock .date { color: var(--d-text-2); margin-top: 6px; font-size: 15px; }
.clock-time { display: flex; flex-direction: column; align-items: center; }
.clock-wx { display: inline-flex; align-items: center; flex-wrap: wrap; justify-content: center; gap: 4px 8px; margin-top: 12px; padding: 6px 12px; border-radius: 99px; background: var(--d-fill); max-width: 100%; }
.clock-wx-ico { font-size: 20px; display: flex; color: var(--d-text-2); }
.clock-wx-temp { font-size: 17px; font-weight: 700; }
.clock-wx-text { font-size: 14px; color: var(--d-text-2); }
.clock-hl { font-size: 14px; color: var(--d-text-2); }
.clock-hl:empty { display: none; }
@container (max-height: 150px) { .clock-wx-text, .clock-hl { display: none; } .clock-wx { margin-top: 6px; } }
.cam-btn { position: absolute; inset: 0; }
.cam { width: 100%; height: 100%; object-fit: cover; display: block; background: #000; }
@@ -405,6 +413,30 @@ body.editing .w:hover .w-resize, body.editing .w.selected .w-resize { opacity: 1
.tabnav-item.add { color: var(--d-text-2); margin-top: 4px; }
.tabnav-item.add .i { font-size: 20px; }
body.kiosk #tabnav { top: 6px; max-height: calc(100vh - 20px); }
/* Icon-only rail: full height on the left edge, names as tooltips. */
@media (min-width: 641px) {
#tabnav.icons {
top: 72px; width: 76px; height: calc(100vh - 72px); max-height: none; margin: 0; padding: 12px 10px;
justify-content: center; align-items: center; gap: 10px; overflow: visible;
border: 0; border-right: 1px solid var(--d-separator); border-radius: 0;
background: color-mix(in srgb, var(--d-tile) 72%, transparent);
}
body.kiosk #tabnav.icons { top: 6px; height: calc(100vh - 6px); }
#tabnav.icons .tabnav-item { position: relative; width: 56px; height: 56px; min-height: 0; padding: 0; justify-content: center; border-radius: 16px; transition: background-color .2s, transform .1s; }
#tabnav.icons .tabnav-item:active { transform: scale(0.94); }
#tabnav.icons .tabnav-ico { font-size: 25px; }
#tabnav.icons .tabnav-item[aria-current="page"]::before { content: ""; position: absolute; left: -10px; top: 16px; bottom: 16px; width: 4px; border-radius: 0 3px 3px 0; background: var(--d-accent); }
#tabnav.icons .tabnav-item.add { margin-top: 6px; border: 1.5px dashed var(--d-separator); }
#tabnav.icons .tabnav-label {
position: absolute; left: calc(100% + 14px); top: 50%; z-index: 40;
transform: translate(-4px, -50%); opacity: 0; pointer-events: none;
padding: 6px 10px; border-radius: 9px; background: var(--surface); color: var(--text);
font-size: 13px; font-weight: 600; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25); transition: opacity .15s, transform .15s;
}
#tabnav.icons .tabnav-item:hover .tabnav-label, #tabnav.icons .tabnav-item:focus-visible .tabnav-label { opacity: 1; transform: translate(0, -50%); }
.surface-plain #tabnav.icons { border-right-color: transparent; }
}
.surface-plain #tabnav { background: transparent; border-color: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; }
.i.flip { transform: rotate(180deg); }
.tab-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 4px; }
@@ -531,14 +563,14 @@ body.kiosk.idle, body.kiosk.idle * { cursor: none !important; }
}
/* While editing (and on tablets) the menu becomes a compact rail to leave room for the grid. */
@media (min-width: 641px) {
body.editing #tabnav { width: 84px; padding: 6px; margin-left: 10px; }
body.editing .tabnav-item { flex-direction: column; justify-content: center; gap: 3px; padding: 8px 4px; min-height: 60px; text-align: center; }
body.editing .tabnav-label { font-size: 11px; font-weight: 600; max-width: 100%; }
body.editing #tabnav:not(.icons) { width: 84px; padding: 6px; margin-left: 10px; }
body.editing #tabnav:not(.icons) .tabnav-item { flex-direction: column; justify-content: center; gap: 3px; padding: 8px 4px; min-height: 60px; text-align: center; }
body.editing #tabnav:not(.icons) .tabnav-label { font-size: 11px; font-weight: 600; max-width: 100%; }
}
@media (max-width: 900px) {
#tabnav { width: 84px; padding: 6px; margin-left: 10px; }
.tabnav-item { flex-direction: column; justify-content: center; gap: 3px; padding: 8px 4px; min-height: 60px; text-align: center; }
.tabnav-label { font-size: 11px; font-weight: 600; max-width: 100%; }
#tabnav:not(.icons) { width: 84px; padding: 6px; margin-left: 10px; }
#tabnav:not(.icons) .tabnav-item { flex-direction: column; justify-content: center; gap: 3px; padding: 8px 4px; min-height: 60px; text-align: center; }
#tabnav:not(.icons) .tabnav-label { font-size: 11px; font-weight: 600; max-width: 100%; }
#palette { width: 180px; }
#inspector { width: 260px; }
#palette-list { grid-template-columns: 1fr; }
@@ -550,7 +582,10 @@ body.kiosk.idle, body.kiosk.idle * { cursor: none !important; }
flex-direction: row; max-height: none; overflow-x: auto; padding: 6px; border-radius: 22px;
background: var(--glass); border-color: var(--glass-edge); box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
}
body:not(.editing) #tabnav .tabnav-item { flex: 1; min-width: 64px; }
body:not(.editing) #tabnav .tabnav-item { flex: 1; min-width: 64px; flex-direction: column; justify-content: center; gap: 3px; padding: 8px 4px; min-height: 56px; width: auto; height: auto; }
/* A tab bar keeps its names on phones: there's no hover to reveal them. */
body:not(.editing) #tabnav.icons .tabnav-label { position: static; opacity: 1; transform: none; background: none; box-shadow: none; padding: 0; font-size: 11px; color: inherit; pointer-events: auto; max-width: 100%; }
body:not(.editing) #tabnav.icons .tabnav-item[aria-current="page"]::before { display: none; }
body.has-tabs:not(.editing) #canvas { padding-bottom: 96px; }
body.editing #tabnav { position: static; width: auto; flex-direction: row; overflow-x: auto; max-height: none; margin: 4px 10px; }
body.editing #stage { flex-direction: column; align-items: stretch; }