annotate design_system/NOTIFICATIONS.md @ 266:efaf4c63cc94

fix clean production bundle staging Recreate deployment staging before copying the Bazel bundle and verify required inference runtime paths before promoting it. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 12:52:30 -0700
parents 60a876c4587a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
252
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1 # Zenbu UI notifications
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
3 `zen-notifications` is a light-DOM, framework-free notification scope. Its
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
4 stack is fixed to the bottom-right by default and styled only with `--zen-*`
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
5 tokens.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
6
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
7 ```html
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
8 <zen-notifications aria-label="Notifications">
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
9 <main id="application"></main>
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
10 </zen-notifications>
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
11 ```
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
12
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13 ## Notify
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
14
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
15 Descendants dispatch a bubbling, non-composed event:
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
16
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
17 ```js
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
18 source.dispatchEvent(new CustomEvent("zen-notify", {
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
19 bubbles: true,
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
20 composed: false,
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
21 detail: {
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
22 version: 1,
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
23 id: "repository-removed",
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
24 tone: "success",
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
25 message: "Repository removed",
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
26 description: "The local checkout was preserved.",
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
27 announcement: "polite",
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
28 durationMs: 5000,
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
29 action: {
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
30 token: "opaque-action-token",
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
31 label: "Undo",
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
32 },
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
33 },
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
34 }));
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35 ```
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
37 Fields:
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
38
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
39 | Field | Values |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
40 | --- | --- |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
41 | `version` | must be `1` |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
42 | `id` | stable non-empty string |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
43 | `tone` | `info`, `success`, `warning`, or `error` |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
44 | `message` | required text |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
45 | `description` | optional text |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
46 | `announcement` | `none`, `polite`, or `assertive` |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
47 | `durationMs` | 250–120000; defaults to 5000 |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
48 | `persistent` | disables timeout when `true` |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
49 | `action` | opaque token and visible label |
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
50
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
51 The same ID updates and moves the existing record instead of creating a
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
52 duplicate. An ID is announced once during its current lifetime.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
53
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
54 ## Dismiss and actions
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
55
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
56 Dismiss through the public method or a scoped event:
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
57
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
58 ```js
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
59 notifications.dismiss("repository-removed");
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
60
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
61 source.dispatchEvent(new CustomEvent("zen-dismiss-notification", {
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
62 bubbles: true,
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
63 composed: false,
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
64 detail: { version: 1, id: "repository-removed" },
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
65 }));
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
66 ```
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
67
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
68 Action buttons dispatch `zen-notification-action` with
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
69 `{ version, id, token }`. The opaque token remains in private component state
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
70 and is never written into DOM attributes or source markup.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
71
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
72 Removal dispatches `zen-notification-removed` with `{ version, id, reason }`.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
73
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
74 ## Bounds and timing
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
75
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
76 - Three records are rendered.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
77 - Twenty additional records may remain queued.
253
fdf3816959cb [ui] Add Sonner-like notification stack
MrJuneJune <me@mrjunejune.com>
parents: 252
diff changeset
78 - The idle stack layers older records behind the newest with depth and scale.
fdf3816959cb [ui] Add Sonner-like notification stack
MrJuneJune <me@mrjunejune.com>
parents: 252
diff changeset
79 - Hovering the stack or focusing an action expands all visible records using
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 253
diff changeset
80 their measured heights and first-party component code.
252
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
81 - Overflow evicts the oldest finite record; all-persistent queues reject new
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
82 records.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
83 - Queued records do not count down.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
84 - Finite timers pause while hovered, while focus remains inside, and while the
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
85 document is hidden.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
86 - Disconnecting clears records, timers, announcements, and internal DOM.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
87
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
88 ## Accessibility
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
89
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
90 - Polite and assertive announcements use separate persistent live regions.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
91 - Announcement priority is explicit and independent of tone.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
92 - Announcement messages are serialized so bursts remain observable.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
93 - Actions and dismissal use native buttons.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
94 - New notifications never move focus.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
95 - Keyed rendering preserves focused controls when unrelated records change.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
96 - Forced-colors and reduced-motion modes are supported by component CSS.
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
97
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
98 Events with `composed: true` are rejected. This keeps nested application scopes
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
99 isolated; adapters crossing a ShadowRoot must validate and redispatch a new
7a7581f040e8 [ui] Add scoped notification component
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
100 non-composed event deliberately.