Rework the dashboard into two looks over one behaviour
A dashboard is a wall panel somebody hangs in their own hallway, so it now wears what they choose: a look, and a palette of their own colours. Two complete component sets live under `Dashboard/ui/` — `glass` (translucent panes over a slowly moving ground) and `material` (Material 3 tonal cards) — behind one prop contract. Every control's state, keyboard and `aria-` live in `ui/core` and are shared, so the two sets are the same dashboard drawn twice rather than two products: a set only decides what a control looks like while doing it. Four settings join the channel, each drivable by a flow like any other: `look`, `palette`, `background` and `touch`. A palette is an ordered list of hex colours — background, surface, primary, accent, text, then more chart colours — pasted from a coolors.co link or typed, written onto the canvas as the token variables everything already reads. Trailing roles are derived, so three colours are a whole dashboard, and derived text is held to AA rather than trusted (`theme.check.ts` measures it). A palette also decides light or dark, since its first colour is the ground. Widgets are measured against their own tile with container queries rather than against the viewport, animate through `motion`, and can be drawn without their title. The three reworks: - a bar draws a row per reading, up to eight, each in the dashboard's own data colours and each able to carry its own scale — replacing readings nested in one fill, which could only ever share one colour and stop at three. Documents written the old way are read as rows. - a chart's range picker moved to a column down its right-hand edge, which gives the plot back a whole row of a short tile. - the colour wheel became a disc: hue is the angle and saturation the distance from the middle, so a colour is one gesture rather than three, with brightness on a slider beside it. `index.css` and `lib/motion.ts` are untouched — the dashboard overrides token *values* on its canvas, never the blocks the two repos share.
This commit is contained in:
+42
-26
@@ -147,10 +147,16 @@ def process(tick, mode="comfort", away=False, setpoint=21.0):
|
||||
"outdoor": round(outdoor, 2),
|
||||
"humidity": round(humidity, 1),
|
||||
# Not a reading: what the panel on the wall should wear. The dashboard
|
||||
# binds its `theme` setting to this, which is what "switch the panel at
|
||||
# sunset" looks like here — a flow publishing, not a rule in the
|
||||
# dashboard.
|
||||
"panel_theme": "dark" if hour < 7.0 or hour >= 20.0 else "light",
|
||||
# binds its `palette` setting to this, which is what "switch the panel
|
||||
# at sunset" looks like here — a flow publishing, not a rule in the
|
||||
# dashboard. Colours in role order: the ground, the surface a widget
|
||||
# is, the primary and the accent. The ground is also what decides
|
||||
# whether the panel reads light or dark, so one message does both.
|
||||
"panel_palette": (
|
||||
["#101b24", "#17252f", "#7ba3b8", "#e5a184"]
|
||||
if hour < 7.0 or hour >= 20.0
|
||||
else ["#f2f0ea", "#ffffff", "#4a7189", "#de8f6e"]
|
||||
),
|
||||
}
|
||||
'''
|
||||
|
||||
@@ -337,7 +343,7 @@ HOUSE_NODES = [
|
||||
{"name": "outdoor", "dtype": "float", "interval": 60},
|
||||
{"name": "humidity", "dtype": "float"},
|
||||
# Twice a day at most, so it is paced rather than sent every tick.
|
||||
{"name": "panel_theme", "dtype": "str", "interval": 60},
|
||||
{"name": "panel_palette", "dtype": "list", "interval": 60},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -870,14 +876,22 @@ NOW_WIDGETS = [
|
||||
"title": "House draw, and the share the roof covered",
|
||||
"layout": at(11, 2, 5, 2),
|
||||
"config": {
|
||||
"message": msg(HOUSE, "load_kw"),
|
||||
"dtype": "float",
|
||||
# A second reading nested inside the first, on the same scale, so
|
||||
# containment is what the picture shows rather than something to
|
||||
# work out. It only means anything because the flow computed a
|
||||
# share: the roof's whole output is not part of the house's draw.
|
||||
"inner": msg(HOUSE, "self_use_kw"),
|
||||
"inner_dtype": "float",
|
||||
# Two readings on one scale, a row each: the shorter bar *is* the
|
||||
# smaller part, so containment is still what the picture shows.
|
||||
# It only means anything because the flow computed a share — the
|
||||
# roof's whole output is not part of the house's draw.
|
||||
"rows": [
|
||||
{
|
||||
"message": msg(HOUSE, "load_kw"),
|
||||
"dtype": "float",
|
||||
"label": "House",
|
||||
},
|
||||
{
|
||||
"message": msg(HOUSE, "self_use_kw"),
|
||||
"dtype": "float",
|
||||
"label": "From the roof",
|
||||
},
|
||||
],
|
||||
"min": 0,
|
||||
"max": 9,
|
||||
"precision": 2,
|
||||
@@ -1226,21 +1240,23 @@ def seed_dashboard(api: Api) -> None:
|
||||
"canvas_height": CANVAS[1],
|
||||
# The settings channel: the dashboard itself as a receiver. Costs
|
||||
# no tile, which is why it fits a panel with all 17 rows spoken
|
||||
# for. `system` is the fallback until the flow first says
|
||||
# otherwise; `locked` is left unset, which is the static default
|
||||
# and keeps every control on the demo usable.
|
||||
# for. `locked` is left unset, which is the static default and
|
||||
# keeps every control on the demo usable.
|
||||
"settings": {
|
||||
"theme": {
|
||||
"value": "system",
|
||||
"message": msg(HOUSE, "panel_theme"),
|
||||
"dtype": "str",
|
||||
# Glass, because the demo is the thing people look at first
|
||||
# and this is the look that has to be seen to be understood.
|
||||
"look": {"value": "glass"},
|
||||
# Driven by the house flow: the panel's colours follow the
|
||||
# hour, and the ground it names is also what makes it read
|
||||
# light by day and dark at night. The value here is the
|
||||
# fallback until the flow first says otherwise.
|
||||
"palette": {
|
||||
"value": ["#f2f0ea", "#ffffff", "#4a7189", "#de8f6e"],
|
||||
"message": msg(HOUSE, "panel_palette"),
|
||||
"dtype": "list",
|
||||
},
|
||||
# The same three slots a three-line chart would spread onto
|
||||
# by itself, in the opposite order — so the Power chart reads
|
||||
# just as clearly while the panel shows a palette that was
|
||||
# chosen rather than one that was defaulted into. Naming none
|
||||
# here would demonstrate nothing.
|
||||
"palette": {"value": ["5", "3", "1"]},
|
||||
# A hallway panel is touched, not pointed at.
|
||||
"touch": {"value": True},
|
||||
},
|
||||
"pages": PAGES,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user