@opentui-ui/toast 0.0.1
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/README.md +660 -0
- package/dist/icons-DXx_5j_z.mjs +181 -0
- package/dist/icons-DXx_5j_z.mjs.map +1 -0
- package/dist/icons.d.mts +116 -0
- package/dist/icons.d.mts.map +1 -0
- package/dist/icons.mjs +3 -0
- package/dist/index.d.mts +53 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +4 -0
- package/dist/react.d.mts +13 -0
- package/dist/react.d.mts.map +1 -0
- package/dist/react.mjs +14 -0
- package/dist/react.mjs.map +1 -0
- package/dist/state-CoqnQZsz.d.mts +157 -0
- package/dist/state-CoqnQZsz.d.mts.map +1 -0
- package/dist/themes.d.mts +69 -0
- package/dist/themes.d.mts.map +1 -0
- package/dist/themes.mjs +118 -0
- package/dist/themes.mjs.map +1 -0
- package/dist/toaster-CQ5RySDh.mjs +1118 -0
- package/dist/toaster-CQ5RySDh.mjs.map +1 -0
- package/dist/types-BnTc6iEw.d.mts +342 -0
- package/dist/types-BnTc6iEw.d.mts.map +1 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img width="512" src="https://github.com/user-attachments/assets/ab2088f4-167b-4290-aeed-03cd8e1750d9" />
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
<br />
|
|
6
|
+
|
|
7
|
+
<div align="center"><strong>A beautiful toast library for terminal UIs built on OpenTUI</strong></div>
|
|
8
|
+
<div align="center">
|
|
9
|
+
<sub>Built by <a href="https://x.com/msmps_">Matt Simpson</a> | Inspired by <a href="https://sonner.emilkowal.ski/">Sonner</a></sub>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<br />
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bun add @opentui-ui/toast
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { toast, ToasterRenderable } from "@opentui-ui/toast";
|
|
24
|
+
|
|
25
|
+
// 1. Add the toaster to your app (one line!)
|
|
26
|
+
ctx.root.add(new ToasterRenderable(ctx));
|
|
27
|
+
|
|
28
|
+
// 2. Show toasts from anywhere!
|
|
29
|
+
toast("Hello World");
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
That's it! No providers, no context, no configuration required.
|
|
33
|
+
|
|
34
|
+
## Quick Reference
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// Toast Types
|
|
38
|
+
toast("message"); // default
|
|
39
|
+
toast.success("message"); // green checkmark
|
|
40
|
+
toast.error("message"); // red X
|
|
41
|
+
toast.warning("message"); // yellow warning
|
|
42
|
+
toast.info("message"); // blue info
|
|
43
|
+
toast.loading("message"); // animated spinner
|
|
44
|
+
|
|
45
|
+
// Common Patterns
|
|
46
|
+
toast("msg", { description: "details" }); // Two-line toast
|
|
47
|
+
toast("msg", { duration: Infinity }); // Persistent (manual dismiss)
|
|
48
|
+
toast("msg", { action: { label: "Undo", onClick: fn } }); // With button
|
|
49
|
+
|
|
50
|
+
// Dismiss
|
|
51
|
+
const id = toast("Hello");
|
|
52
|
+
toast.dismiss(id); // Dismiss one
|
|
53
|
+
toast.dismiss(); // Dismiss all
|
|
54
|
+
|
|
55
|
+
// Update existing toast
|
|
56
|
+
const id = toast.loading("Uploading...");
|
|
57
|
+
toast.success("Done!", { id }); // Updates in place
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Toast Types
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
toast("Default notification");
|
|
64
|
+
toast.success("Operation completed!");
|
|
65
|
+
toast.error("Something went wrong");
|
|
66
|
+
toast.warning("Please check your input");
|
|
67
|
+
toast.info("Did you know?");
|
|
68
|
+
toast.loading("Processing...");
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## With Descriptions
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
toast.success("File uploaded", {
|
|
75
|
+
description: "Your file has been saved to the cloud",
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Promise Toast
|
|
80
|
+
|
|
81
|
+
The `toast.promise()` API automatically shows loading, success, and error states:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
toast.promise(fetchData(), {
|
|
85
|
+
loading: "Fetching data...",
|
|
86
|
+
success: "Data loaded successfully!",
|
|
87
|
+
error: "Failed to load data",
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// With dynamic messages
|
|
91
|
+
toast.promise(saveUser(data), {
|
|
92
|
+
loading: "Saving user...",
|
|
93
|
+
success: (user) => `${user.name} has been saved`,
|
|
94
|
+
error: (err) => `Error: ${err.message}`,
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Actions
|
|
99
|
+
|
|
100
|
+
Add interactive buttons to your toasts:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
toast("File deleted", {
|
|
104
|
+
action: {
|
|
105
|
+
label: "Undo",
|
|
106
|
+
onClick: () => restoreFile(),
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Updating Toasts
|
|
112
|
+
|
|
113
|
+
Update an existing toast by passing its ID:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
const id = toast.loading("Uploading...");
|
|
117
|
+
|
|
118
|
+
// Later...
|
|
119
|
+
toast.success("Upload complete!", { id });
|
|
120
|
+
|
|
121
|
+
// Or on error
|
|
122
|
+
toast.error("Upload failed", { id });
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Dismissing Toasts
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
// Dismiss a specific toast
|
|
129
|
+
const id = toast("Hello");
|
|
130
|
+
toast.dismiss(id);
|
|
131
|
+
|
|
132
|
+
// Dismiss all toasts
|
|
133
|
+
toast.dismiss();
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Duration
|
|
137
|
+
|
|
138
|
+
### Duration Presets
|
|
139
|
+
|
|
140
|
+
Use the built-in `TOAST_DURATION` presets for consistent, readable duration values:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
import { toast, TOAST_DURATION } from "@opentui-ui/toast";
|
|
144
|
+
|
|
145
|
+
// Quick confirmation (2s)
|
|
146
|
+
toast.success("Copied!", { duration: TOAST_DURATION.SHORT });
|
|
147
|
+
|
|
148
|
+
// Standard duration (4s) - this is the default
|
|
149
|
+
toast("Hello", { duration: TOAST_DURATION.DEFAULT });
|
|
150
|
+
|
|
151
|
+
// Important message (6s)
|
|
152
|
+
toast.warning("Check your settings", { duration: TOAST_DURATION.LONG });
|
|
153
|
+
|
|
154
|
+
// Critical information (10s)
|
|
155
|
+
toast.error("Connection lost", { duration: TOAST_DURATION.EXTENDED });
|
|
156
|
+
|
|
157
|
+
// Manual dismiss only
|
|
158
|
+
toast.info("Click to continue", { duration: TOAST_DURATION.PERSISTENT });
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Duration Preset Values
|
|
162
|
+
|
|
163
|
+
| Preset | Duration | Use Case |
|
|
164
|
+
| ------------ | -------- | ------------------------- |
|
|
165
|
+
| `SHORT` | 2000ms | Brief confirmations |
|
|
166
|
+
| `DEFAULT` | 4000ms | Standard notifications |
|
|
167
|
+
| `LONG` | 6000ms | Important messages |
|
|
168
|
+
| `EXTENDED` | 10000ms | Critical information |
|
|
169
|
+
| `PERSISTENT` | Infinity | Requires manual dismissal |
|
|
170
|
+
|
|
171
|
+
### Custom Duration
|
|
172
|
+
|
|
173
|
+
You can also pass any number in milliseconds:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
// Custom duration (in milliseconds)
|
|
177
|
+
toast("This disappears in 10 seconds", {
|
|
178
|
+
duration: 10000,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Persistent toast (won't auto-dismiss)
|
|
182
|
+
toast("I'll stay until dismissed", {
|
|
183
|
+
duration: Infinity,
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Themes
|
|
188
|
+
|
|
189
|
+
Optional theme presets are available via a separate import. These override the built-in defaults with alternative visual styles.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { ToasterRenderable } from "@opentui-ui/toast";
|
|
193
|
+
import { minimal } from "@opentui-ui/toast/themes";
|
|
194
|
+
|
|
195
|
+
const toaster = new ToasterRenderable(ctx, minimal);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Available Themes
|
|
199
|
+
|
|
200
|
+
| Theme | Description |
|
|
201
|
+
| ------------ | --------------------------------- |
|
|
202
|
+
| `minimal` | Clean and unobtrusive, no borders |
|
|
203
|
+
| `monochrome` | Grayscale only, no colors |
|
|
204
|
+
|
|
205
|
+
### Customizing Themes
|
|
206
|
+
|
|
207
|
+
Spread a theme and override specific options:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
import { minimal } from "@opentui-ui/toast/themes";
|
|
211
|
+
|
|
212
|
+
const toaster = new ToasterRenderable(ctx, {
|
|
213
|
+
...minimal,
|
|
214
|
+
position: "bottom-right",
|
|
215
|
+
stackingMode: "stack",
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Theme Utilities
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
import { themes } from "@opentui-ui/toast/themes";
|
|
223
|
+
|
|
224
|
+
// Access all themes
|
|
225
|
+
themes.minimal;
|
|
226
|
+
themes.monochrome;
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Theme Types
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
import type { ToasterTheme } from "@opentui-ui/toast/themes";
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Toaster Configuration
|
|
236
|
+
|
|
237
|
+
Customize the toaster appearance and behavior:
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
const toaster = new ToasterRenderable(ctx, {
|
|
241
|
+
// Position on screen
|
|
242
|
+
position: "bottom-right", // 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'
|
|
243
|
+
|
|
244
|
+
// Gap between toasts (terminal rows)
|
|
245
|
+
gap: 1,
|
|
246
|
+
|
|
247
|
+
// How to handle multiple toasts
|
|
248
|
+
stackingMode: "single", // 'single' | 'stack'
|
|
249
|
+
|
|
250
|
+
// Max visible toasts in stack mode
|
|
251
|
+
visibleToasts: 3,
|
|
252
|
+
|
|
253
|
+
// Show close button on toasts
|
|
254
|
+
closeButton: false,
|
|
255
|
+
|
|
256
|
+
// Maximum width for toasts
|
|
257
|
+
maxWidth: 60,
|
|
258
|
+
|
|
259
|
+
// Offset from screen edges
|
|
260
|
+
offset: {
|
|
261
|
+
top: 1,
|
|
262
|
+
right: 2,
|
|
263
|
+
bottom: 1,
|
|
264
|
+
left: 2,
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
// Custom icons
|
|
268
|
+
icons: {
|
|
269
|
+
success: "✓",
|
|
270
|
+
error: "✗",
|
|
271
|
+
warning: "⚠",
|
|
272
|
+
info: "ℹ",
|
|
273
|
+
loading: "◌",
|
|
274
|
+
close: "×",
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
// Toast styling and duration options
|
|
278
|
+
toastOptions: {
|
|
279
|
+
style: {
|
|
280
|
+
/* base styles */
|
|
281
|
+
},
|
|
282
|
+
duration: 4000,
|
|
283
|
+
success: {
|
|
284
|
+
style: {
|
|
285
|
+
/* overrides */
|
|
286
|
+
},
|
|
287
|
+
duration: 3000,
|
|
288
|
+
},
|
|
289
|
+
// ... other types
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### ToasterOptions Reference
|
|
295
|
+
|
|
296
|
+
| Option | Type | Default | Description |
|
|
297
|
+
| --------------- | ------------------------------ | ------------------------------------------ | ------------------------------------------------------------ |
|
|
298
|
+
| `position` | `Position` | `"bottom-right"` | Position on screen |
|
|
299
|
+
| `gap` | `number` | `1` | Gap between toasts (terminal rows) |
|
|
300
|
+
| `stackingMode` | `StackingMode` | `"single"` | How to handle multiple toasts: `"single"` or `"stack"` |
|
|
301
|
+
| `visibleToasts` | `number` | `3` | Max visible toasts in stack mode |
|
|
302
|
+
| `closeButton` | `boolean` | `false` | Show close button on toasts |
|
|
303
|
+
| `maxWidth` | `number` | `60` | Maximum width for toasts (terminal columns) |
|
|
304
|
+
| `offset` | `ToasterOffset` | `{ top: 1, right: 2, bottom: 1, left: 2 }` | Offset from screen edges |
|
|
305
|
+
| `icons` | `Partial<ToastIcons> \| false` | - | Custom icons for each toast type, or `false` to disable |
|
|
306
|
+
| `toastOptions` | `ToastOptions` | - | Default toast options (styles, duration, per-type overrides) |
|
|
307
|
+
|
|
308
|
+
## Styling
|
|
309
|
+
|
|
310
|
+
Configure toast styles using the `toastOptions` prop:
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
const toaster = new ToasterRenderable(ctx, {
|
|
314
|
+
toastOptions: {
|
|
315
|
+
// Base styles applied to all toasts
|
|
316
|
+
style: {
|
|
317
|
+
backgroundColor: "#1a1a1a",
|
|
318
|
+
foregroundColor: "#ffffff",
|
|
319
|
+
borderColor: "#333333",
|
|
320
|
+
borderStyle: "rounded", // 'single' | 'double' | 'rounded' | 'heavy'
|
|
321
|
+
paddingX: 1,
|
|
322
|
+
paddingY: 0,
|
|
323
|
+
},
|
|
324
|
+
// Default duration for all toasts
|
|
325
|
+
duration: 4000,
|
|
326
|
+
// Per-type overrides
|
|
327
|
+
success: {
|
|
328
|
+
style: { borderColor: "#22c55e" },
|
|
329
|
+
duration: 3000,
|
|
330
|
+
},
|
|
331
|
+
error: {
|
|
332
|
+
style: { borderColor: "#ef4444" },
|
|
333
|
+
duration: 6000,
|
|
334
|
+
},
|
|
335
|
+
warning: {
|
|
336
|
+
style: { borderColor: "#f59e0b" },
|
|
337
|
+
},
|
|
338
|
+
info: {
|
|
339
|
+
style: { borderColor: "#3b82f6" },
|
|
340
|
+
},
|
|
341
|
+
loading: {
|
|
342
|
+
style: { borderColor: "#6b7280" },
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### ToastStyle Reference
|
|
349
|
+
|
|
350
|
+
| Property | Type | Default | Description |
|
|
351
|
+
| ------------------- | -------------------------- | ----------- | ------------------------------------------------------------------------------------------- |
|
|
352
|
+
| `border` | `boolean \| BorderSides[]` | `true` | Border configuration. `true` = all sides, `false` = none, or array like `["left", "right"]` |
|
|
353
|
+
| `borderColor` | `string` | `"#333333"` | Border color (hex, rgb, or named) |
|
|
354
|
+
| `borderStyle` | `BorderStyle` | `"single"` | Border style: `"single"` \| `"double"` \| `"rounded"` \| `"heavy"` |
|
|
355
|
+
| `customBorderChars` | `BorderCharacters` | - | Custom border characters (overrides `borderStyle`) |
|
|
356
|
+
| `minHeight` | `number` | `3` | Minimum height in terminal rows |
|
|
357
|
+
| `maxWidth` | `number` | - | Maximum width in terminal columns |
|
|
358
|
+
| `minWidth` | `number` | - | Minimum width in terminal columns |
|
|
359
|
+
| `padding` | `number` | - | Uniform padding (all sides) |
|
|
360
|
+
| `paddingX` | `number` | `1` | Horizontal padding (left + right) |
|
|
361
|
+
| `paddingY` | `number` | `0` | Vertical padding (top + bottom) |
|
|
362
|
+
| `paddingTop` | `number` | - | Top padding |
|
|
363
|
+
| `paddingBottom` | `number` | - | Bottom padding |
|
|
364
|
+
| `paddingLeft` | `number` | - | Left padding |
|
|
365
|
+
| `paddingRight` | `number` | - | Right padding |
|
|
366
|
+
| `backgroundColor` | `string` | `"#1a1a1a"` | Background color |
|
|
367
|
+
| `foregroundColor` | `string` | `"#ffffff"` | Text/foreground color |
|
|
368
|
+
| `mutedColor` | `string` | `"#6b7280"` | Muted text color (for descriptions) |
|
|
369
|
+
| `iconColor` | `string` | - | Icon color (defaults to `borderColor`) |
|
|
370
|
+
|
|
371
|
+
### Custom Border Characters
|
|
372
|
+
|
|
373
|
+
For full control over border rendering, use `customBorderChars` to define each border character:
|
|
374
|
+
|
|
375
|
+
```ts
|
|
376
|
+
const toaster = new ToasterRenderable(ctx, {
|
|
377
|
+
toastOptions: {
|
|
378
|
+
style: {
|
|
379
|
+
border: ["left", "right"],
|
|
380
|
+
customBorderChars: {
|
|
381
|
+
topLeft: "",
|
|
382
|
+
topRight: "",
|
|
383
|
+
bottomLeft: "",
|
|
384
|
+
bottomRight: "",
|
|
385
|
+
horizontal: " ",
|
|
386
|
+
vertical: "┃",
|
|
387
|
+
topT: "",
|
|
388
|
+
bottomT: "",
|
|
389
|
+
leftT: "",
|
|
390
|
+
rightT: "",
|
|
391
|
+
cross: "",
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
This is useful for creating unique border styles, like a vertical bar accent:
|
|
399
|
+
|
|
400
|
+
```ts
|
|
401
|
+
// Vertical bar on left and right only
|
|
402
|
+
border: ["left", "right"],
|
|
403
|
+
customBorderChars: {
|
|
404
|
+
vertical: "┃",
|
|
405
|
+
// Other characters can be empty strings
|
|
406
|
+
topLeft: "", topRight: "", bottomLeft: "", bottomRight: "",
|
|
407
|
+
horizontal: " ", topT: "", bottomT: "", leftT: "", rightT: "", cross: "",
|
|
408
|
+
},
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Per-Toast Styles
|
|
412
|
+
|
|
413
|
+
Override styles on individual toasts:
|
|
414
|
+
|
|
415
|
+
```ts
|
|
416
|
+
toast.success("Custom styled!", {
|
|
417
|
+
style: {
|
|
418
|
+
borderColor: "#8b5cf6",
|
|
419
|
+
backgroundColor: "#1e1b4b",
|
|
420
|
+
},
|
|
421
|
+
});
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Icon Sets
|
|
425
|
+
|
|
426
|
+
Choose from built-in icon sets based on terminal capabilities:
|
|
427
|
+
|
|
428
|
+
```ts
|
|
429
|
+
import {
|
|
430
|
+
DEFAULT_ICONS, // Unicode icons (default)
|
|
431
|
+
ASCII_ICONS, // ASCII-only for limited terminals
|
|
432
|
+
MINIMAL_ICONS, // Single character icons
|
|
433
|
+
EMOJI_ICONS, // Emoji icons
|
|
434
|
+
} from "@opentui-ui/toast";
|
|
435
|
+
|
|
436
|
+
// Use ASCII icons for terminals with limited Unicode support
|
|
437
|
+
const toaster = new ToasterRenderable(ctx, {
|
|
438
|
+
icons: ASCII_ICONS,
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// Use emoji icons for terminals with good emoji support
|
|
442
|
+
const toaster = new ToasterRenderable(ctx, {
|
|
443
|
+
icons: EMOJI_ICONS,
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Custom Loading Spinner
|
|
448
|
+
|
|
449
|
+
The `loading` icon can be either a static string or an animated spinner configuration:
|
|
450
|
+
|
|
451
|
+
```ts
|
|
452
|
+
const toaster = new ToasterRenderable(ctx, {
|
|
453
|
+
icons: {
|
|
454
|
+
// Static loading icon (no animation)
|
|
455
|
+
loading: "...",
|
|
456
|
+
|
|
457
|
+
// Or animated spinner
|
|
458
|
+
loading: {
|
|
459
|
+
frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
|
|
460
|
+
interval: 80,
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
});
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Some spinner examples:
|
|
467
|
+
|
|
468
|
+
```ts
|
|
469
|
+
// Dots spinner
|
|
470
|
+
{ frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"], interval: 80 }
|
|
471
|
+
|
|
472
|
+
// Circle spinner (default)
|
|
473
|
+
{ frames: ["◜", "◠", "◝", "◞", "◡", "◟"], interval: 100 }
|
|
474
|
+
|
|
475
|
+
// Simple ASCII spinner
|
|
476
|
+
{ frames: ["-", "\\", "|", "/"], interval: 100 }
|
|
477
|
+
|
|
478
|
+
// Bouncing bar
|
|
479
|
+
{ frames: ["[ ]", "[= ]", "[== ]", "[=== ]", "[ ===]", "[ ==]", "[ =]", "[ ]"], interval: 120 }
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Disabling Icons
|
|
483
|
+
|
|
484
|
+
To disable icons entirely, set `icons: false`:
|
|
485
|
+
|
|
486
|
+
```ts
|
|
487
|
+
const toaster = new ToasterRenderable(ctx, {
|
|
488
|
+
icons: false,
|
|
489
|
+
});
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
Individual toasts can still override this by providing a custom `icon`:
|
|
493
|
+
|
|
494
|
+
```ts
|
|
495
|
+
// Icons are disabled globally, but this toast will show a custom icon
|
|
496
|
+
toast.success("Done!", { icon: "✓" });
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
## API Reference
|
|
500
|
+
|
|
501
|
+
### `toast(message, options?)`
|
|
502
|
+
|
|
503
|
+
Show a default toast.
|
|
504
|
+
|
|
505
|
+
### `toast.success(message, options?)`
|
|
506
|
+
|
|
507
|
+
Show a success toast with a checkmark icon.
|
|
508
|
+
|
|
509
|
+
### `toast.error(message, options?)`
|
|
510
|
+
|
|
511
|
+
Show an error toast with an X icon.
|
|
512
|
+
|
|
513
|
+
### `toast.warning(message, options?)`
|
|
514
|
+
|
|
515
|
+
Show a warning toast with a warning icon.
|
|
516
|
+
|
|
517
|
+
### `toast.info(message, options?)`
|
|
518
|
+
|
|
519
|
+
Show an info toast with an info icon.
|
|
520
|
+
|
|
521
|
+
### `toast.loading(message, options?)`
|
|
522
|
+
|
|
523
|
+
Show a loading toast with an animated spinner.
|
|
524
|
+
|
|
525
|
+
### `toast.promise(promise, options)`
|
|
526
|
+
|
|
527
|
+
Show a toast that updates based on promise state.
|
|
528
|
+
|
|
529
|
+
### `toast.dismiss(id?)`
|
|
530
|
+
|
|
531
|
+
Dismiss a specific toast by ID, or all toasts if no ID provided.
|
|
532
|
+
|
|
533
|
+
### `toast.getToasts()`
|
|
534
|
+
|
|
535
|
+
Get all currently active toasts.
|
|
536
|
+
|
|
537
|
+
### `toast.getHistory()`
|
|
538
|
+
|
|
539
|
+
Get all toasts ever created (including dismissed).
|
|
540
|
+
|
|
541
|
+
### Toast Options
|
|
542
|
+
|
|
543
|
+
| Option | Type | Default | Description |
|
|
544
|
+
| ------------- | -------------------------- | ---------- | ---------------------------------- |
|
|
545
|
+
| `id` | `string \| number` | auto | Unique identifier for the toast |
|
|
546
|
+
| `description` | `string \| (() => string)` | - | Secondary text below the title |
|
|
547
|
+
| `duration` | `number` | `4000` | Time in ms before auto-dismiss |
|
|
548
|
+
| `dismissible` | `boolean` | `true` | Whether the toast can be dismissed |
|
|
549
|
+
| `icon` | `string` | type-based | Custom icon to display |
|
|
550
|
+
| `action` | `{ label, onClick }` | - | Action button configuration |
|
|
551
|
+
| `closeButton` | `boolean` | `false` | Show close button |
|
|
552
|
+
| `style` | `ToastStyle` | - | Per-toast style overrides |
|
|
553
|
+
| `onDismiss` | `(toast) => void` | - | Callback when dismissed |
|
|
554
|
+
| `onAutoClose` | `(toast) => void` | - | Callback when auto-closed |
|
|
555
|
+
|
|
556
|
+
## Examples
|
|
557
|
+
|
|
558
|
+
### Basic Example
|
|
559
|
+
|
|
560
|
+
```ts
|
|
561
|
+
import { createCliRenderer } from "@opentui/core";
|
|
562
|
+
import { toast, ToasterRenderable } from "@opentui-ui/toast";
|
|
563
|
+
|
|
564
|
+
const renderer = await createCliRenderer();
|
|
565
|
+
|
|
566
|
+
// Add toaster
|
|
567
|
+
const toaster = new ToasterRenderable(renderer, {
|
|
568
|
+
position: "bottom-right",
|
|
569
|
+
});
|
|
570
|
+
renderer.root.add(toaster);
|
|
571
|
+
|
|
572
|
+
// Show some toasts
|
|
573
|
+
toast.success("Application started!");
|
|
574
|
+
|
|
575
|
+
setTimeout(() => {
|
|
576
|
+
toast.info("Press 'q' to quit");
|
|
577
|
+
}, 1000);
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### Async Operation
|
|
581
|
+
|
|
582
|
+
```ts
|
|
583
|
+
async function saveData(data: unknown) {
|
|
584
|
+
toast.promise(
|
|
585
|
+
fetch("/api/save", {
|
|
586
|
+
method: "POST",
|
|
587
|
+
body: JSON.stringify(data),
|
|
588
|
+
}),
|
|
589
|
+
{
|
|
590
|
+
loading: "Saving...",
|
|
591
|
+
success: "Saved!",
|
|
592
|
+
error: "Failed to save",
|
|
593
|
+
}
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### Manual Loading State
|
|
599
|
+
|
|
600
|
+
```ts
|
|
601
|
+
async function uploadFile(file: File) {
|
|
602
|
+
const id = toast.loading("Uploading...");
|
|
603
|
+
|
|
604
|
+
try {
|
|
605
|
+
const result = await upload(file);
|
|
606
|
+
toast.success(`Uploaded ${result.filename}`, { id });
|
|
607
|
+
} catch (error) {
|
|
608
|
+
toast.error("Upload failed", { id });
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
## TypeScript
|
|
614
|
+
|
|
615
|
+
Full TypeScript support with exported types:
|
|
616
|
+
|
|
617
|
+
```ts
|
|
618
|
+
import type {
|
|
619
|
+
Action, // Action button configuration
|
|
620
|
+
ExternalToast, // Options for toast() calls
|
|
621
|
+
Position, // Toaster position type
|
|
622
|
+
PromiseData, // Configuration for toast.promise()
|
|
623
|
+
SpinnerConfig, // Animated spinner configuration { frames, interval }
|
|
624
|
+
StackingMode, // Stacking mode ('single' | 'stack')
|
|
625
|
+
ToasterOffset, // Offset configuration for positioning
|
|
626
|
+
ToasterOptions, // Configuration for ToasterRenderable
|
|
627
|
+
ToastIcons, // Custom icon set type
|
|
628
|
+
ToastOptions, // Default toast options (styles, duration, per-type overrides)
|
|
629
|
+
ToastStyle, // Per-toast styling options
|
|
630
|
+
ToastType, // Toast type variants
|
|
631
|
+
TypeToastOptions, // Per-type options (style + duration)
|
|
632
|
+
} from "@opentui-ui/toast";
|
|
633
|
+
|
|
634
|
+
// Border types (for customBorderChars) come from @opentui/core
|
|
635
|
+
import type { BorderCharacters, BorderSides, BorderStyle } from "@opentui/core";
|
|
636
|
+
|
|
637
|
+
// Type guards
|
|
638
|
+
import { isAction, isSpinnerConfig } from "@opentui-ui/toast";
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
### Constants
|
|
642
|
+
|
|
643
|
+
```ts
|
|
644
|
+
import { TOAST_DURATION } from "@opentui-ui/toast";
|
|
645
|
+
|
|
646
|
+
// Duration presets
|
|
647
|
+
TOAST_DURATION.SHORT; // 2000ms - brief confirmations
|
|
648
|
+
TOAST_DURATION.DEFAULT; // 4000ms - standard notifications
|
|
649
|
+
TOAST_DURATION.LONG; // 6000ms - important messages
|
|
650
|
+
TOAST_DURATION.EXTENDED; // 10000ms - critical information
|
|
651
|
+
TOAST_DURATION.PERSISTENT; // Infinity - manual dismiss only
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
## Acknowledgments
|
|
655
|
+
|
|
656
|
+
Inspired by [Sonner](https://sonner.emilkowal.ski/) by Emil Kowalski.
|
|
657
|
+
|
|
658
|
+
## License
|
|
659
|
+
|
|
660
|
+
MIT
|