Dashboard Studio 2.3.0: light, light group and room cards redesigned
- Light card: the card is the lamp; brightness fills it in the lamp's colour, drag anywhere to dim, large brightness figure, switch and colour row - Light groups: the group fader on top, a fader row per lamp in its colour - Room card: name with what's going on, all-lights switch, large climate figures, open doors in amber, device tiles that glow by brightness - Room: new "Hide these entities" field Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -372,7 +372,6 @@ body.editing .w:hover .w-resize, body.editing .w.selected .w-resize { opacity: 1
|
||||
.gauge { display: flex; flex-direction: column; align-items: center; height: 100%; width: 100%; }
|
||||
.gauge svg { flex: 1; width: 100%; min-height: 0; }
|
||||
|
||||
.light { display: flex; flex-direction: column; height: 100%; gap: 10px; justify-content: space-between; }
|
||||
.tile-row { display: flex; align-items: center; gap: 12px; min-width: 0; }
|
||||
/* Brightness: a wide pill slider like Control Center, filled with the lamp's color. */
|
||||
.slider {
|
||||
@@ -679,29 +678,11 @@ body.kiosk #tabnav { top: 6px; max-height: calc(100vh - 20px); }
|
||||
.pos9 button[aria-pressed="true"] i { width: 14px; height: 10px; border-radius: 3px; background: var(--accent); opacity: 1; }
|
||||
|
||||
/* light card */
|
||||
.light-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
|
||||
.light-badge { cursor: pointer; }
|
||||
.light-toggle { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
||||
.light-switch { flex: none; display: flex; }
|
||||
.lm-switch { display: flex; }
|
||||
.swatches { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; flex: none; }
|
||||
.swatch { width: 26px; height: 26px; border-radius: 50%; background: var(--sw); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12); flex: none; display: grid; place-items: center; font-size: 15px; }
|
||||
.swatches.compact .swatch { width: 22px; height: 22px; }
|
||||
.swatch.more { background: var(--d-fill); }
|
||||
.swatch:hover { transform: scale(1.1); }
|
||||
.light.is-group { justify-content: flex-start; gap: 10px; }
|
||||
.light-members2 { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; margin: 0 -4px; padding: 0 4px; }
|
||||
.lm-row { display: grid; grid-template-columns: 36px minmax(0, 1fr) auto auto; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 12px; background: var(--d-fill); }
|
||||
.lm-dot { width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; font-size: 18px; background: color-mix(in srgb, var(--d-text) 8%, transparent); }
|
||||
.lm-row.on .lm-dot { background: var(--tint, var(--d-lit)); color: #2a1d05; }
|
||||
.lm-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
|
||||
.lm-name { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.lm-state { font-size: 12px; color: var(--d-text-2); }
|
||||
.lm-slider { height: 8px; border-radius: 4px; }
|
||||
.lm-slider::-webkit-slider-thumb { height: 16px; width: 16px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.35); }
|
||||
.lm-slider::-moz-range-thumb { height: 16px; width: 16px; border-radius: 50%; background: #fff; }
|
||||
.lm-pct { font-size: 12px; color: var(--d-text-2); min-width: 32px; text-align: right; }
|
||||
.w.lit-lamp .lm-row { background: rgba(255, 255, 255, 0.45); }
|
||||
.w.lit-lamp .swatch.more { background: rgba(255, 255, 255, 0.55); }
|
||||
/* light popup */
|
||||
.lp-head { display: flex; align-items: center; gap: 12px; }
|
||||
@@ -721,8 +702,6 @@ body.kiosk #tabnav { top: 6px; max-height: calc(100vh - 20px); }
|
||||
.swatch.custom input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
|
||||
|
||||
/* light groups */
|
||||
.light-members { flex: 1; min-height: 0; margin: 0 -6px; }
|
||||
.light:has(.light-members) { justify-content: flex-start; }
|
||||
|
||||
/* energy flow */
|
||||
.energy { display: flex; flex-direction: column; height: 100%; gap: 10px; }
|
||||
@@ -885,27 +864,7 @@ body.kiosk #tabnav { top: 6px; max-height: calc(100vh - 20px); }
|
||||
.nt-empty .i { font-size: 28px; color: var(--ok); }
|
||||
|
||||
/* room */
|
||||
.room { position: relative; display: flex; flex-direction: column; gap: 12px; height: 100%; min-height: 0; }
|
||||
.room.on-image { margin: -16px; padding: 16px; border-radius: inherit; color: #fff; --d-text-2: rgba(255, 255, 255, 0.86); --d-fill: rgba(255, 255, 255, 0.18);
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.15) 45%, rgba(0, 0, 0, 0.6)), var(--room-img) center / cover; } /* taste-skill-ignore: a neutral scrim over the photo */
|
||||
.room-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
|
||||
.room-name { font-size: 17px; }
|
||||
.room-chips { display: flex; flex-wrap: wrap; gap: 6px; }
|
||||
.room-chip { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 0 12px; border-radius: 99px; background: var(--d-fill); font-size: 13px; font-weight: 600; max-width: 100%; }
|
||||
.room-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.room-chip .i { font-size: 16px; flex: none; }
|
||||
.room-chip.on { background: var(--d-text); color: var(--d-tile); }
|
||||
.room-chip.warn { color: var(--warn); background: color-mix(in srgb, var(--warn) 16%, transparent); }
|
||||
.room-devices { flex: 1; min-height: 0; overflow-y: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); align-content: start; gap: 8px; }
|
||||
.room-dev { display: flex; align-items: center; gap: 8px; padding: 8px 10px; min-height: 48px; border-radius: 12px; background: var(--d-fill); min-width: 0; }
|
||||
.room-dev.on { background: var(--d-text); color: var(--d-tile); --d-text-2: color-mix(in srgb, var(--d-tile) 70%, transparent); }
|
||||
.room-dev-ico { font-size: 18px; display: flex; flex: none; }
|
||||
.room-dev-text { display: flex; flex-direction: column; min-width: 0; }
|
||||
.room-dev-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.room-dev-state { font-size: 12px; color: var(--d-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.w.lit-lamp .room-dev.on { background: rgba(255, 255, 255, 0.7); color: var(--lit-text); --d-text-2: var(--lit-text-2); }
|
||||
.w.lit-lamp .room-chip.on { background: rgba(61, 44, 10, 0.85); color: #fff6e6; }
|
||||
@container (max-height: 200px) { .room-devices { display: none; } }
|
||||
|
||||
/* vacuum: compact on small cards, a robot with stats on bigger ones */
|
||||
/* the more room, the more it shows */
|
||||
@@ -1480,7 +1439,6 @@ body.in-haven #btn-new { display: none; }
|
||||
.w-body { padding: var(--c-pad); }
|
||||
.pad { padding: var(--c-pad); }
|
||||
.clock-bg, .clock-dim { margin: calc(-1 * var(--c-pad)); }
|
||||
.room.on-image { margin: calc(-1 * var(--c-pad)); padding: var(--c-pad); }
|
||||
|
||||
/* one title style, one name style, one meta style */
|
||||
.wt { font-size: var(--c-fs-title); font-weight: 600; color: var(--d-text); }
|
||||
@@ -1536,11 +1494,6 @@ body.in-haven #btn-new { display: none; }
|
||||
/* light: brightness as one wide bar, colours in one row */
|
||||
.swatch { width: 24px; height: 24px; }
|
||||
.swatch.more { color: var(--d-text-2); }
|
||||
.lm-dot { background: transparent; width: 28px; height: 28px; font-size: var(--c-ico); color: var(--d-text-2); }
|
||||
.lm-row.on .lm-dot { background: transparent; color: color-mix(in srgb, var(--tint, #e3a12f) 70%, #8a5a00); }
|
||||
.w.lit-lamp .lm-row.on .lm-dot { color: var(--lit-text); }
|
||||
.lm-row { grid-template-columns: 28px minmax(0, 1fr) auto auto; }
|
||||
.lm-slider::-webkit-slider-thumb { box-shadow: none; border: 1px solid rgba(0, 0, 0, .2); }
|
||||
|
||||
/* thermostat */
|
||||
.climate .target { font-size: clamp(32px, min(26cqh, 22cqw), 72px); }
|
||||
@@ -1610,11 +1563,6 @@ body.in-haven #btn-new { display: none; }
|
||||
.pp-where { font-size: var(--c-fs-meta); }
|
||||
|
||||
/* room: a plain mark, chips and devices without a filled icon */
|
||||
.room-name { font-size: var(--c-fs-name); }
|
||||
.room-chip { min-height: 32px; font-size: var(--c-fs-meta); }
|
||||
.room-dev { min-height: var(--c-row); border-radius: var(--c-r); }
|
||||
.room-dev-name { font-size: var(--c-fs-meta); }
|
||||
.room-dev.on { background: color-mix(in srgb, var(--d-text) 88%, transparent); }
|
||||
|
||||
/* vacuum: the state in words, the battery as a bar */
|
||||
|
||||
@@ -1767,7 +1715,6 @@ body.in-haven #btn-new { display: none; }
|
||||
background: var(--slider-fill, var(--d-text)); box-shadow: -2000px 0 0 2000px var(--slider-fill, var(--d-text)); }
|
||||
.slider::-moz-range-thumb { width: 4px; height: 100px; border: 0; border-radius: 0; background: var(--slider-fill, var(--d-text)); }
|
||||
.slider::-moz-range-progress { height: 100%; background: var(--slider-fill, var(--d-text)); }
|
||||
.lm-slider { height: 10px; border-radius: 5px; }
|
||||
/* the night dimmer only exists while it dims */
|
||||
body:not([style*="--night-dim: 0."]):not([style*="--night-dim: 1"]) #night-dim { display: none; }
|
||||
/* a heading keeps its set size, but a phone's title stays phone-sized */
|
||||
@@ -1783,7 +1730,6 @@ body:not([style*="--night-dim: 0."]):not([style*="--night-dim: 1"]) #night-dim {
|
||||
/* each slider knows its track height, and its fill-painting thumb is exactly that tall */
|
||||
.slider { --trk: calc(var(--c-ctl) + 8px); height: var(--trk); }
|
||||
.slider.thin { --trk: 28px; }
|
||||
.lm-slider, .cv-slider { --trk: 10px; }
|
||||
.slider::-webkit-slider-thumb, .lm-slider::-webkit-slider-thumb { height: var(--trk); }
|
||||
.slider::-moz-range-thumb { height: var(--trk); }
|
||||
/* solar: today's hours in the sun's colour, the hours gone faded */
|
||||
@@ -1793,7 +1739,6 @@ body:not([style*="--night-dim: 0."]):not([style*="--night-dim: 1"]) #night-dim {
|
||||
.sf-h:not(.best) i { opacity: .7; }
|
||||
.sf-h.past:not(.best) i { opacity: .3; }
|
||||
/* light: the brightness bar never gives way; the colours stay one row you can swipe */
|
||||
.light .slider { flex: none; }
|
||||
.swatches { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
|
||||
.swatches::-webkit-scrollbar { display: none; }
|
||||
.sf-h:not(.best) i { opacity: 1; }
|
||||
@@ -1972,3 +1917,87 @@ body.guest .guest-hide { display: none; }
|
||||
.sp-play { color: var(--d-text); }
|
||||
@container (max-height: 230px) { .sp-odds, .sp-place, .sp-play { display: none; } }
|
||||
@container (max-height: 170px) { .sp-meta, .sp-head { display: none; } }
|
||||
|
||||
/* light: the card is the lamp. Off it's the theme's card; on, it takes the lamp's colour and the brightness
|
||||
fills it from the left in a deeper shade. Drag anywhere across it to dim. */
|
||||
.lt { display: flex; flex-direction: column; height: 100%; min-height: 0; gap: 8px; }
|
||||
.fader { position: relative; overflow: hidden; isolation: isolate; --fill: color-mix(in srgb, var(--tint, #ffc46b) 72%, #e8962a); }
|
||||
.fader-fill { position: absolute; inset: 0 auto 0 0; width: var(--pct, 0%); background: var(--fill); z-index: -1; transition: width .25s ease; }
|
||||
.fader.on .fader-fill { opacity: 1; }
|
||||
.fader-input { -webkit-appearance: none; appearance: none; position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: ew-resize; z-index: 1; touch-action: pan-y; }
|
||||
button.fader-input { cursor: pointer; }
|
||||
.fader-input:focus-visible { opacity: 1; background: transparent; outline: 2px solid var(--accent); outline-offset: -3px; border-radius: inherit; }
|
||||
.fader > :not(.fader-fill):not(.fader-input) { position: relative; z-index: 2; pointer-events: none; }
|
||||
.fader .wbtn:not(.fader-input), .fader .swatches { pointer-events: auto; }
|
||||
@media (prefers-reduced-motion: reduce) { .fader-fill { transition: none; } }
|
||||
/* the single light fills the whole card */
|
||||
.lt-main { flex: 1; min-height: 0; margin: calc(-1 * var(--c-pad)); padding: var(--c-pad); border-radius: inherit; display: flex; flex-direction: column; justify-content: space-between; gap: 8px; }
|
||||
.lt.group .lt-main { flex: none; min-height: 112px; margin-bottom: 0; border-radius: inherit; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
|
||||
.lt-top { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
||||
.lt-ico { width: 32px; height: 32px; display: grid; place-items: center; font-size: calc(var(--c-ico) + 4px); color: var(--d-text-2); flex: none; border-radius: 50%; }
|
||||
.lt.on .lt-ico { color: var(--lit-text); }
|
||||
.lt-title { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
||||
.lt-title .name { font-size: var(--c-fs-name); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.lt-sub { font-size: var(--c-fs-meta); color: var(--d-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.light-switch { flex: none; display: flex; }
|
||||
.lt-foot { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; min-width: 0; }
|
||||
.lt-big { font-size: clamp(30px, min(26cqh, 16cqw), 64px); font-weight: 400; letter-spacing: -0.03em; line-height: .95; }
|
||||
.lt:not(.on) .lt-big { color: var(--d-text-2); }
|
||||
.lt-foot .swatches { flex: 0 1 auto; min-width: 0; margin-left: auto; justify-content: flex-start; }
|
||||
.lt-foot .swatch { width: 22px; height: 22px; }
|
||||
.w.lit-lamp .swatch.more { color: var(--lit-text); }
|
||||
/* a group: the group's fader on top, then a fader per light, each in its own colour */
|
||||
.lt-rows { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
|
||||
.lf-row { flex: none; display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 10px; min-height: var(--c-row); padding: 0 6px 0 14px; border-radius: var(--c-r); background: var(--d-fill); }
|
||||
.w.lit-lamp .lf-row { background: rgba(255, 255, 255, .45); }
|
||||
.lf-name { font-size: var(--c-fs-body); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.lf-pct { font-size: var(--c-fs-meta); color: var(--d-text-2); }
|
||||
.lf-row.on .lf-pct { color: inherit; }
|
||||
.lf-row .switch { transform: scale(.85); }
|
||||
/* not much room: the colours go (the bulb opens them) */
|
||||
@container (max-height: 150px) { .lt-foot .swatches { display: none; } }
|
||||
@container (max-width: 260px) { .lt-foot .swatches { display: none; } }
|
||||
|
||||
/* room: the name and what's going on, the climate in large figures, then its devices as tiles that light up */
|
||||
.rm { display: flex; flex-direction: column; gap: 12px; height: 100%; min-height: 0; }
|
||||
.rm.on-image { margin: calc(-1 * var(--c-pad)); padding: var(--c-pad); border-radius: inherit; color: #fff; --d-text-2: rgba(255, 255, 255, 0.86); --d-fill: rgba(255, 255, 255, 0.18);
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.15) 45%, rgba(0, 0, 0, 0.6)), var(--room-img) center / cover; } /* taste-skill-ignore: a neutral scrim over the photo */
|
||||
.rm-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
||||
.rm-ico { font-size: calc(var(--c-ico) + 4px); color: var(--d-text-2); display: flex; flex: none; }
|
||||
.rm-title { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
|
||||
.rm-name { font-size: calc(var(--c-fs-name) + 3px); font-weight: 650; letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.rm-said { font-size: var(--c-fs-meta); color: var(--d-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.rm-climate { display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; }
|
||||
.rm-temp { font-size: clamp(30px, 11cqw, 48px); font-weight: 400; letter-spacing: -0.03em; line-height: 1; }
|
||||
.rm-temp small, .rm-hum small { font-size: .45em; color: var(--d-text-2); margin-left: 2px; letter-spacing: 0; }
|
||||
.rm-hum { display: inline-flex; align-items: baseline; gap: 4px; font-size: var(--c-fs-mid); }
|
||||
.rm-hum .i { font-size: 16px; color: var(--d-text-2); align-self: center; }
|
||||
.rm-heat { display: inline-flex; align-items: center; gap: 6px; font-size: var(--c-fs-meta); font-weight: 600; padding: 0 12px; min-height: 30px; border-radius: 99px; background: var(--d-fill); margin-left: auto; align-self: center; }
|
||||
.rm-heat .i { font-size: 15px; }
|
||||
.rm-warn { display: flex; align-items: center; gap: 8px; font-size: var(--c-fs-meta); font-weight: 600; color: var(--warn); }
|
||||
.rm-warn .i { font-size: 16px; flex: none; }
|
||||
.rm-devs { flex: 1; min-height: 0; overflow-y: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); align-content: start; gap: 8px; }
|
||||
.rd { position: relative; overflow: hidden; isolation: isolate; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto; column-gap: 8px; align-items: center;
|
||||
min-height: calc(var(--c-row) + 8px); padding: 8px 12px; border-radius: var(--c-r); background: var(--d-fill); text-align: left; --fill: color-mix(in srgb, var(--tint, #ffc46b) 72%, #e8962a); }
|
||||
.rd-fill { position: absolute; inset: 0 auto 0 0; width: 0; z-index: -1; }
|
||||
.rd.on { background: color-mix(in srgb, var(--d-text) 88%, transparent); color: var(--d-tile); --d-text-2: color-mix(in srgb, var(--d-tile) 70%, transparent); }
|
||||
.rd.light.on { background: color-mix(in srgb, var(--tint, #ffc46b) 32%, var(--d-lit, #ffedc7)); color: var(--lit-text); --d-text-2: var(--lit-text-2); }
|
||||
.rd.light.on .rd-fill { width: var(--pct, 0%); background: var(--fill); }
|
||||
.rd-ico { grid-row: span 2; display: flex; font-size: var(--c-ico); }
|
||||
.rd-name { font-size: var(--c-fs-meta); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.rd-state { font-size: 12px; color: var(--d-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
@container (max-height: 220px) { .rm-devs { display: none; } }
|
||||
@container (max-height: 150px) { .rm-climate { display: none; } }
|
||||
@media (max-width: 640px) { .rm-devs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
||||
/* very narrow light and room cards: the name gets its own line, nothing is cut off */
|
||||
@container (max-width: 200px) {
|
||||
.lt-top { flex-wrap: wrap; row-gap: 6px; }
|
||||
.lt-title { order: 3; flex-basis: 100%; }
|
||||
.lt-ico { width: 28px; height: 28px; }
|
||||
.lf-row { grid-template-columns: minmax(0, 1fr) auto; padding-right: 10px; }
|
||||
.lf-row .light-switch { display: none; }
|
||||
.rm-climate { gap: 6px 12px; }
|
||||
.rm-heat { margin-left: 0; }
|
||||
.rm-head .rm-ico { display: none; }
|
||||
}
|
||||
@container (max-width: 200px) and (max-height: 190px) { .lt-sub { display: none; } .lt-big { font-size: 28px; } .lt-main { gap: 4px; } }
|
||||
|
||||
Reference in New Issue
Block a user