@tempoxyz/ds 0.3.9 → 0.3.11
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/dist/docs/AGENTS.md +9 -0
- package/dist/docs/components/accordion.md +489 -0
- package/dist/docs/components/address-card.md +147 -0
- package/dist/docs/components/agent-logo.md +194 -0
- package/dist/docs/components/alert-dialog.md +631 -0
- package/dist/docs/components/alert.md +448 -0
- package/dist/docs/components/amount-input.md +305 -0
- package/dist/docs/components/amount.md +794 -0
- package/dist/docs/components/app-shell.md +559 -0
- package/dist/docs/components/asset-chip.md +294 -0
- package/dist/docs/components/autocomplete.md +619 -0
- package/dist/docs/components/avatar.md +321 -0
- package/dist/docs/components/badge.md +339 -0
- package/dist/docs/components/badged-logo.md +116 -0
- package/dist/docs/components/banner.md +379 -0
- package/dist/docs/components/bar-chart.md +208 -0
- package/dist/docs/components/breadcrumbs.md +380 -0
- package/dist/docs/components/button-group.md +286 -0
- package/dist/docs/components/button.md +650 -0
- package/dist/docs/components/calendar.md +375 -0
- package/dist/docs/components/callout.md +96 -0
- package/dist/docs/components/checkbox-group.md +521 -0
- package/dist/docs/components/checkbox.md +467 -0
- package/dist/docs/components/choice-group.md +516 -0
- package/dist/docs/components/choicebox.md +641 -0
- package/dist/docs/components/code.md +100 -0
- package/dist/docs/components/combobox.md +939 -0
- package/dist/docs/components/container.md +257 -0
- package/dist/docs/components/copy-button.md +642 -0
- package/dist/docs/components/date-picker.md +514 -0
- package/dist/docs/components/dialog.md +1332 -0
- package/dist/docs/components/drawer.md +966 -0
- package/dist/docs/components/empty.md +340 -0
- package/dist/docs/components/field.md +570 -0
- package/dist/docs/components/fieldset.md +398 -0
- package/dist/docs/components/frame.md +434 -0
- package/dist/docs/components/gauge.md +299 -0
- package/dist/docs/components/get-started-visual.md +117 -0
- package/dist/docs/components/grid.md +288 -0
- package/dist/docs/components/hero-visual.md +155 -0
- package/dist/docs/components/hex.md +487 -0
- package/dist/docs/components/icon-tile.md +292 -0
- package/dist/docs/components/identicon.md +371 -0
- package/dist/docs/components/inline.md +233 -0
- package/dist/docs/components/inset.md +225 -0
- package/dist/docs/components/kbd.md +423 -0
- package/dist/docs/components/list-group.md +981 -0
- package/dist/docs/components/loading-dots.md +237 -0
- package/dist/docs/components/menu.md +934 -0
- package/dist/docs/components/native-select.md +204 -0
- package/dist/docs/components/network-logo.md +248 -0
- package/dist/docs/components/number-field.md +543 -0
- package/dist/docs/components/otp-field.md +616 -0
- package/dist/docs/components/pagination.md +516 -0
- package/dist/docs/components/popover.md +544 -0
- package/dist/docs/components/progress.md +388 -0
- package/dist/docs/components/qr.md +314 -0
- package/dist/docs/components/radio-group.md +528 -0
- package/dist/docs/components/secret-value.md +406 -0
- package/dist/docs/components/select.md +751 -0
- package/dist/docs/components/separator.md +379 -0
- package/dist/docs/components/sidebar-menu.md +922 -0
- package/dist/docs/components/skeleton.md +517 -0
- package/dist/docs/components/slider.md +539 -0
- package/dist/docs/components/snippet.md +424 -0
- package/dist/docs/components/spinner.md +216 -0
- package/dist/docs/components/split-bar.md +139 -0
- package/dist/docs/components/split-button.md +464 -0
- package/dist/docs/components/stack.md +299 -0
- package/dist/docs/components/status-chip.md +226 -0
- package/dist/docs/components/status-indicator.md +119 -0
- package/dist/docs/components/status-row.md +174 -0
- package/dist/docs/components/stepper.md +451 -0
- package/dist/docs/components/success-hero.md +157 -0
- package/dist/docs/components/surface.md +639 -0
- package/dist/docs/components/switch.md +472 -0
- package/dist/docs/components/table.md +967 -0
- package/dist/docs/components/tabs.md +627 -0
- package/dist/docs/components/tempo-logo.md +185 -0
- package/dist/docs/components/text-input.md +624 -0
- package/dist/docs/components/textarea.md +352 -0
- package/dist/docs/components/toast.md +535 -0
- package/dist/docs/components/token-logo.md +371 -0
- package/dist/docs/components/token.md +247 -0
- package/dist/docs/components/tooltip.md +490 -0
- package/dist/docs/components/verification-code.md +116 -0
- package/dist/docs/components/visual.md +249 -0
- package/dist/docs/components.md +203 -0
- package/dist/docs/foundations/accessibility.md +377 -0
- package/dist/docs/foundations/agents.md +150 -0
- package/dist/docs/foundations/color.md +522 -0
- package/dist/docs/foundations/content/tone.md +194 -0
- package/dist/docs/foundations/content/voice.md +194 -0
- package/dist/docs/foundations/content/writing-style.md +406 -0
- package/dist/docs/foundations/iconography.md +282 -0
- package/dist/docs/foundations/intent.md +360 -0
- package/dist/docs/foundations/layout.md +508 -0
- package/dist/docs/foundations/linter.md +296 -0
- package/dist/docs/foundations/motion.md +151 -0
- package/dist/docs/foundations/radius-and-padding.md +86 -0
- package/dist/docs/foundations/typography.md +266 -0
- package/dist/docs/index.md +137 -0
- package/dist/docs/introduction/faq.md +132 -0
- package/dist/docs/introduction/getting-started.md +377 -0
- package/dist/docs/patterns/blockchain-values.md +709 -0
- package/dist/docs/patterns/dashboards.md +638 -0
- package/dist/docs/patterns/destructive-actions.md +626 -0
- package/dist/docs/patterns/empty-states.md +612 -0
- package/dist/docs/patterns/errors-and-validation.md +808 -0
- package/dist/docs/patterns/feedback-and-status.md +518 -0
- package/dist/docs/patterns/forms.md +679 -0
- package/dist/docs/patterns/loading.md +630 -0
- package/dist/docs/patterns/navigation.md +397 -0
- package/dist/docs/patterns/payments.md +765 -0
- package/dist/docs/patterns/responsive-layout.md +997 -0
- package/dist/docs/patterns/tables-and-lists.md +964 -0
- package/dist/docs/products/tempo-console.md +671 -0
- package/dist/docs/products/tempo-performance.md +437 -0
- package/dist/docs/products/tempo-wallet.md +438 -0
- package/dist/web/components/OtpField.css +1 -1
- package/dist/web/components/OtpField.d.ts +1 -1
- package/dist/web/components/OtpField.d.ts.map +1 -1
- package/dist/web/components/OtpField.js +3 -4
- package/dist/web/components/OtpField.js.map +1 -1
- package/dist/web/components/OtpField.js.zyzz.json +1 -1
- package/dist/web/index.js.zyzz.json +1 -1
- package/package.json +1 -1
- package/src/web/components/OtpField.tsx +2 -24
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
# Toast
|
|
2
|
+
|
|
3
|
+
Shows a brief notification that dismisses itself.
|
|
4
|
+
|
|
5
|
+
[View source and API](https://github.com/tempoxyz/ds/blob/main/src/web/components/Toast.tsx)
|
|
6
|
+
|
|
7
|
+
Figma: [Toast](https://www.figma.com/design/yE96kcymnNR88PJp6G1sPs?node-id=1186-3381) (`Toast.Item`)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Toasts are queued with a hook and render in a live region at the edge of the viewport.
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
### Basic
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { Button, Toast } from '@tempoxyz/ds'
|
|
19
|
+
|
|
20
|
+
function Trigger() {
|
|
21
|
+
const toast = Toast.useToast()
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Button
|
|
25
|
+
onClick={() =>
|
|
26
|
+
toast.add({ description: 'Transfers settle in seconds.', title: 'Payment sent' })
|
|
27
|
+
}
|
|
28
|
+
size="small"
|
|
29
|
+
variant="secondary"
|
|
30
|
+
>
|
|
31
|
+
Show toast
|
|
32
|
+
</Button>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function Demo() {
|
|
37
|
+
return (
|
|
38
|
+
<Toast.Provider>
|
|
39
|
+
<Trigger />
|
|
40
|
+
<Toast.Viewport />
|
|
41
|
+
</Toast.Provider>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Toast/Basic.tsx)
|
|
47
|
+
|
|
48
|
+
### Intent
|
|
49
|
+
|
|
50
|
+
Pass `intent` to `toast.add` as `neutral` (default), `info`, `positive`, `warning`, or `negative`.
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { Button, style, Toast } from '@tempoxyz/ds'
|
|
54
|
+
|
|
55
|
+
const intents = ['neutral', 'info', 'positive', 'warning', 'negative'] as const
|
|
56
|
+
|
|
57
|
+
function Triggers() {
|
|
58
|
+
const toast = Toast.useToast()
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div {...styles.row()}>
|
|
62
|
+
{intents.map((intent) => (
|
|
63
|
+
<Button
|
|
64
|
+
key={intent}
|
|
65
|
+
onClick={() =>
|
|
66
|
+
toast.add({
|
|
67
|
+
description: 'Transfers settle in seconds.',
|
|
68
|
+
intent,
|
|
69
|
+
title: `${intent} toast`,
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
size="small"
|
|
73
|
+
variant="secondary"
|
|
74
|
+
>
|
|
75
|
+
{intent}
|
|
76
|
+
</Button>
|
|
77
|
+
))}
|
|
78
|
+
</div>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function Demo() {
|
|
83
|
+
return (
|
|
84
|
+
<Toast.Provider>
|
|
85
|
+
<Triggers />
|
|
86
|
+
<Toast.Viewport />
|
|
87
|
+
</Toast.Provider>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
namespace styles {
|
|
92
|
+
export const row = style({ alignItems: 'center', display: 'flex', flexWrap: 'wrap', gap: '12' })
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Toast/Intent.tsx)
|
|
97
|
+
|
|
98
|
+
### Action
|
|
99
|
+
|
|
100
|
+
Pass an `action` with a `label` to add a button. Set `timeout: 0` to keep the toast open until dismissed.
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { Button, Toast } from '@tempoxyz/ds'
|
|
104
|
+
|
|
105
|
+
function Trigger() {
|
|
106
|
+
const toast = Toast.useToast()
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<Button
|
|
110
|
+
onClick={() =>
|
|
111
|
+
toast.add({
|
|
112
|
+
action: { label: 'Undo' },
|
|
113
|
+
intent: 'positive',
|
|
114
|
+
timeout: 0,
|
|
115
|
+
title: 'Archived',
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
size="small"
|
|
119
|
+
variant="secondary"
|
|
120
|
+
>
|
|
121
|
+
With action
|
|
122
|
+
</Button>
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function Demo() {
|
|
127
|
+
return (
|
|
128
|
+
<Toast.Provider>
|
|
129
|
+
<Trigger />
|
|
130
|
+
<Toast.Viewport />
|
|
131
|
+
</Toast.Provider>
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Toast/Action.tsx)
|
|
137
|
+
|
|
138
|
+
### Item
|
|
139
|
+
|
|
140
|
+
`Toast.Viewport` renders a `Toast.Item` for each queued toast. Render an item yourself only in a custom viewport under `Toast.Provider`, and pass it a toast object, whose `type` sets the intent.
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import { style, Toast } from '@tempoxyz/ds'
|
|
144
|
+
|
|
145
|
+
export function Demo() {
|
|
146
|
+
return (
|
|
147
|
+
<Toast.Provider>
|
|
148
|
+
<div {...styles.frame()}>
|
|
149
|
+
<Toast.Item
|
|
150
|
+
toast={{
|
|
151
|
+
description: 'Sent 25.00 USDC to Alice',
|
|
152
|
+
id: 'sent',
|
|
153
|
+
title: 'Payment sent',
|
|
154
|
+
type: 'positive',
|
|
155
|
+
}}
|
|
156
|
+
/>
|
|
157
|
+
</div>
|
|
158
|
+
</Toast.Provider>
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
namespace styles {
|
|
163
|
+
// The item sits at the bottom of its containing block, as the viewport places it.
|
|
164
|
+
export const frame = style({ height: '72', position: 'relative', width: '320' })
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
[View example source](https://github.com/tempoxyz/ds/blob/main/docs/src/examples/demos/Toast/Item.tsx)
|
|
169
|
+
|
|
170
|
+
## Anatomy
|
|
171
|
+
|
|
172
|
+
Import the component and assemble its parts.
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import { Toast } from '@tempoxyz/ds'
|
|
176
|
+
|
|
177
|
+
<Toast.Provider>
|
|
178
|
+
<Toast.Viewport />
|
|
179
|
+
<Toast.Item />
|
|
180
|
+
</Toast.Provider>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Guidelines
|
|
184
|
+
|
|
185
|
+
### When to Use
|
|
186
|
+
|
|
187
|
+
* Confirm that a user action finished, such as Payment sent or Webhook saved.
|
|
188
|
+
* Report a background event that needs no response, such as a deposit that arrived while the user was on another page.
|
|
189
|
+
* Offer a short Undo after a reversible action, such as Archived, when the same result is reachable elsewhere.
|
|
190
|
+
|
|
191
|
+
### When Not to Use
|
|
192
|
+
|
|
193
|
+
* Use an [Alert](/docs/components/alert) for an error or warning that must stay beside its content, such as a failed payment.
|
|
194
|
+
* Use a [Banner](/docs/components/banner) for a condition that affects the whole product, such as an outage.
|
|
195
|
+
* Use an [AlertDialog](/docs/components/alert-dialog) for a decision before an action continues.
|
|
196
|
+
* Use `Field.Error` from [Field](/docs/components/field) for validation messages on an input.
|
|
197
|
+
* Use `loading` on a [Button](/docs/components/button), or [Progress](/docs/components/progress), for work that still runs.
|
|
198
|
+
|
|
199
|
+
### Keep Required Actions Out of Toasts
|
|
200
|
+
|
|
201
|
+
A toast dismisses itself, and keyboard users must press F6 to reach it. Put required steps in the page or in an [AlertDialog](/docs/components/alert-dialog).
|
|
202
|
+
|
|
203
|
+
**Do:** Confirm a finished action and include the detail that identifies it.
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
/**
|
|
207
|
+
* Do example for "Keep Required Actions Out of Toasts" on the Toast page.
|
|
208
|
+
* Confirm a finished action and include the detail that identifies it.
|
|
209
|
+
* @module
|
|
210
|
+
*/
|
|
211
|
+
import { CheckCircle, Close } from '@tempoxyz/ds/icons'
|
|
212
|
+
import { style } from '@tempoxyz/ds'
|
|
213
|
+
|
|
214
|
+
// Toasts render in a portal, so this preview draws one in place with the toast's styles.
|
|
215
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
216
|
+
export function Demo() {
|
|
217
|
+
return (
|
|
218
|
+
<div {...styles.toast()}>
|
|
219
|
+
<CheckCircle {...styles.icon()} />
|
|
220
|
+
<div {...styles.body()}>
|
|
221
|
+
<div {...styles.title()}>Payment sent</div>
|
|
222
|
+
<div {...styles.description()}>50.00 USDC to 0x8f3c…a21b</div>
|
|
223
|
+
</div>
|
|
224
|
+
<Close {...styles.close()} />
|
|
225
|
+
</div>
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
namespace styles {
|
|
230
|
+
export const body = style({
|
|
231
|
+
display: 'flex',
|
|
232
|
+
flex: '1 !custom',
|
|
233
|
+
flexDirection: 'column',
|
|
234
|
+
minWidth: '0px !custom',
|
|
235
|
+
rowGap: '4',
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
export const close = style({ color: 'content.tertiary', flexShrink: '0 !custom', fontSize: '16' })
|
|
239
|
+
|
|
240
|
+
export const description = style({ color: 'content.secondary', typography: 'body.b2' })
|
|
241
|
+
|
|
242
|
+
export const icon = style({ color: 'content.positive', flexShrink: '0 !custom', fontSize: '20' })
|
|
243
|
+
|
|
244
|
+
export const title = style({ color: 'content.primary', typography: 'body.b2Strong' })
|
|
245
|
+
|
|
246
|
+
export const toast = style({
|
|
247
|
+
alignItems: 'center',
|
|
248
|
+
backgroundColor: 'background.elevated',
|
|
249
|
+
borderRadius: 'sm',
|
|
250
|
+
boxShadow: 'regular',
|
|
251
|
+
boxSizing: 'border-box',
|
|
252
|
+
columnGap: '12',
|
|
253
|
+
display: 'flex',
|
|
254
|
+
paddingBlock: '16',
|
|
255
|
+
paddingInline: '20',
|
|
256
|
+
width: '100% !custom',
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Don't:** Ask for a confirmation or another required step in a toast.
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
/**
|
|
265
|
+
* Don't example for "Keep Required Actions Out of Toasts" on the Toast page.
|
|
266
|
+
* Don't ask for a confirmation or another required step in a toast.
|
|
267
|
+
* @module
|
|
268
|
+
*/
|
|
269
|
+
import { AlertTriangle, Close } from '@tempoxyz/ds/icons'
|
|
270
|
+
import { style } from '@tempoxyz/ds'
|
|
271
|
+
|
|
272
|
+
// Toasts render in a portal, so this preview draws one in place with the toast's styles.
|
|
273
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
274
|
+
export function Demo() {
|
|
275
|
+
return (
|
|
276
|
+
<div {...styles.toast()}>
|
|
277
|
+
<AlertTriangle {...styles.icon()} />
|
|
278
|
+
<div {...styles.body()}>
|
|
279
|
+
<div {...styles.title()}>Confirm payment</div>
|
|
280
|
+
<div {...styles.description()}>50.00 USDC to 0x8f3c…a21b</div>
|
|
281
|
+
</div>
|
|
282
|
+
<span {...styles.action()}>Confirm</span>
|
|
283
|
+
<Close {...styles.close()} />
|
|
284
|
+
</div>
|
|
285
|
+
)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
namespace styles {
|
|
289
|
+
export const action = style({
|
|
290
|
+
alignItems: 'center',
|
|
291
|
+
backgroundColor: 'container.regular',
|
|
292
|
+
borderRadius: 'full',
|
|
293
|
+
color: 'content.primary',
|
|
294
|
+
cornerShape: 'round',
|
|
295
|
+
display: 'inline-flex',
|
|
296
|
+
flexShrink: '0 !custom',
|
|
297
|
+
height: '32',
|
|
298
|
+
paddingInline: '12',
|
|
299
|
+
typography: 'body.b3Strong',
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
export const body = style({
|
|
303
|
+
display: 'flex',
|
|
304
|
+
flex: '1 !custom',
|
|
305
|
+
flexDirection: 'column',
|
|
306
|
+
minWidth: '0px !custom',
|
|
307
|
+
rowGap: '4',
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
export const close = style({ color: 'content.tertiary', flexShrink: '0 !custom', fontSize: '16' })
|
|
311
|
+
|
|
312
|
+
export const description = style({ color: 'content.secondary', typography: 'body.b2' })
|
|
313
|
+
|
|
314
|
+
export const icon = style({ color: 'content.warning', flexShrink: '0 !custom', fontSize: '20' })
|
|
315
|
+
|
|
316
|
+
export const title = style({ color: 'content.primary', typography: 'body.b2Strong' })
|
|
317
|
+
|
|
318
|
+
export const toast = style({
|
|
319
|
+
alignItems: 'center',
|
|
320
|
+
backgroundColor: 'background.elevated',
|
|
321
|
+
borderRadius: 'sm',
|
|
322
|
+
boxShadow: 'regular',
|
|
323
|
+
boxSizing: 'border-box',
|
|
324
|
+
columnGap: '12',
|
|
325
|
+
display: 'flex',
|
|
326
|
+
paddingBlock: '16',
|
|
327
|
+
paddingInline: '20',
|
|
328
|
+
width: '100% !custom',
|
|
329
|
+
})
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
An Undo action is fine if the page also reverses the change, such as an Archive tab that restores an archived key.
|
|
334
|
+
|
|
335
|
+
### Choose an Intent
|
|
336
|
+
|
|
337
|
+
* **Neutral (neutral):** The default, with no icon. Updates with no outcome to judge, such as Signed out.
|
|
338
|
+
* **Info (info):** Events the user didn't start, such as a deposit that arrived.
|
|
339
|
+
* **Positive (positive):** An action that succeeded, such as a confirmation that reads Payment sent.
|
|
340
|
+
* **Warning (warning):** An action that finished with a caveat, such as a test delivery that timed out.
|
|
341
|
+
* **Negative (negative):** A non-critical action that failed and that the user can try again.
|
|
342
|
+
|
|
343
|
+
### Set Duration by Content
|
|
344
|
+
|
|
345
|
+
* **Short Content (5 seconds):** The default, for a title and a short description.
|
|
346
|
+
* **Longer Description (timeout):** Raise `timeout`, or set it app-wide on `Toast.Provider`.
|
|
347
|
+
* **Action (timeout: 0):** Keeps the toast open until dismissed ([SC 2.2.1](https://www.w3.org/WAI/WCAG22/Understanding/timing-adjustable.html)).
|
|
348
|
+
|
|
349
|
+
### Send One Toast per Outcome
|
|
350
|
+
|
|
351
|
+
`Toast.Provider` shows up to three toasts by default, and hides older ones past its `limit`. Combine related results into one toast.
|
|
352
|
+
|
|
353
|
+
**Do:** Combine related results into one toast, such as 3 payments sent.
|
|
354
|
+
|
|
355
|
+
```tsx
|
|
356
|
+
/**
|
|
357
|
+
* Do example for "Send One Toast per Outcome" on the Toast page.
|
|
358
|
+
* Combine related results into one toast, such as 3 payments sent.
|
|
359
|
+
* @module
|
|
360
|
+
*/
|
|
361
|
+
import { CheckCircle, Close } from '@tempoxyz/ds/icons'
|
|
362
|
+
import { style } from '@tempoxyz/ds'
|
|
363
|
+
|
|
364
|
+
// Toasts render in a portal, so this preview draws one in place with the toast's styles.
|
|
365
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
366
|
+
export function Demo() {
|
|
367
|
+
return (
|
|
368
|
+
<div {...styles.toast()}>
|
|
369
|
+
<CheckCircle {...styles.icon()} />
|
|
370
|
+
<div {...styles.body()}>
|
|
371
|
+
<div {...styles.title()}>3 payments sent</div>
|
|
372
|
+
<div {...styles.description()}>150.00 USDC to 3 recipients</div>
|
|
373
|
+
</div>
|
|
374
|
+
<Close {...styles.close()} />
|
|
375
|
+
</div>
|
|
376
|
+
)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
namespace styles {
|
|
380
|
+
export const body = style({
|
|
381
|
+
display: 'flex',
|
|
382
|
+
flex: '1 !custom',
|
|
383
|
+
flexDirection: 'column',
|
|
384
|
+
minWidth: '0px !custom',
|
|
385
|
+
rowGap: '4',
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
export const close = style({ color: 'content.tertiary', flexShrink: '0 !custom', fontSize: '16' })
|
|
389
|
+
|
|
390
|
+
export const description = style({ color: 'content.secondary', typography: 'body.b2' })
|
|
391
|
+
|
|
392
|
+
export const icon = style({ color: 'content.positive', flexShrink: '0 !custom', fontSize: '20' })
|
|
393
|
+
|
|
394
|
+
export const title = style({ color: 'content.primary', typography: 'body.b2Strong' })
|
|
395
|
+
|
|
396
|
+
export const toast = style({
|
|
397
|
+
alignItems: 'center',
|
|
398
|
+
backgroundColor: 'background.elevated',
|
|
399
|
+
borderRadius: 'sm',
|
|
400
|
+
boxShadow: 'regular',
|
|
401
|
+
boxSizing: 'border-box',
|
|
402
|
+
columnGap: '12',
|
|
403
|
+
display: 'flex',
|
|
404
|
+
paddingBlock: '16',
|
|
405
|
+
paddingInline: '20',
|
|
406
|
+
width: '100% !custom',
|
|
407
|
+
})
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**Don't:** Send a separate toast for each result of one action.
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
/**
|
|
415
|
+
* Don't example for "Send One Toast per Outcome" on the Toast page.
|
|
416
|
+
* Don't send a separate toast for each result of one action.
|
|
417
|
+
* @module
|
|
418
|
+
*/
|
|
419
|
+
import { CheckCircle, Close } from '@tempoxyz/ds/icons'
|
|
420
|
+
import { style } from '@tempoxyz/ds'
|
|
421
|
+
|
|
422
|
+
const payments = ['0x8f3c…a21b', '0x41d0…9c7e', '0xb27a…04f5']
|
|
423
|
+
|
|
424
|
+
// Toasts render in a portal, so this preview draws them in place with the toast's styles.
|
|
425
|
+
/** Renders the static preview, which the guideline card shows inert. */
|
|
426
|
+
export function Demo() {
|
|
427
|
+
return (
|
|
428
|
+
<div {...styles.stack()}>
|
|
429
|
+
{payments.map((address) => (
|
|
430
|
+
<div key={address} {...styles.toast()}>
|
|
431
|
+
<CheckCircle {...styles.icon()} />
|
|
432
|
+
<div {...styles.body()}>
|
|
433
|
+
<div {...styles.title()}>Payment sent</div>
|
|
434
|
+
<div {...styles.description()}>50.00 USDC to {address}</div>
|
|
435
|
+
</div>
|
|
436
|
+
<Close {...styles.close()} />
|
|
437
|
+
</div>
|
|
438
|
+
))}
|
|
439
|
+
</div>
|
|
440
|
+
)
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
namespace styles {
|
|
444
|
+
export const body = style({
|
|
445
|
+
display: 'flex',
|
|
446
|
+
flex: '1 !custom',
|
|
447
|
+
flexDirection: 'column',
|
|
448
|
+
minWidth: '0px !custom',
|
|
449
|
+
rowGap: '4',
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
export const close = style({ color: 'content.tertiary', flexShrink: '0 !custom', fontSize: '16' })
|
|
453
|
+
|
|
454
|
+
export const description = style({ color: 'content.secondary', typography: 'body.b2' })
|
|
455
|
+
|
|
456
|
+
export const icon = style({ color: 'content.positive', flexShrink: '0 !custom', fontSize: '20' })
|
|
457
|
+
|
|
458
|
+
export const stack = style({
|
|
459
|
+
display: 'flex',
|
|
460
|
+
flexDirection: 'column',
|
|
461
|
+
gap: '8',
|
|
462
|
+
width: '100% !custom',
|
|
463
|
+
})
|
|
464
|
+
|
|
465
|
+
export const title = style({ color: 'content.primary', typography: 'body.b2Strong' })
|
|
466
|
+
|
|
467
|
+
export const toast = style({
|
|
468
|
+
alignItems: 'center',
|
|
469
|
+
backgroundColor: 'background.elevated',
|
|
470
|
+
borderRadius: 'sm',
|
|
471
|
+
boxShadow: 'regular',
|
|
472
|
+
boxSizing: 'border-box',
|
|
473
|
+
columnGap: '12',
|
|
474
|
+
display: 'flex',
|
|
475
|
+
paddingBlock: '16',
|
|
476
|
+
paddingInline: '20',
|
|
477
|
+
width: '100% !custom',
|
|
478
|
+
})
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Content
|
|
483
|
+
|
|
484
|
+
* Write the title as the result in a few words, usually past tense: Payment sent, Key revoked, Webhook saved.
|
|
485
|
+
* Add a description only for the detail that identifies the action, such as 50.00 USDC to 0x8f3c…a21b.
|
|
486
|
+
* Leave out exclamation marks and filler such as Success or Done.
|
|
487
|
+
* Label the action with one verb, such as Undo or Retry.
|
|
488
|
+
|
|
489
|
+
## Accessibility
|
|
490
|
+
|
|
491
|
+
Toasts never take focus on their own. Don't move focus to a new toast yourself.
|
|
492
|
+
|
|
493
|
+
### Semantics
|
|
494
|
+
|
|
495
|
+
* **Toast.Viewport (region):** A landmark named "Notifications". Announces new toasts without moving focus.
|
|
496
|
+
* **Toast (dialog):** A non-modal dialog, named by its title and described by its description.
|
|
497
|
+
* **High Priority (alertdialog):** With `priority: 'high'`, a separate alert interrupts current speech. Intent alone never does.
|
|
498
|
+
* **Action and Dismiss (button):** The action is named by `action.label`. Every toast also has a Dismiss button.
|
|
499
|
+
* **Intent Icon (aria-hidden):** Hidden from assistive technology, so the title must carry the outcome.
|
|
500
|
+
|
|
501
|
+
### Keyboard
|
|
502
|
+
|
|
503
|
+
* **Reach the Viewport (F6):** Moves focus to the toast viewport from anywhere on the page.
|
|
504
|
+
* **Move Through the Toast (Tab):** Moves focus to the newest toast, then to its action and Dismiss button.
|
|
505
|
+
* **Move Back (Shift+Tab):** Moves focus back. From the viewport, returns focus to where it was before F6.
|
|
506
|
+
* **Activate a Button (Enter or Space):** Activates the action or the Dismiss button that holds focus.
|
|
507
|
+
* **Dismiss the Toast (Escape):** Dismisses the toast that holds focus, the same as its Dismiss button.
|
|
508
|
+
|
|
509
|
+
### Dismissal
|
|
510
|
+
|
|
511
|
+
* **Pausing:** Hover or focus in the viewport pauses all dismiss timers, as does a background window.
|
|
512
|
+
* **Swiping:** On touch screens, a swipe down or to the right dismisses a toast.
|
|
513
|
+
|
|
514
|
+
### Your Responsibilities
|
|
515
|
+
|
|
516
|
+
* **Reserve High Priority (priority: 'high'):** Use it only for urgent messages. Show critical errors inline or in a [Dialog](/docs/components/dialog).
|
|
517
|
+
* **Render One Viewport (F6):** Render one viewport per app, so the shortcut always reaches it.
|
|
518
|
+
|
|
519
|
+
## Related
|
|
520
|
+
|
|
521
|
+
[Alert](/docs/components/alert)
|
|
522
|
+
|
|
523
|
+
Use for messages that stay beside their content.
|
|
524
|
+
|
|
525
|
+
[Banner](/docs/components/banner)
|
|
526
|
+
|
|
527
|
+
Use for messages about the whole product.
|
|
528
|
+
|
|
529
|
+
[AlertDialog](/docs/components/alert-dialog)
|
|
530
|
+
|
|
531
|
+
Use for decisions before an action continues.
|
|
532
|
+
|
|
533
|
+
[Feedback and Status](/docs/patterns/feedback-and-status)
|
|
534
|
+
|
|
535
|
+
Covers choosing a message component.
|