@fugood/bricks-ctor 2.25.0-beta.5 → 2.25.0-beta.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compile/__tests__/config-diff.test.js +100 -0
- package/compile/__tests__/index.test.js +365 -0
- package/compile/__tests__/util.test.js +317 -0
- package/compile/action-name-map.ts +64 -0
- package/compile/config-diff.ts +155 -0
- package/compile/index.ts +273 -32
- package/compile/util.ts +26 -7
- package/package.json +7 -3
- package/skills/bricks-ctor/SKILL.md +23 -17
- package/skills/bricks-ctor/{rules → references}/animation.md +3 -2
- package/skills/bricks-ctor/{rules → references}/architecture-patterns.md +18 -0
- package/skills/bricks-ctor/{rules → references}/automations.md +11 -0
- package/skills/bricks-ctor/references/buttress.md +245 -0
- package/skills/bricks-ctor/references/data-calculation.md +239 -0
- package/skills/bricks-ctor/references/simulator.md +132 -0
- package/skills/bricks-ctor/references/source-editing-tools.md +81 -0
- package/skills/bricks-ctor/references/verification-toolchain.md +200 -0
- package/skills/bricks-design/SKILL.md +150 -45
- package/skills/bricks-design/references/architecture-truths.md +132 -0
- package/skills/bricks-design/references/avoiding-complexity.md +91 -0
- package/skills/bricks-design/references/design-critique.md +195 -0
- package/skills/bricks-design/references/design-languages.md +265 -0
- package/skills/bricks-design/references/performance.md +116 -0
- package/skills/bricks-design/references/presentation-and-slideshow.md +137 -0
- package/skills/bricks-design/references/translating-inputs.md +152 -0
- package/skills/bricks-design/references/variations-and-tweaks.md +124 -0
- package/skills/bricks-design/references/when-the-brief-is-branded.md +284 -0
- package/skills/bricks-design/references/when-the-brief-is-vague.md +85 -0
- package/skills/bricks-design/references/workflow.md +134 -0
- package/skills/bricks-ux/SKILL.md +114 -0
- package/skills/bricks-ux/references/accessibility.md +162 -0
- package/skills/bricks-ux/references/flow-states.md +175 -0
- package/skills/bricks-ux/references/interaction-archetypes.md +189 -0
- package/skills/bricks-ux/references/monitoring-screens.md +153 -0
- package/skills/bricks-ux/references/pressable-composition.md +126 -0
- package/skills/bricks-ux/references/user-journey.md +168 -0
- package/skills/bricks-ux/references/ux-critique.md +256 -0
- package/tools/__tests__/_cli-error.test.ts +35 -0
- package/tools/_cli-error.ts +17 -0
- package/tools/_edits-log.ts +41 -0
- package/tools/_git-author.ts +10 -2
- package/tools/_last-pushed-commit.ts +28 -0
- package/tools/_shell.ts +8 -1
- package/tools/deploy.ts +17 -6
- package/tools/mcp-env.ts +13 -0
- package/tools/mcp-server.ts +8 -0
- package/tools/mcp-tools/__tests__/data-calc-editing.test.js +516 -0
- package/tools/mcp-tools/__tests__/entry-editing.test.js +866 -0
- package/tools/mcp-tools/__tests__/huggingface.test.ts +49 -0
- package/tools/mcp-tools/__tests__/icons.test.ts +21 -0
- package/tools/mcp-tools/__tests__/mcp-env.test.js +19 -0
- package/tools/mcp-tools/_editing-helpers.ts +58 -0
- package/tools/mcp-tools/_verify.ts +50 -0
- package/tools/mcp-tools/compile.ts +21 -9
- package/tools/mcp-tools/data-calc-editing.ts +1349 -0
- package/tools/mcp-tools/entry-editing.ts +2336 -0
- package/tools/mcp-tools/huggingface.ts +23 -13
- package/tools/mcp-tools/icons.ts +23 -7
- package/tools/mcp-tools/media.ts +4 -1
- package/tools/postinstall.ts +80 -3
- package/tools/pull.ts +93 -22
- package/tools/push-config.ts +114 -0
- package/tools/{preview-main.mjs → simulator-main.mjs} +207 -12
- package/tools/simulator-preload.cjs +16 -0
- package/tools/{preview.ts → simulator.ts} +4 -4
- package/types/{animation.ts → animation.d.ts} +24 -8
- package/types/{automation.ts → automation.d.ts} +16 -20
- package/types/{brick-base.ts → brick-base.d.ts} +1 -1
- package/types/bricks/{Camera.ts → Camera.d.ts} +8 -8
- package/types/bricks/{Chart.ts → Chart.d.ts} +4 -4
- package/types/bricks/{GenerativeMedia.ts → GenerativeMedia.d.ts} +15 -15
- package/types/bricks/{Icon.ts → Icon.d.ts} +7 -7
- package/types/bricks/{Image.ts → Image.d.ts} +21 -9
- package/types/bricks/{Items.ts → Items.d.ts} +7 -7
- package/types/bricks/{Lottie.ts → Lottie.d.ts} +10 -10
- package/types/bricks/{Maps.ts → Maps.d.ts} +11 -11
- package/types/bricks/{QrCode.ts → QrCode.d.ts} +7 -7
- package/types/bricks/{Rect.ts → Rect.d.ts} +7 -7
- package/types/bricks/{RichText.ts → RichText.d.ts} +12 -9
- package/types/bricks/{Rive.ts → Rive.d.ts} +9 -9
- package/types/bricks/Scene3D.d.ts +676 -0
- package/types/bricks/{Sketch.ts → Sketch.d.ts} +6 -6
- package/types/bricks/{Slideshow.ts → Slideshow.d.ts} +7 -7
- package/types/bricks/{Svg.ts → Svg.d.ts} +7 -7
- package/types/bricks/{Text.ts → Text.d.ts} +9 -9
- package/types/bricks/{TextInput.ts → TextInput.d.ts} +10 -10
- package/types/bricks/{Video.ts → Video.d.ts} +12 -12
- package/types/bricks/{VideoStreaming.ts → VideoStreaming.d.ts} +10 -10
- package/types/bricks/{WebRtcStream.ts → WebRtcStream.d.ts} +1 -1
- package/types/bricks/{WebView.ts → WebView.d.ts} +4 -4
- package/types/bricks/{index.ts → index.d.ts} +1 -0
- package/types/{common.ts → common.d.ts} +3 -6
- package/types/data-calc-command/base.d.ts +57 -0
- package/types/data-calc-command/collection.d.ts +418 -0
- package/types/data-calc-command/color.d.ts +432 -0
- package/types/data-calc-command/constant.d.ts +50 -0
- package/types/data-calc-command/datetime.d.ts +147 -0
- package/types/data-calc-command/file.d.ts +129 -0
- package/types/data-calc-command/index.d.ts +13 -0
- package/types/data-calc-command/iteratee.d.ts +23 -0
- package/types/data-calc-command/logictype.d.ts +190 -0
- package/types/data-calc-command/math.d.ts +275 -0
- package/types/data-calc-command/object.d.ts +119 -0
- package/types/data-calc-command/sandbox.d.ts +66 -0
- package/types/data-calc-command/string.d.ts +407 -0
- package/types/{data-calc.ts → data-calc.d.ts} +1 -0
- package/types/{data.ts → data.d.ts} +4 -2
- package/types/generators/{Assistant.ts → Assistant.d.ts} +19 -0
- package/types/generators/{LlmGgml.ts → LlmGgml.d.ts} +43 -1
- package/types/generators/{LlmMlx.ts → LlmMlx.d.ts} +1 -0
- package/types/generators/{RerankerGgml.ts → RerankerGgml.d.ts} +5 -1
- package/types/generators/{SoundRecorder.ts → SoundRecorder.d.ts} +10 -1
- package/types/generators/{SpeechToTextGgml.ts → SpeechToTextGgml.d.ts} +6 -1
- package/types/generators/{SttAppleBuiltin.ts → SttAppleBuiltin.d.ts} +27 -4
- package/types/generators/{ThermalPrinter.ts → ThermalPrinter.d.ts} +9 -7
- package/types/generators/{VadGgml.ts → VadGgml.d.ts} +12 -2
- package/types/{subspace.ts → subspace.d.ts} +1 -1
- package/utils/__tests__/calc.test.js +25 -0
- package/utils/__tests__/id.test.js +154 -0
- package/utils/calc.ts +5 -1
- package/utils/data.ts +5 -7
- package/utils/event-props.ts +17 -0
- package/utils/id.ts +109 -56
- package/skills/bricks-ctor/rules/buttress.md +0 -156
- package/skills/bricks-ctor/rules/data-calculation.md +0 -209
- package/skills/bricks-design/LICENSE.txt +0 -180
- package/types/data-calc-command.ts +0 -7005
- /package/skills/bricks-ctor/{rules → references}/local-sync.md +0 -0
- /package/skills/bricks-ctor/{rules → references}/media-flow.md +0 -0
- /package/skills/bricks-ctor/{rules → references}/remote-data-bank.md +0 -0
- /package/skills/bricks-ctor/{rules → references}/standby-transition.md +0 -0
- /package/types/{canvas.ts → canvas.d.ts} +0 -0
- /package/types/{data-calc-script.ts → data-calc-script.d.ts} +0 -0
- /package/types/generators/{AlarmClock.ts → AlarmClock.d.ts} +0 -0
- /package/types/generators/{BleCentral.ts → BleCentral.d.ts} +0 -0
- /package/types/generators/{BlePeripheral.ts → BlePeripheral.d.ts} +0 -0
- /package/types/generators/{CanvasMap.ts → CanvasMap.d.ts} +0 -0
- /package/types/generators/{CastlesPay.ts → CastlesPay.d.ts} +0 -0
- /package/types/generators/{DataBank.ts → DataBank.d.ts} +0 -0
- /package/types/generators/{File.ts → File.d.ts} +0 -0
- /package/types/generators/{GraphQl.ts → GraphQl.d.ts} +0 -0
- /package/types/generators/{Http.ts → Http.d.ts} +0 -0
- /package/types/generators/{HttpServer.ts → HttpServer.d.ts} +0 -0
- /package/types/generators/{Information.ts → Information.d.ts} +0 -0
- /package/types/generators/{Intent.ts → Intent.d.ts} +0 -0
- /package/types/generators/{Iterator.ts → Iterator.d.ts} +0 -0
- /package/types/generators/{Keyboard.ts → Keyboard.d.ts} +0 -0
- /package/types/generators/{LlmAnthropicCompat.ts → LlmAnthropicCompat.d.ts} +0 -0
- /package/types/generators/{LlmAppleBuiltin.ts → LlmAppleBuiltin.d.ts} +0 -0
- /package/types/generators/{LlmMediaTekNeuroPilot.ts → LlmMediaTekNeuroPilot.d.ts} +0 -0
- /package/types/generators/{LlmOnnx.ts → LlmOnnx.d.ts} +0 -0
- /package/types/generators/{LlmOpenAiCompat.ts → LlmOpenAiCompat.d.ts} +0 -0
- /package/types/generators/{LlmQualcommAiEngine.ts → LlmQualcommAiEngine.d.ts} +0 -0
- /package/types/generators/{Mcp.ts → Mcp.d.ts} +0 -0
- /package/types/generators/{McpServer.ts → McpServer.d.ts} +0 -0
- /package/types/generators/{MediaFlow.ts → MediaFlow.d.ts} +0 -0
- /package/types/generators/{MqttBroker.ts → MqttBroker.d.ts} +0 -0
- /package/types/generators/{MqttClient.ts → MqttClient.d.ts} +0 -0
- /package/types/generators/{Question.ts → Question.d.ts} +0 -0
- /package/types/generators/{RealtimeTranscription.ts → RealtimeTranscription.d.ts} +0 -0
- /package/types/generators/{SerialPort.ts → SerialPort.d.ts} +0 -0
- /package/types/generators/{SoundPlayer.ts → SoundPlayer.d.ts} +0 -0
- /package/types/generators/{SpeechToTextOnnx.ts → SpeechToTextOnnx.d.ts} +0 -0
- /package/types/generators/{SpeechToTextPlatform.ts → SpeechToTextPlatform.d.ts} +0 -0
- /package/types/generators/{SqLite.ts → SqLite.d.ts} +0 -0
- /package/types/generators/{Step.ts → Step.d.ts} +0 -0
- /package/types/generators/{Tcp.ts → Tcp.d.ts} +0 -0
- /package/types/generators/{TcpServer.ts → TcpServer.d.ts} +0 -0
- /package/types/generators/{TextToSpeechAppleBuiltin.ts → TextToSpeechAppleBuiltin.d.ts} +0 -0
- /package/types/generators/{TextToSpeechGgml.ts → TextToSpeechGgml.d.ts} +0 -0
- /package/types/generators/{TextToSpeechOnnx.ts → TextToSpeechOnnx.d.ts} +0 -0
- /package/types/generators/{TextToSpeechOpenAiLike.ts → TextToSpeechOpenAiLike.d.ts} +0 -0
- /package/types/generators/{Tick.ts → Tick.d.ts} +0 -0
- /package/types/generators/{Udp.ts → Udp.d.ts} +0 -0
- /package/types/generators/{VadOnnx.ts → VadOnnx.d.ts} +0 -0
- /package/types/generators/{VadTraditional.ts → VadTraditional.d.ts} +0 -0
- /package/types/generators/{VectorStore.ts → VectorStore.d.ts} +0 -0
- /package/types/generators/{Watchdog.ts → Watchdog.d.ts} +0 -0
- /package/types/generators/{WebCrawler.ts → WebCrawler.d.ts} +0 -0
- /package/types/generators/{WebRtc.ts → WebRtc.d.ts} +0 -0
- /package/types/generators/{WebSocket.ts → WebSocket.d.ts} +0 -0
- /package/types/generators/{index.ts → index.d.ts} +0 -0
- /package/types/{index.ts → index.d.ts} +0 -0
- /package/types/{switch.ts → switch.d.ts} +0 -0
- /package/types/{system.ts → system.d.ts} +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Flow States
|
|
2
|
+
|
|
3
|
+
Idle, loading, empty, error, attractor, boot, maintenance — these are not afterthoughts. They are states the deployment will spend real time in. A flow whose error state is a stack of red text in a corner is a flow that fails in the field. A kiosk whose idle state is "whatever the last user was looking at" is a kiosk that confuses every next user.
|
|
4
|
+
|
|
5
|
+
This file treats each as a **first-class designed state**. Universal principles, BRICKS-native expression notes, and the failure mode that consistently slips into agent-produced work.
|
|
6
|
+
|
|
7
|
+
The common thread across all of them: every state has a *who arrives*, a *what they see*, a *what they need to know*, and a *how they leave*. If you cannot answer all four, the state is unfinished.
|
|
8
|
+
|
|
9
|
+
## Idle
|
|
10
|
+
|
|
11
|
+
**The state when the screen is on, the user is not present, and no peripheral / sensor event is active.**
|
|
12
|
+
|
|
13
|
+
Most kiosks and interactive deployments spend the majority of their hours idle. Yet idle is the most-skipped designed state in agent work — it gets treated as "whatever Canvas is loaded when nobody's using it," which is wrong.
|
|
14
|
+
|
|
15
|
+
**Design discipline:**
|
|
16
|
+
|
|
17
|
+
- **Idle is a designed Canvas (or set of Canvases), not a side-effect.** The flow returns to it after every session via an idle-timeout reset.
|
|
18
|
+
- **Idle invites.** A passerby should look at the idle screen and understand what's offered here. This is the affordance layer for the eventual interact flow — see [`user-journey.md`](user-journey.md) step 1.
|
|
19
|
+
- **Idle resets cleanly.** No state from the previous user persists into idle — no half-built order, no name still on screen, no "please confirm". The reset wipes flow Data; `persistData: true` is reserved for *deployment* state (last-known-good, config), not session state.
|
|
20
|
+
- **Idle rotates if needed.** For deployments where idle runs hours, a slow Slideshow / Canvas rotation prevents burn-in and gives the screen rhythm. Don't loop a single static Canvas indefinitely.
|
|
21
|
+
- **Idle is calm.** No spinners, no progress indicators, no "loading" residue. The screen is at rest.
|
|
22
|
+
|
|
23
|
+
**Failure modes:**
|
|
24
|
+
|
|
25
|
+
- Idle = "last interact Canvas frozen." Next user arrives mid-flow, doesn't know whose order is on screen, may complete or cancel someone else's.
|
|
26
|
+
- Idle with a spinner or "please wait" — implies the system is busy when it isn't.
|
|
27
|
+
- Idle without an attractor element — passersby see "this is on" but not "this is for them".
|
|
28
|
+
- Idle timeout reset that doesn't actually reset all Data — partial state leaks into next session.
|
|
29
|
+
- Idle too noisy — looping animation that demands attention from people not interacting; reads as broken.
|
|
30
|
+
|
|
31
|
+
## Attractor
|
|
32
|
+
|
|
33
|
+
**The active state of "no current user, but invite the next one."**
|
|
34
|
+
|
|
35
|
+
Some deployments differentiate idle (passive) from attractor (actively inviting). A kiosk in a quiet store may use the same Canvas for both; a kiosk in a busy mall might cycle a deliberate attractor sequence to pull users in.
|
|
36
|
+
|
|
37
|
+
**Design discipline:**
|
|
38
|
+
|
|
39
|
+
- **A clear value proposition.** "Order here", "Check in", "See today's events", "Find your room". One line, large, immediately readable from approach distance.
|
|
40
|
+
- **A demonstration of action.** A subtle animation showing the kind of interaction the user will do — a finger graphic tapping a tile, a card moving toward a reader, a face-detection frame breathing.
|
|
41
|
+
- **Brand presence, not brand wallpaper.** The brand is in the attractor; the attractor isn't *only* brand. A wordmark-only attractor doesn't tell the passerby what's possible.
|
|
42
|
+
- **Calibrated motion.** Enough to catch the eye from peripheral vision (10–15° off-axis), not enough to read as broken or anxious.
|
|
43
|
+
- **Time-of-day / context aware** if the deployment runs long hours — morning rush attractor differs from afternoon quiet differs from late-night.
|
|
44
|
+
|
|
45
|
+
**Failure modes:**
|
|
46
|
+
|
|
47
|
+
- Attractor that's only logo + tagline — looks like signage, not like an invitation to act.
|
|
48
|
+
- Attractor that demos a different action than what's available — promises one experience, delivers another.
|
|
49
|
+
- Attractor with hover-style affordances on no-touch hardware — implies pointing-device interaction that doesn't exist.
|
|
50
|
+
- Attractor competing with the deployment's surroundings — the screen drowns in a busy retail wall, or shouts over a quiet hotel lobby.
|
|
51
|
+
|
|
52
|
+
## Boot
|
|
53
|
+
|
|
54
|
+
**The state when the device just started — pre-content, pre-user.**
|
|
55
|
+
|
|
56
|
+
Per `bricks-design/performance.md`, the boot Canvas must render in < 1s using only cached/persisted Data. That's the runtime floor. The design floor is *what the user sees during that second and what arrives after*.
|
|
57
|
+
|
|
58
|
+
**Design discipline:**
|
|
59
|
+
|
|
60
|
+
- **Boot is brand, not work.** The first second is brand presence — wordmark, logo lockup, a confident moment. Not a spinner. Not "loading…".
|
|
61
|
+
- **Boot transitions into idle gracefully.** Standby Transitions carry the boot chrome into the idle Canvas; Truth #3 shared Brick ids preserve continuity. The user doesn't see a blank moment between boot and idle.
|
|
62
|
+
- **Boot is fault-tolerant.** If a Generator fails, if a Data source is unreachable, if a peripheral hasn't initialised — boot completes anyway, with the failure surfaced in the affected component (a sensor that hasn't reported reads as "—", not as a frozen screen).
|
|
63
|
+
- **Boot is what a watchdog reset returns to.** A reset is a fresh boot; design boot so the operator and any in-progress user can recover gracefully. Persistent state restores last-known-good, not last-current-screen.
|
|
64
|
+
|
|
65
|
+
**Failure modes:**
|
|
66
|
+
|
|
67
|
+
- Boot as a loading spinner over a blank background — every reset reads as "this is broken."
|
|
68
|
+
- Boot Canvas different from idle Canvas — the user sees the brand appear, then a layout shift to idle; instability tell.
|
|
69
|
+
- Boot that requires network / Generator success — offline boot fails; deployment goes dark.
|
|
70
|
+
- Boot that doesn't acknowledge watchdog reset — operator or user in-flight is suddenly back at boot with no explanation.
|
|
71
|
+
|
|
72
|
+
## Loading
|
|
73
|
+
|
|
74
|
+
**The state when the user has acted (or the system has triggered) and a response is pending.**
|
|
75
|
+
|
|
76
|
+
This is step 4 of the user journey (in-flight visibility, see [`user-journey.md`](user-journey.md)). Loading is a *state visibility* discipline, not a decorative flourish.
|
|
77
|
+
|
|
78
|
+
**Design discipline:**
|
|
79
|
+
|
|
80
|
+
- **Loading is not blankness.** A pending response gets a visible state — spinner, progress indicator, animated tile, "processing" badge — that confirms the system is working.
|
|
81
|
+
- **Loading is bounded by time-out.** Every loading state has a failure path. If the response doesn't arrive in N seconds (deployment-relative, typically 10–30 seconds for network operations, 2–5 for peripheral), the state transitions to error recovery (step 6 of the journey).
|
|
82
|
+
- **Loading disables the trigger.** While loading, the affordance that triggered it is `pressable: 'disabled'` or Switch-hidden — user can't re-trigger.
|
|
83
|
+
- **Loading scales with expected wait.** A < 1s wait is a snap-cut visual change; a 1–5s wait is a spinner; a 5s+ wait surfaces progress estimate or "still working".
|
|
84
|
+
- **Skeleton screens** (showing the *shape* of incoming content with a placeholder) work for content that arrives gradually. Less appropriate for transact-flow loading (a fake-result skeleton would mislead).
|
|
85
|
+
|
|
86
|
+
**Failure modes:**
|
|
87
|
+
|
|
88
|
+
- Loading visually identical to idle — user doesn't know if they pressed something or not.
|
|
89
|
+
- Loading without a time-out — system hangs; loading state persists forever; user walks away.
|
|
90
|
+
- Loading that allows re-trigger — user impatient, presses again, queues duplicate work.
|
|
91
|
+
- Loading dressed as success — skeleton that looks complete; user assumes the action finished and acts on the placeholder.
|
|
92
|
+
- Loading on a transact flow that reads ambiguous between "still processing" and "approved" — user walks away from a partial transaction.
|
|
93
|
+
|
|
94
|
+
## Empty
|
|
95
|
+
|
|
96
|
+
**The state when there's nothing to show — no items in the list, no events today, no notifications, no search results.**
|
|
97
|
+
|
|
98
|
+
Empty is the most-forgotten state in agent work. Loading gets designed because it follows from acting; empty gets skipped because it follows from *not* acting and the agent thinks "there's nothing to design".
|
|
99
|
+
|
|
100
|
+
**Design discipline:**
|
|
101
|
+
|
|
102
|
+
- **Empty explains the absence.** Not "nothing here". Specifically: "No bookings today. New bookings appear here." or "No events scheduled. Check back tomorrow." or "No matches. Try a different spelling."
|
|
103
|
+
- **Empty offers a path forward.** Even on monitoring deployments, empty should suggest what will populate it ("Sensor will report every 30 seconds") or how the user can change the state ("Add an item to begin").
|
|
104
|
+
- **Empty is not error.** A bookings list with no bookings today is a perfectly normal state — design it as content, not as failure.
|
|
105
|
+
- **Empty preserves the layout.** The list area / grid area is still occupied — by an empty-state composition, not by collapsed-away whitespace that resizes the rest of the screen.
|
|
106
|
+
- **Empty is rare on dense deployments and frequent on others.** A retail menu board never has an empty menu (it would close instead). A queue display is empty when there's no queue — which is most of the time.
|
|
107
|
+
|
|
108
|
+
**Failure modes:**
|
|
109
|
+
|
|
110
|
+
- Empty rendered as collapsed space — the screen's layout shifts because there's nothing there; users perceive the screen as broken.
|
|
111
|
+
- Empty rendered as "—" everywhere — placeholders never replaced by content; design forgot to handle the populated case (or vice versa).
|
|
112
|
+
- Empty as error — "No results" styled as red and alarming; the user thinks they made a mistake.
|
|
113
|
+
- Empty without explanation — the user can't tell if there's truly nothing or if data hasn't loaded.
|
|
114
|
+
|
|
115
|
+
## Error
|
|
116
|
+
|
|
117
|
+
**The state when something went wrong — peripheral disconnected, validation failed, network unavailable, Generator timed out, content feed broken.**
|
|
118
|
+
|
|
119
|
+
Error is step 6 of the user journey. It is a first-class designed state, not a corner-text afterthought.
|
|
120
|
+
|
|
121
|
+
**Design discipline:**
|
|
122
|
+
|
|
123
|
+
- **Error declares the failure.** Specifically. "Card declined." "Couldn't reach the menu. Try again in a moment." "Scanner can't see the code." Not "An error occurred." Not "ERR_TX_REJECTED."
|
|
124
|
+
- **Error explains in user-language.** Technical codes belong in logs, not on the user's screen. If the underlying cause is genuinely useful to surface (network-down state for an interactive kiosk in a corporate setting), translate.
|
|
125
|
+
- **Error offers a path forward.** Retry, alternate method, get help, abandon. Never a dead-end. Even "the system is unavailable, please come back later" is a path (the user knows to leave).
|
|
126
|
+
- **Error preserves user input.** Form input retained; user shouldn't re-type after a single validation fail. Selection state preserved; user shouldn't re-select after a "couldn't connect, try again".
|
|
127
|
+
- **Error distinguishes categories.** *User error* (action didn't succeed, retry sensibly). *System error* (the system has a problem, not the user's fault). *Abandonment* (timeout, idle reset). Each has its own treatment.
|
|
128
|
+
- **Error is calm in tone where possible.** A "card declined" screen designed in shouting red feels accusatory; the user did nothing wrong (the bank declined). Match the tone to what's actually happened.
|
|
129
|
+
|
|
130
|
+
**Failure modes:**
|
|
131
|
+
|
|
132
|
+
- Error as a stack of red text — accusatory and unhelpful.
|
|
133
|
+
- Error as a generic toast — disappears before the user reads it.
|
|
134
|
+
- Error with no recovery path — user stuck on an error Canvas with no way forward except staff intervention.
|
|
135
|
+
- Error that erases user progress — single-field validation fail dumps the user back to step 1 of a 7-step flow.
|
|
136
|
+
- Error category collapsed — every kind of failure ("declined" / "network down" / "wrong card type") shown identically; user can't pick the right recovery.
|
|
137
|
+
- Error styled as alarm-grade visual when the failure is mundane — fatigues the user and the operator.
|
|
138
|
+
|
|
139
|
+
## Maintenance
|
|
140
|
+
|
|
141
|
+
**The state when the deployment is intentionally taken out of service — software update, content refresh, scheduled downtime, manual operator pause.**
|
|
142
|
+
|
|
143
|
+
**Design discipline:**
|
|
144
|
+
|
|
145
|
+
- **Maintenance is a Canvas, not a black screen.** The screen tells the user / operator that the deployment is intentionally offline and when it'll return.
|
|
146
|
+
- **Maintenance distinguishes itself from error.** "We're updating menus — back in 5 minutes" reads differently from "Something went wrong." Different visual tone, different language.
|
|
147
|
+
- **Maintenance has a return path.** Specific return time if known; vague "shortly" if not, with a contact route if relevant.
|
|
148
|
+
- **Maintenance is operator-aware.** A factory-floor monitor in maintenance shows the operator badge / contact / instructions to bring it back online. A passerby-facing deployment shows a friendly message; the operator interface for resuming is gated by some access (Settings, password, key combo).
|
|
149
|
+
|
|
150
|
+
**Failure modes:**
|
|
151
|
+
|
|
152
|
+
- Maintenance = black screen — user thinks the device is broken.
|
|
153
|
+
- Maintenance = the most-recent error state — implies failure, not intentional pause.
|
|
154
|
+
- Maintenance without a return signal — operator forgets the deployment is paused; users walk away assuming the venue is closed.
|
|
155
|
+
- Maintenance accessible to passerby — anyone can put the kiosk into maintenance and walk away.
|
|
156
|
+
|
|
157
|
+
## When to design each state
|
|
158
|
+
|
|
159
|
+
Different deployments live in different states most of the time.
|
|
160
|
+
|
|
161
|
+
- **Signage / glance**: idle (= the running state), boot, occasional maintenance. Loading / empty / error rare; design lightly. Attractor sometimes a separate state for higher-energy deployments.
|
|
162
|
+
- **Self-service kiosk / interact / transact**: idle, attractor (often = idle), boot, loading (per step), error (per failure category), occasional empty, maintenance. **All states must be designed**; this is the highest-flow-state-count category.
|
|
163
|
+
- **Dashboard / monitor**: calm (= the running state, see [`monitoring-screens.md`](monitoring-screens.md)), stale-data variant, demand / alarm states, occasional empty (no data yet), error if feed is dead, maintenance.
|
|
164
|
+
- **Dwell / ambient**: looping content (= idle), boot. Error / empty rare; treat lightly.
|
|
165
|
+
|
|
166
|
+
Design the states that will actually be visited. Skipping a state because it's "rare" is correct *only if* you can confirm it actually is rare in this deployment.
|
|
167
|
+
|
|
168
|
+
## How to use this file
|
|
169
|
+
|
|
170
|
+
1. **List which states this deployment will visit.** Not all states apply to every deployment.
|
|
171
|
+
2. **For each, design the four answers** — who arrives, what they see, what they need to know, how they leave.
|
|
172
|
+
3. **Verify the state's existence in preview.** Force-trigger each state via Automation or by editing Data values; capture a screenshot; view it back. A state you haven't seen is a state you haven't designed.
|
|
173
|
+
4. **Surface every gap in the trade-off note.** If a state is in-scope but unverified for some reason (peripheral simulation not available, error mode hard to trigger), say so explicitly. The user reading the handoff should know which states have been actually tested in design.
|
|
174
|
+
|
|
175
|
+
A flow declared done where only the golden path has been screenshot-verified is a flow with undesigned states. The next user will find them.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Interaction Archetypes
|
|
2
|
+
|
|
3
|
+
The user in front of a BRICKS screen is doing one of six things. The archetype determines Subspace shape — Canvas count, dominant Brick families, motion vocabulary, what carries forward across the flow — and which UX disciplines weight strongest.
|
|
4
|
+
|
|
5
|
+
Pick the archetype first, then commit. Archetypes don't blend gracefully; a "glanceable + interact" hybrid is a sign that you need two Subspaces or one designed-as-archetype-X Subspace with a clearly bounded archetype-Y moment.
|
|
6
|
+
|
|
7
|
+
## Glance
|
|
8
|
+
|
|
9
|
+
**What the user does:** reads the screen in 1–2 seconds while passing. No interaction. No commitment. Often peripheral vision.
|
|
10
|
+
|
|
11
|
+
**Where it lives:** lobby signage, transit platform info, queue-number displays, menu boards, ambient information screens, attractor loops between active sessions.
|
|
12
|
+
|
|
13
|
+
**Rule set:**
|
|
14
|
+
|
|
15
|
+
- Type at the *legibility floor for viewing distance* — calibrate to the deployment, not to instinct. A 75" panel viewed from 4m needs body text at ≥ 4 grid units (with appropriate hardware); a 32" panel at 1m can read smaller.
|
|
16
|
+
- One primary idea per Canvas. Two competing headlines = neither lands.
|
|
17
|
+
- Refresh cadence calm — content rotates on a slow rhythm (8–15 seconds per item). Anything faster crosses into demand-attention territory.
|
|
18
|
+
- Hero continuity (Truth #3) — even glanceable signage benefits from a persistent element (logo, time, brand chrome) so the viewer's eye knows where they are returning to.
|
|
19
|
+
- No affordance for interaction the hardware can't deliver. No hover, no implied "tap for more" on a no-touch panel.
|
|
20
|
+
|
|
21
|
+
**Carries forward:** nothing. Each glance is self-sufficient.
|
|
22
|
+
|
|
23
|
+
**Failure modes:**
|
|
24
|
+
|
|
25
|
+
- Two-line headline at the edge of legibility — viewer can't read in 1.5 seconds, looks away.
|
|
26
|
+
- Slideshow rotates faster than read time — viewer catches "Item 4 of 12" but never the title.
|
|
27
|
+
- Content-dense layout imported from web — five sections fighting for the eye.
|
|
28
|
+
- Affordance signals (chevrons, button-styled tiles, "click here" copy) where the hardware can't deliver.
|
|
29
|
+
|
|
30
|
+
**Critical UX dimensions:** visual hierarchy, legibility floor, dwell-pacing.
|
|
31
|
+
**Negligible UX dimensions:** in-flight visibility, error recovery, closure (the user doesn't act).
|
|
32
|
+
|
|
33
|
+
## Browse
|
|
34
|
+
|
|
35
|
+
**What the user does:** scans options without commitment. Reads multiple things looking for what's relevant. Looks at, doesn't necessarily decide.
|
|
36
|
+
|
|
37
|
+
**Where it lives:** menu boards with multiple categories, schedule boards, room-availability displays, retail-shelf overhead screens, museum exhibit info.
|
|
38
|
+
|
|
39
|
+
**Rule set:**
|
|
40
|
+
|
|
41
|
+
- Layout supports comparison. Adjacent items should be visually parallel (same Brick shape, same scale) so the eye can shift between them.
|
|
42
|
+
- One axis of variation per dimension — sort by category OR by time OR by price, not all three simultaneously without UI separation.
|
|
43
|
+
- If the deployment is touch-capable, browse can promote to interact: tiles with deliberate pressable affordance (see [`pressable-composition.md`](pressable-composition.md)). On no-touch, browse stays pure read.
|
|
44
|
+
- Carry forward minimal — if the user wanders away and comes back, the screen should be in the same readable state (no half-completed selection clogging the view).
|
|
45
|
+
- Dwell time is real — viewer may stand there 5–20 seconds. Plan for it. Content should *reward* dwell with subtle motion (Standby on Brick lists, gentle highlights) without crossing into demand attention.
|
|
46
|
+
|
|
47
|
+
**Carries forward:** sometimes selection state if browse promotes to interact; otherwise nothing.
|
|
48
|
+
|
|
49
|
+
**Failure modes:**
|
|
50
|
+
|
|
51
|
+
- Items styled too differently — eye can't compare, fragments instead of scans.
|
|
52
|
+
- Excessive depth — a browse screen that requires drilling reads as interact, not browse.
|
|
53
|
+
- Auto-rotation while user is browsing — content shifts mid-read, viewer loses place.
|
|
54
|
+
- Empty browse state (no items today, gallery closed) treated as forgotten case — see [`flow-states.md`](flow-states.md).
|
|
55
|
+
|
|
56
|
+
**Critical UX dimensions:** visual hierarchy, comparison legibility, empty/sparse state design.
|
|
57
|
+
**Negligible UX dimensions:** transact discipline, alarm hierarchy.
|
|
58
|
+
|
|
59
|
+
## Interact
|
|
60
|
+
|
|
61
|
+
**What the user does:** drives a flow. Taps to choose, navigates between Canvases, completes a non-financial task — order something, request information, configure a setting, sign in to a non-payment portal.
|
|
62
|
+
|
|
63
|
+
**Where it lives:** self-service ordering, ticket selection, info-kiosk requests, queue ticket dispensers, event check-in, configuration interfaces, language pickers.
|
|
64
|
+
|
|
65
|
+
**Rule set:**
|
|
66
|
+
|
|
67
|
+
- Every action gets the full 7-step journey (see [`user-journey.md`](user-journey.md)). Skipping any step is a UX failure.
|
|
68
|
+
- Hero Bricks carry continuity across the flow Canvases (Truth #3). The brand chrome / progress indicator / step number should never disappear mid-flow.
|
|
69
|
+
- Pressable affordance is unambiguous (see [`pressable-composition.md`](pressable-composition.md)). Tiles that look like tiles, taps that visibly land.
|
|
70
|
+
- Idle reset — interact deployments are often left mid-flow. The Subspace must have an idle timeout that returns to attractor / boot state without preserving the abandoned session for the next user (unless explicitly designed for resumption).
|
|
71
|
+
- Position memory — the user should be able to back out one step without losing the whole flow. Switch on a `flowStep` Data with persistent intermediate states.
|
|
72
|
+
- Reduce decision pressure — short on-Canvas option lists (≤ 5 primary choices on one Canvas); promote to multi-Canvas if more.
|
|
73
|
+
|
|
74
|
+
**Carries forward:** flow state (selection, configuration, pending submission) across Canvases until completion or reset.
|
|
75
|
+
|
|
76
|
+
**Failure modes:**
|
|
77
|
+
|
|
78
|
+
- 12-option grid that needs scrolling on Canvas 1 — overload, no scroll on BRICKS (Truth #10).
|
|
79
|
+
- Continuation Canvas changes the location of the back action — user can't return.
|
|
80
|
+
- Mid-flow content overload — every Canvas tries to summarise everything before, instead of advancing.
|
|
81
|
+
- Idle timeout missing — next user inherits previous user's half-built order.
|
|
82
|
+
- Recovery for no-input dead-ends absent — user walks away without completing; no abandonment cleanup.
|
|
83
|
+
|
|
84
|
+
**Critical UX dimensions:** journey completeness (all 7 steps), affordance clarity, idle reset, position memory.
|
|
85
|
+
**Negligible UX dimensions:** alarm hierarchy, monitoring discipline.
|
|
86
|
+
|
|
87
|
+
## Transact
|
|
88
|
+
|
|
89
|
+
**What the user does:** completes an action with stakes — payment, identity capture, signed agreement, regulated action. The cost of error is real (financial, legal, safety).
|
|
90
|
+
|
|
91
|
+
**Where it lives:** payment terminals, self-checkout, identity verification, age check, regulated-document signing, controlled-access entry.
|
|
92
|
+
|
|
93
|
+
**Rule set:**
|
|
94
|
+
|
|
95
|
+
- The 7-step journey *tightens* (see `user-journey.md` § "When the seven steps intensify"). Confirmation before commit. In-flight visibility cannot be skipped. Recovery has explicit categories. Closure declares completion.
|
|
96
|
+
- The *point-of-no-return moment* must be visually distinct from everything before and after. The user knows when they've committed.
|
|
97
|
+
- Peripherals dominate — payment terminal, NFC reader, camera for ID. Each peripheral's state must be visible to the user. Generator events drive Switch transitions; never guess at peripheral state.
|
|
98
|
+
- Audio cues if hardware allows — financial transactions benefit from non-visual confirmation (the user is often looking at the terminal, not the screen, mid-tap).
|
|
99
|
+
- Path 2 verification (on-device DevTools) is mandatory for these deployments; the design must be tested on the real hardware with the real peripherals before declaring done.
|
|
100
|
+
- No idle timeout *during* an active transact step — the system waits for the user, not the other way around. Idle timeout only between sessions.
|
|
101
|
+
- Receipt / artifact handoff is part of the design — the closure Canvas waits for the printer event or the email-sent confirmation before declaring done.
|
|
102
|
+
|
|
103
|
+
**Carries forward:** transaction state through to closure; nothing after.
|
|
104
|
+
|
|
105
|
+
**Failure modes:**
|
|
106
|
+
|
|
107
|
+
- Confirmation step skipped — user commits without realising.
|
|
108
|
+
- In-flight state ≤ 200ms — the user double-taps because they don't see acknowledgement; second tap queues a duplicate.
|
|
109
|
+
- Generic error recovery — "Try again" doesn't distinguish card-declined (try a different card) from network-down (wait and try) from user-cancelled (start over).
|
|
110
|
+
- Closure transient — success Canvas auto-advances to idle in 1.5 seconds; user mid-blink, never saw confirmation; calls customer service.
|
|
111
|
+
- Peripheral assumed instead of observed — design assumes card-tap is instant; in production the reader takes 2–3 seconds; users walk away thinking it failed.
|
|
112
|
+
|
|
113
|
+
**Critical UX dimensions:** journey intensification, point-of-no-return clarity, in-flight visibility, recovery categories, closure weight, peripheral state visibility.
|
|
114
|
+
**Negligible UX dimensions:** ambient pacing, dwell rhythm.
|
|
115
|
+
|
|
116
|
+
## Monitor
|
|
117
|
+
|
|
118
|
+
**What the user does:** watches changing state. Often peripheral attention — the screen is a stand-by surface that becomes the centre of attention when something changes. Not always actively read; trusted by reference.
|
|
119
|
+
|
|
120
|
+
**Where it lives:** control rooms, factory floor monitors, network operations dashboards, security camera grids, transport-control screens, sensor-driven status boards, hospital nurse stations, AI-assistant monitoring panels.
|
|
121
|
+
|
|
122
|
+
**Rule set:**
|
|
123
|
+
|
|
124
|
+
- Calm-state default. The screen at rest should be readable and forgettable — operator can scan, look away, return.
|
|
125
|
+
- Change must be detectable without being demanding — a subtle motion / colour shift / hierarchy promotion that draws the eye but doesn't startle. Demand attention is reserved for true alarms.
|
|
126
|
+
- Stale-data trust principle — if the operator can't tell what's current, they will trust what they see. Stale state must be visibly declared.
|
|
127
|
+
- Alarm hierarchy under stress — multiple simultaneous alarms must already have priority order designed. The screen sorts; the operator doesn't.
|
|
128
|
+
- Show vs ask — a monitor screen often only *shows* state, leaving action to operator judgement; sometimes it *suggests* action (highlighted protocol button). Decide which it is; not both.
|
|
129
|
+
- Full coverage in [`monitoring-screens.md`](monitoring-screens.md).
|
|
130
|
+
|
|
131
|
+
**Carries forward:** operator's mental model of "what was last normal" — design with this in mind, since change-from-baseline is the operator's real read.
|
|
132
|
+
|
|
133
|
+
**Failure modes:**
|
|
134
|
+
|
|
135
|
+
- Every data field updates identically — operator can't distinguish meaningful change from background fluctuation.
|
|
136
|
+
- Alarms styled the same regardless of severity — minor warning indistinguishable from critical alert.
|
|
137
|
+
- Stale-data badge in 8pt corner type — operator never sees it.
|
|
138
|
+
- Color-only encoding (red for alarm, green for normal) — fails for colour-blind operators and in low-contrast environments.
|
|
139
|
+
- Loading state designed, empty state forgotten — fresh deployment shows "—" everywhere with no explanation.
|
|
140
|
+
|
|
141
|
+
**Critical UX dimensions:** calm/detect/demand hierarchy, stale-data trust, alarm priority, accessibility (operators may be on shift, fatigued, in suboptimal viewing conditions).
|
|
142
|
+
**Negligible UX dimensions:** dwell pacing, single-action affordance discipline.
|
|
143
|
+
|
|
144
|
+
## Dwell
|
|
145
|
+
|
|
146
|
+
**What the user does:** inhabits the space. The screen is ambient — wallpaper for a hospitality lobby, a hotel-room TV channel, a restaurant ambient display, a museum atmospheric backdrop, a brand-experience wall.
|
|
147
|
+
|
|
148
|
+
**Where it lives:** hotel and hospitality lobbies, restaurant ambiences, retail mood walls, brand-experience installations, event backdrops, spas, premium reception areas.
|
|
149
|
+
|
|
150
|
+
**Rule set:**
|
|
151
|
+
|
|
152
|
+
- Content rotates slowly — 15–60 seconds per item depending on register. Field.io-style motion poetics can run continuous loops; Kenya Hara photographs hold longer.
|
|
153
|
+
- No interaction. No affordance. The screen does not invite touching.
|
|
154
|
+
- Visual quality at maximum — assets must score high on the 5-10-2-8 craft bar (see `bricks-design/when-the-brief-is-branded.md`); poor assets in a dwell context degrade the surrounding brand more than they would in a glanceable signage context.
|
|
155
|
+
- Motion has continuity — Truth #3 hero auto-tween across Canvases keeps the dwell experience reading as one piece rather than a slide rotation.
|
|
156
|
+
- Day-night awareness if relevant — dwell deployments often run 24-hour; design adapts to ambient luminance, time-of-day, scheduled content.
|
|
157
|
+
- Sound (if hardware allows) is part of the design — ambient music selection, volume scheduling, silence as deliberate.
|
|
158
|
+
|
|
159
|
+
**Carries forward:** nothing per-user; only the slow rhythm of the loop itself.
|
|
160
|
+
|
|
161
|
+
**Failure modes:**
|
|
162
|
+
|
|
163
|
+
- Looped motion at the wrong speed — too slow reads as broken, too fast reads as nervous. Calibrate.
|
|
164
|
+
- Content variation insufficient — the same three Canvases looping every 30 seconds for 14 hours reads as broken signage.
|
|
165
|
+
- Day-night neglected — dwell loop blasting bright content into a darkened lounge at 11pm.
|
|
166
|
+
- Decorative motion competing with the brand chrome — the dwell loop should feel of-a-piece with the venue, not be a separate visual register.
|
|
167
|
+
|
|
168
|
+
**Critical UX dimensions:** asset quality, motion continuity, content variation, ambient-luminance awareness.
|
|
169
|
+
**Negligible UX dimensions:** affordance, journey completeness, alarm hierarchy.
|
|
170
|
+
|
|
171
|
+
## Hybrid and transitions
|
|
172
|
+
|
|
173
|
+
Real briefs sometimes span archetypes:
|
|
174
|
+
|
|
175
|
+
- **Glance → Interact**: signage that becomes interactive when a user approaches (BLE proximity, camera detection). Treat as a Subspace state machine — glanceable Canvas as default, transition into interact Subspace on approach event. Don't try to make one Canvas serve both; the design discipline differs.
|
|
176
|
+
- **Browse → Transact**: retail menu that promotes to ordering. Same — boundary Canvas with explicit "I want to order" affordance.
|
|
177
|
+
- **Monitor → Interact**: dashboard with an action button (acknowledge alarm, dispatch protocol). The action follows the full 7-step journey; the monitor part follows monitoring discipline.
|
|
178
|
+
- **Dwell → Glance**: ambient screen that occasionally surfaces information (welcome message for VIP, time-sensitive promotion). Add a glance Canvas as a temporary state, return to dwell after.
|
|
179
|
+
|
|
180
|
+
In every case, the transition itself is a designed moment, not an accident.
|
|
181
|
+
|
|
182
|
+
## How to use this file
|
|
183
|
+
|
|
184
|
+
1. **Pick the archetype** as part of Priority #0 — what is the user doing in front of the screen?
|
|
185
|
+
2. **Apply the rule set** as the design's starting constraints.
|
|
186
|
+
3. **Check the failure modes** before declaring the design done — most are specific to the archetype.
|
|
187
|
+
4. **Note the UX dimension weights** — let critique focus where it matters for the chosen archetype.
|
|
188
|
+
|
|
189
|
+
If you find yourself wanting to follow rules from a different archetype, the brief may actually be that archetype. Pick again.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Monitoring Screens
|
|
2
|
+
|
|
3
|
+
A monitoring screen is a designed reading surface, not a designed flow. The user — operator, controller, observer — is not driving an interaction; they are absorbing state. The discipline is entirely about what they *see* and *trust*, not what they *do*.
|
|
4
|
+
|
|
5
|
+
This file is the UX layer. Runtime semantics (Generators, Data event subscriptions, Switch thresholds) live in `bricks-design/architecture-truths.md` — particularly Truth #4 (Switches compare, Data Hit/Not-Hit only matches) and Truth #5 (Generators are headless / async / event-driven). Use them as the substrate. The design question is *what the screen shows about the state of the world*.
|
|
6
|
+
|
|
7
|
+
## The three states a viewer reads
|
|
8
|
+
|
|
9
|
+
A monitor screen is always in one of three reading-states. Designing for one without the others produces a screen that works in calm and fails under stress (or vice versa).
|
|
10
|
+
|
|
11
|
+
### Calm — scanning for the absence of trouble
|
|
12
|
+
|
|
13
|
+
The default state. Nothing requires attention. The viewer's job is reading at a glance and confirming "still nominal." This state is on the screen 95% of the time.
|
|
14
|
+
|
|
15
|
+
**Design discipline:**
|
|
16
|
+
|
|
17
|
+
- **Readable and forgettable.** The viewer should be able to absorb the screen in one peripheral-vision pass, look away, and feel confident nothing changed. Visual rhythm should be calm, predictable, with no demand-attention motion.
|
|
18
|
+
- **Hierarchy by role, not by activity.** The most-important-thing-to-monitor stays in the same place even when it's calm. Operators learn the screen by location; shifting layout based on which metric is most active destroys that mental model.
|
|
19
|
+
- **Subtle motion is permitted.** A sweep-second hand, a gentle pulse on the "live" indicator, a slow re-flow of a chart. The point is to confirm the screen is alive, not to draw the eye. `Animation` `runType: 'loop'` is legitimate here precisely for "the screen is breathing" signalling.
|
|
20
|
+
|
|
21
|
+
**Failure modes:**
|
|
22
|
+
|
|
23
|
+
- Calm-state screen so visually busy that the viewer can't tell normal from abnormal at a glance.
|
|
24
|
+
- Calm with no "alive" signal — the operator can't tell if the screen is frozen or actually displaying current state.
|
|
25
|
+
- Hierarchy that shifts based on data values — the top-of-screen item swaps because of recent activity, and the operator's eye-anchor is gone.
|
|
26
|
+
|
|
27
|
+
### Detect — change worth noticing
|
|
28
|
+
|
|
29
|
+
Something shifted. It isn't urgent, but it's worth the viewer's attention. A sensor crossed a soft threshold, a counter incremented, a new item entered the queue, a node went from 99.9% to 99.3% uptime.
|
|
30
|
+
|
|
31
|
+
**Design discipline:**
|
|
32
|
+
|
|
33
|
+
- **Show, don't ask.** The change should be detectable peripherally — a colour shift, a soft pulse on the affected item, a slow scale-up. The viewer can catch it without breaking focus from other things.
|
|
34
|
+
- **Local, not global.** The change is localised to the affected Brick / region; the rest of the screen stays calm. Global re-styling of the whole Canvas for a single sub-system change is over-reaction.
|
|
35
|
+
- **Time-bounded acknowledgement.** A detect-state visual should hold for long enough to be noticed (say 5–15 seconds), then quietly subside or escalate, depending on what happened next.
|
|
36
|
+
- **Hero continuity.** Truth #3 — the chrome around the changing element does not also re-render. The eye lands on what moved.
|
|
37
|
+
|
|
38
|
+
**Failure modes:**
|
|
39
|
+
|
|
40
|
+
- Detect-state styled identically to calm — the viewer can't see anything changed.
|
|
41
|
+
- Detect-state escalates immediately into demand styling (loud, motion-heavy, audible) — false alarm fatigue. The viewer learns to ignore "alarms" that are really just minor changes.
|
|
42
|
+
- Detect-state persists indefinitely — small changes from yesterday still highlighted on today's screen; visual debt accumulates; nothing reads as fresh.
|
|
43
|
+
|
|
44
|
+
### Demand — compel response
|
|
45
|
+
|
|
46
|
+
A threshold breach. Something is wrong; the operator needs to act. This is the only state where the screen is allowed to *interrupt* the viewer.
|
|
47
|
+
|
|
48
|
+
**Design discipline:**
|
|
49
|
+
|
|
50
|
+
- **Unambiguous shift in register.** A clear visual rupture from calm — bold colour, accelerated motion, on-screen size, possible audio cue. The viewer's eye lands within a second.
|
|
51
|
+
- **Action-pathing visible.** If the operator is expected to do something (acknowledge, dispatch, escalate), the action is on-screen and reachable. If they're expected to look elsewhere (radio, terminal), the screen says so.
|
|
52
|
+
- **No false demand.** Demand state is earned by genuine threshold breaches; not by every-blue-moon variance. Demand-fatigue is the most expensive failure mode of a monitoring deployment — operators learn to dismiss real alarms because there were too many false ones.
|
|
53
|
+
- **Persistent until cleared.** Demand state holds until the underlying condition resolves *or* the operator explicitly acknowledges. It does not time out on its own.
|
|
54
|
+
- **Severity tiers** if the deployment has more than one demand level (warning / critical / emergency). Each tier reads distinctly; an operator under stress must be able to triage in one look.
|
|
55
|
+
|
|
56
|
+
**Failure modes:**
|
|
57
|
+
|
|
58
|
+
- Demand state styled subtly — operator misses it because it doesn't stand out.
|
|
59
|
+
- Multiple concurrent demand states styled identically — no priority order; the operator picks one arbitrarily.
|
|
60
|
+
- Demand state auto-clears after a timer — the underlying condition is still active; the screen has gone silent on it; the operator believes things are fine.
|
|
61
|
+
- Demand state uses motion that overwhelms — every demand item flashes; the screen becomes unreadable.
|
|
62
|
+
|
|
63
|
+
## The transitions between states are designed
|
|
64
|
+
|
|
65
|
+
Calm → Detect → Demand → Calm is not a state machine the runtime hands you. It's a designed UX transition the agent commits to. Shared Brick auto-tween (Truth #3) carries the affected item across the transition; the chrome around it stays.
|
|
66
|
+
|
|
67
|
+
- **Calm → Detect.** A subtle promotion. The affected Brick scales by 5–10%, gains a soft colour overlay, gets a subtle Standby Transition pulse. The eye is invited, not yanked.
|
|
68
|
+
- **Detect → Demand.** A clear escalation. The affected Brick gains strong styling — a contrasting outline, a faster pulse, a colour shift to alarm tone — and possibly promotes in screen hierarchy (becomes larger, moves to a dedicated alarm region).
|
|
69
|
+
- **Demand → Calm.** The release is also designed. Operator acknowledges or condition resolves; the affected Brick returns to its calm pose with a Standby Transition. The transition reads as relief, not as the screen forgetting.
|
|
70
|
+
|
|
71
|
+
Each transition is a Switch on a state Data with thresholds (Truth #4). Each step in the transition has its own Brick configuration. The agent commits to the visual story across the four states, not just the calm baseline.
|
|
72
|
+
|
|
73
|
+
## Stale-data trust principle
|
|
74
|
+
|
|
75
|
+
**Stale data is worse than no data.** If the viewer cannot tell whether what they're seeing is current, they will trust what they see and act on it. Staleness must be *visibly declared* — not as fine-print, as a visible state change.
|
|
76
|
+
|
|
77
|
+
**Design discipline:**
|
|
78
|
+
|
|
79
|
+
- Every live-data Brick should have a visible "data age" or "last update" indicator, or a Switch-driven visual state for staleness. Background colour shift, opacity drop, "STALE" badge, or full handover to a "feed is down" Canvas if all sources are stale.
|
|
80
|
+
- The threshold for "stale" is a design decision per source. Sub-second feeds (sensor stream) are stale after a few seconds. Minute-cadence feeds (weather, news) tolerate longer. Per-source thresholds belong in Data, not hardcoded everywhere.
|
|
81
|
+
- A feed that loses its source entirely must not silently freeze on its last value — the screen must visibly transition to a no-data state. The operator can then route around it.
|
|
82
|
+
|
|
83
|
+
**Failure modes:**
|
|
84
|
+
|
|
85
|
+
- No staleness indicator at all — viewer trusts last-known-value forever.
|
|
86
|
+
- Staleness indicator at 8pt in the corner — invisible to peripheral vision.
|
|
87
|
+
- Stale value styled identically to current value — operator looks at "23°C" and acts on it; the reading is from 4 hours ago.
|
|
88
|
+
- "Last update" shown but in a format the viewer must parse — "15:42:03" with no relative time framing. Relative ("2 minutes ago") beats absolute when "is this current" is the question.
|
|
89
|
+
|
|
90
|
+
## Show vs ask — a design decision
|
|
91
|
+
|
|
92
|
+
Some monitor screens *show* — they display state, leave action to operator judgement, never suggest. Air traffic control. Power-grid status.
|
|
93
|
+
|
|
94
|
+
Others *show and ask* — they display state and surface protocol actions at the right moment. Hospital nurse stations. Building security. A "page nurse" button appears next to a patient whose vitals shifted; an "acknowledge alarm" button appears with a fire-system trigger.
|
|
95
|
+
|
|
96
|
+
**Decide which it is per deployment, not per Canvas.** A monitor that sometimes asks and sometimes only shows confuses the operator about what they should be doing.
|
|
97
|
+
|
|
98
|
+
Once decided:
|
|
99
|
+
|
|
100
|
+
- **Show-only** monitors should not have action buttons at all. Any "do something" lives in a separate system (operator radio, dedicated terminal). The monitor reads as documentation.
|
|
101
|
+
- **Show-and-ask** monitors integrate the action affordance into the alarm hierarchy. The action affordance follows the 7-step journey (see [`user-journey.md`](user-journey.md)) — affordance, instruction, feedback on press, in-flight visibility, continuation, recovery, closure. The monitor returns to calm only after the operator's action is registered and the underlying condition clears.
|
|
102
|
+
|
|
103
|
+
## Hierarchy under stress
|
|
104
|
+
|
|
105
|
+
When multiple things demand attention at once — three alarms, two warnings, a stale feed — the screen must already have a priority order designed.
|
|
106
|
+
|
|
107
|
+
**Design discipline:**
|
|
108
|
+
|
|
109
|
+
- **Sort by severity, then by recency.** Critical alarms above warnings above advisories; within tier, newest at top. Operators learn the order; reading is faster.
|
|
110
|
+
- **Don't dilute.** Two simultaneous critical alarms don't both shrink to fit; the second one takes a designed "stacked" slot rather than reducing the first.
|
|
111
|
+
- **Aggregate count visible.** When more demand states exist than the screen surfaces in detail, an "N more" indicator preserves operator awareness of the full picture.
|
|
112
|
+
- **The calm Bricks recede.** Under stress, the rest of the screen quietens — backgrounds desaturate, non-alarm items reduce opacity. The eye is led to the demand region.
|
|
113
|
+
|
|
114
|
+
**Failure modes:**
|
|
115
|
+
|
|
116
|
+
- All concurrent alarms styled identically — operator picks one arbitrarily, may not hit the most critical.
|
|
117
|
+
- The most recent alarm overwrites the older one — older urgent alarms vanish from view.
|
|
118
|
+
- Screen layout shifts under stress — the chrome moves; the operator's spatial mental model breaks.
|
|
119
|
+
|
|
120
|
+
## Color is necessary but never sufficient
|
|
121
|
+
|
|
122
|
+
Critical / warning / normal must be encoded redundantly — colour PLUS shape, position, weight, or text. Operators may be colour-blind; viewing conditions may be unkind to colour (sun glare on screen, monochrome failover, photocopy of the screen sent to a stakeholder, viewing through a tinted shield).
|
|
123
|
+
|
|
124
|
+
See [`accessibility.md`](accessibility.md) for the universal principle. For monitor screens specifically:
|
|
125
|
+
|
|
126
|
+
- Critical alarms get a distinctive *shape* (diamond, hexagon, doubled border) on top of colour.
|
|
127
|
+
- Severity indicated by *position* (top-of-list, dedicated alarm strip) as well as colour.
|
|
128
|
+
- Numeric values that exceed threshold get a *prefix or sign* (▲, !, [HIGH]) — not just a colour change.
|
|
129
|
+
|
|
130
|
+
## Refresh cadence is a UX decision
|
|
131
|
+
|
|
132
|
+
How fast data updates is a UX decision before it's a wiring decision. A power-grid status board updating every 100ms reads as nervous; the same data refreshing every 5 seconds with a clear "live" pulse reads as in-control.
|
|
133
|
+
|
|
134
|
+
**Design discipline:**
|
|
135
|
+
|
|
136
|
+
- Pick a refresh cadence per source that matches how the operator should be reading it. Cadence is about *the reading experience*, not about whether the data exists.
|
|
137
|
+
- Visible animation of updates (a value tweens from 23.4 to 23.7 over 400ms) reads calmer than snap updates. Use it for ongoing readings, not for state transitions (those are snaps).
|
|
138
|
+
- For cadence < 1 second, batch the perceived update — even if the underlying stream is 10Hz, the on-screen change rolls forward in human-readable beats.
|
|
139
|
+
- For cadence > 30 seconds, the absence of motion can read as broken. Add a calm "alive" indicator that ticks even when data hasn't changed.
|
|
140
|
+
|
|
141
|
+
## How to use this file
|
|
142
|
+
|
|
143
|
+
Before designing a monitoring screen:
|
|
144
|
+
|
|
145
|
+
1. **Confirm Priority #0** — who is the operator, what are they reading, under what conditions, what's the cost of missing a state change.
|
|
146
|
+
2. **Pick the show / show-and-ask posture.** Don't decide later; it shapes everything else.
|
|
147
|
+
3. **Design all three reading-states** (calm / detect / demand) at the start, not just the calm one. Sketch the demand-state Canvas before the calm baseline lands.
|
|
148
|
+
4. **Design the transitions** between states using shared Brick auto-tween (Truth #3) for affected items and Standby Transitions for the moment of change.
|
|
149
|
+
5. **Design stale-data state per source.** No source is allowed to silently freeze.
|
|
150
|
+
6. **Stress-test the hierarchy.** Stack 3 concurrent demand states in design preview; verify priority reads correctly.
|
|
151
|
+
7. **Verify redundant encoding.** Take a monochrome screenshot; severity tiers should still be distinguishable.
|
|
152
|
+
|
|
153
|
+
A monitor screen that passes calm-state critique but hasn't been designed for demand is half a deliverable.
|