Mercurial
annotate design_system/NOTIFICATIONS.md @ 272:41a49c29a28f
polish JRPG conversation experience
Integrate desktop conversations into the utility panel, simplify the mobile frame, add modal destinations and a reusable Zenbu composer lab, and preserve explicit conversation resume behavior.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 07 Aug 2026 16:05:29 -0700 |
| parents | 60a876c4587a |
| children |
| 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. |