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:
@@ -28,7 +28,7 @@ and dragging is off. Picking a widget and editing its settings still works.
|
||||
| **Value** | anything | a formatted reading with a unit and a precision |
|
||||
| **Gauge** | `float`, `int` | min, max, unit |
|
||||
| **Chart** | `float`, `int` | up to five series; see *Two kinds of chart* below |
|
||||
| **Bar** | `float`, `int` | a reading, optionally nesting up to three inside it |
|
||||
| **Bar** | `float`, `int` | up to eight readings, a row each, with a scale per row |
|
||||
| **Icon** | numbers, booleans, weather strings | maps a value onto a glyph |
|
||||
| **Text** | — | markdown you write; a label, a note, an instruction |
|
||||
| **Agenda** | `list` | upcoming items, e.g. from a calendar connector |
|
||||
@@ -36,6 +36,11 @@ and dragging is off. Picking a widget and editing its settings still works.
|
||||
| **Notification** | `record` | title, body and severity — what an alert channel writes |
|
||||
| **Clock** | — | the time, in a size a wall can read |
|
||||
|
||||
Every widget carries a **title**, and **Show title** decides whether the panel
|
||||
draws it. Turned off, the tile is just the reading — which is what a row of
|
||||
gauges under one heading wants. The title is still the widget's name: what a
|
||||
screen reader calls its controls, and what a published value is labelled with.
|
||||
|
||||
### Input
|
||||
|
||||
| Widget | Publishes | Notes |
|
||||
@@ -88,17 +93,21 @@ ignored rather than two charts overwriting each other's picture.
|
||||
|
||||
## Dashboard settings
|
||||
|
||||
Most of what a dashboard carries is a widget: a tile bound to a message. Two
|
||||
things are not, because they belong to the whole surface rather than to any
|
||||
tile on it — and a screen bolted to a wall has nobody standing at it to set
|
||||
them.
|
||||
Most of what a dashboard carries is a widget: a tile bound to a message. A
|
||||
handful of things are not, because they belong to the whole surface rather than
|
||||
to any tile on it — and a screen bolted to a wall has nobody standing at it to
|
||||
set them.
|
||||
|
||||
| Setting | Is | Driven by |
|
||||
|---|---|---|
|
||||
| **Look** | `Material` or `Glass` | a `str` message |
|
||||
| **Theme** | `System`, `Light` or `Dark` | a `str` message |
|
||||
| **Palette** | the dashboard's colours, in order | a `list` message |
|
||||
| **Background** | the URL of an image | a `str` message |
|
||||
| **Touch** | touch friendly on or off | a `bool` message |
|
||||
| **Lock** | read-only on or off | a `bool` message |
|
||||
|
||||
Both work the same way, and both halves are optional:
|
||||
They all work the same way, and both halves are optional:
|
||||
|
||||
- **Just a value.** Set Theme to `Dark` and that dashboard is dark wherever it
|
||||
is shown, whatever the device or the browser prefers. This costs no flow at
|
||||
@@ -115,9 +124,54 @@ nothing further.
|
||||
|
||||
There is no schedule field, on purpose. **A schedule is a node publishing to
|
||||
the bound message**: an `inject` with a cron expression, feeding a `change`
|
||||
node that maps the hour onto `"dark"` or `"light"`, is the whole of "dark after
|
||||
sunset" — and the same channel then serves anything else you want to drive,
|
||||
including locking a panel down remotely.
|
||||
node that maps the hour onto a palette, is the whole of "warmer after sunset" —
|
||||
and the same channel then serves anything else you want to drive, including
|
||||
locking a panel down remotely.
|
||||
|
||||
### Look
|
||||
|
||||
**Material** lays flat, tonal cards on a plain ground. **Glass** floats
|
||||
translucent tiles over a soft, slowly moving one. They are two complete sets of
|
||||
components, not two stylesheets — but they are the same dashboard: every widget,
|
||||
every control and every keystroke behaves identically, so switching look never
|
||||
changes what a panel can do.
|
||||
|
||||
### Palette
|
||||
|
||||
A palette is an ordered list of colours, and **position is the role**:
|
||||
|
||||
| # | Role |
|
||||
|---|---|
|
||||
| 1 | the ground the dashboard sits on |
|
||||
| 2 | the surface a widget is |
|
||||
| 3 | the primary — fills, active controls, the first chart line |
|
||||
| 4 | the accent — the second chart line |
|
||||
| 5 | text |
|
||||
| 6+ | further chart colours |
|
||||
|
||||
Paste a [coolors.co](https://coolors.co) link (or a list of hex colours) and the
|
||||
whole dashboard is recoloured — every widget, the rail and the charts. Leave the
|
||||
later roles off and they are worked out from the ones you gave, so **three
|
||||
colours are a whole dashboard**. **Rotate** turns the list when the roles landed
|
||||
in the wrong order. Text that could not be read on a surface is replaced with
|
||||
black or white there, so no palette can produce a line nobody can see.
|
||||
|
||||
While a palette is set, **Theme is idle**: the first colour is the ground, so
|
||||
whether the panel reads light or dark is already decided by the palette itself.
|
||||
Fault and success keep their own colours in every palette — a failure must never
|
||||
be paintable as a reading.
|
||||
|
||||
### Background
|
||||
|
||||
An image drawn under the widgets, covering the canvas. It replaces the ground
|
||||
the Glass look brings with it. Bound to a message, a flow decides the picture.
|
||||
|
||||
### Touch
|
||||
|
||||
Bigger controls, and nothing that only happens on hover. A phone gets this
|
||||
anyway, from its own width; a wall panel has no way to say so for itself.
|
||||
|
||||
### Lock
|
||||
|
||||
Lock is a read-only *surface*, not a permission. The controls stay visible,
|
||||
stop publishing and read as disabled, and the panel says **Read-only** in the
|
||||
|
||||
Reference in New Issue
Block a user