Sonner

A toast notification component for displaying temporary messages

Configuration

Adjust toast settings for all demos below.

Toast Types

Different toast types for various notification scenarios.


Code Svelte
1
2<script lang="ts">
3	import { Button, Sonner, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6</script>
7
8<Sonner />
9
10<div class="flex flex-wrap gap-3">
11	<Button
12		variant="outline"
13		onclick={() => toast("This is a default notification")}
14	>
15		Default
16	</Button>
17	<Button
18		color="success"
19		onclick={() => toast.success("Operation completed successfully!")}
20	>
21		Success
22	</Button>
23	<Button
24		color="danger"
25		onclick={() => toast.error("Something went wrong!")}
26	>
27		Error
28	</Button>
29	<Button
30		color="warning"
31		onclick={() => toast.warning("Please review your input")}
32	>
33		Warning
34	</Button>
35	<Button
36		color="info"
37		onclick={() => toast.info("Here's some useful information")}
38	>
39		Info
40	</Button>
41	<Button
42		variant="outline"
43		onclick={() => {
44			const id = toast.loading("Processing...");
45			setTimeout(() => {
46				toast.dismiss(id);
47				toast.success("Done!");
48			}, 2000);
49		}}
50	>
51		Loading
52	</Button>
53</div>

Visual Variants

Four distinct styles to match your UI

Default — tinted backgrounds with type-colored borders

Bordered — clean background with colored left accent border

Filled — solid colored backgrounds for high contrast

Minimal — transparent background with subtle bottom border


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	let activeVariant: SonnerPrimitives.ToasterStyle = $state("default");
6
7	const { toast } = SonnerPrimitives;
8
9</script>
10
11<Sonner variant={activeVariant} />
12
13	<!-- Default -->
14<div class="space-y-8">
15	<div>
16		<h3 class="text-sm font-medium text-muted-foreground mb-3">Default — tinted backgrounds with type-colored borders</h3>
17		<div class="flex flex-wrap gap-2">
18			<Button color="success" variant="flat" onclick={() => { activeVariant = "default"; toast.success("Default variant success"); }}>
19				Success
20			</Button>
21			<Button color="danger" variant="flat" onclick={() => { activeVariant = "default"; toast.error("Default variant error"); }}>
22				Error
23			</Button>
24			<Button color="warning" variant="flat" onclick={() => { activeVariant = "default"; toast.warning("Default variant warning"); }}>
25				Warning
26			</Button>
27			<Button color="info" variant="flat" onclick={() => { activeVariant = "default"; toast.info("Default variant info"); }}>
28				Info
29			</Button>
30		</div>
31	</div>
32
33	<!-- Bordered -->
34	<div>
35		<h3 class="text-sm font-medium text-muted-foreground mb-3">Bordered — clean background with colored left accent border</h3>
36		<div class="flex flex-wrap gap-2">
37			<Button color="success" variant="bordered" onclick={() => { activeVariant = "bordered"; toast.success("Bordered variant success"); }}>
38				Success
39			</Button>
40			<Button color="danger" variant="bordered" onclick={() => { activeVariant = "bordered"; toast.error("Bordered variant error"); }}>
41				Error
42			</Button>
43			<Button color="warning" variant="bordered" onclick={() => { activeVariant = "bordered"; toast.warning("Bordered variant warning"); }}>
44				Warning
45			</Button>
46			<Button color="info" variant="bordered"  onclick={() => { activeVariant = "bordered"; toast.info("Bordered variant info"); }}>
47				Info
48			</Button>
49		</div>
50	</div>
51
52	<!-- Filled -->
53	<div>
54		<h3 class="text-sm font-medium text-muted-foreground mb-3">Filled — solid colored backgrounds for high contrast</h3>
55		<div class="flex flex-wrap gap-2">
56			<Button color="success" variant="default" onclick={() => { activeVariant = "filled"; toast.success("Filled variant success"); }}>
57				Success
58			</Button>
59			<Button color="danger" variant="default" onclick={() => { activeVariant = "filled"; toast.error("Filled variant error"); }}>
60				Error
61			</Button>
62			<Button color="warning" variant="default" onclick={() => { activeVariant = "filled"; toast.warning("Filled variant warning"); }}>
63				Warning
64			</Button>
65			<Button color="info" variant="default" onclick={() => { activeVariant = "filled"; toast.info("Filled variant info"); }}>
66				Info
67			</Button>
68		</div>
69	</div>
70
71	<!-- Minimal -->
72	<div>
73		<h3 class="text-sm font-medium text-muted-foreground mb-3">Minimal — transparent background with subtle bottom border</h3>
74		<div class="flex flex-wrap gap-2">
75			<Button color="success" variant="outline" onclick={() => { activeVariant = "minimal"; toast.success("Minimal variant success"); }}>
76				Success
77			</Button>
78			<Button color="danger" variant="outline" onclick={() => { activeVariant = "minimal"; toast.error("Minimal variant error"); }}>
79				Error
80			</Button>
81			<Button color="warning" variant="outline" onclick={() => { activeVariant = "minimal"; toast.warning("Minimal variant warning"); }}>
82				Warning
83			</Button>
84			<Button color="info" variant="outline" onclick={() => { activeVariant = "minimal"; toast.info("Minimal variant info"); }}>
85				Info
86			</Button>
87		</div>
88	</div>
89</div>
90
91
92

With Descriptions

Add descriptive text for more context.


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6</script>
7
8<Sonner />
9
10<div class="flex flex-wrap gap-3">
11	<Button
12		color="success"
13		onclick={() => toast.success("File uploaded", {
14			description: "Your document has been saved to the cloud successfully."
15		})}
16	>
17		Success with Description
18	</Button>
19	<Button
20		color="danger"
21		onclick={() => toast.error("Upload failed", {
22			description: "The file exceeds the maximum size limit of 10MB."
23		})}
24	>
25		Error with Description
26	</Button>
27	<Button
28		color="warning"
29		onclick={() => toast.warning("Low storage", {
30			description: "You are using 95% of your available storage."
31		})}
32	>
33		Warning with Description
34	</Button>
35</div>

With Action Buttons

Add action and cancel buttons for interactive toasts.


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6</script>
7
8<Sonner />
9
10<div class="flex flex-wrap gap-3">
11	<Button
12		color="success"
13		variant="flat"
14		onclick={() => toast.success("Event created", {
15			description: "Your event has been scheduled.",
16			action: {
17				label: "View Event",
18				onClick: () => toast.info("Opening event details...")
19			}
20		})}
21	>
22		With Action
23	</Button>
24	<Button
25		color="danger"
26		variant="flat"
27		onclick={() => toast.error("Delete this item?", {
28			description: "This action cannot be undone.",
29			action: {
30				label: "Delete",
31				onClick: () => toast.success("Item deleted successfully")
32			},
33			cancel: {
34				label: "Cancel",
35				onClick: () => toast.info("Deletion cancelled")
36			}
37		})}
38	>
39		With Action & Cancel
40	</Button>
41</div>

Promise Toasts

Automatically handle loading, success, and error states.


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6
7	function simulateAsyncOperation(shouldSucceed: boolean = true) {
8		return new Promise((resolve, reject) => {
9			setTimeout(() => {
10				if (shouldSucceed) {
11					resolve({ items: 42, name: "Report.pdf" });
12				} else {
13					reject(new Error("Network connection failed"));
14				}
15			}, 2000);
16		});
17	}
18</script>
19
20<Sonner />
21
22<div class="flex flex-wrap gap-3">
23	<Button
24		onclick={() => {
25			toast.promise(simulateAsyncOperation(true), {
26				loading: "Uploading file...",
27				success: (data) => `${data.name} uploaded successfully!`,
28				error: "Failed to upload file"
29			});
30		}}
31	>
32		Promise (Success)
33	</Button>
34	<Button
35		variant="outline"
36		onclick={() => {
37			toast.promise(simulateAsyncOperation(false), {
38				loading: "Connecting to server...",
39				success: "Connected!",
40				error: (err) => `Error: ${err.message}`
41			});
42		}}
43	>
44		Promise (Error)
45	</Button>
46</div>

Duration & Persistence

Control how long toasts stay visible.


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6</script>
7
8<Sonner />
9
10<div class="flex flex-wrap gap-3">
11	<Button
12		variant="outline"
13		onclick={() => toast.info("Quick toast", { duration: 1000 })}
14	>
15		1 Second
16	</Button>
17	<Button
18		variant="outline"
19		onclick={() => toast.info("Normal toast", { duration: 4000 })}
20	>
21		4 Seconds
22	</Button>
23	<Button
24		variant="outline"
25		onclick={() => toast.info("Long toast", { duration: 10000 })}
26	>
27		10 Seconds
28	</Button>
29	<Button
30		color="warning"
31		onclick={() => toast.warning("Persistent notification", {
32			description: "This toast will not auto-dismiss.",
33			duration: Infinity
34		})}
35	>
36		Persistent (Infinity)
37	</Button>
38</div>

Multiple Toasts

Stack multiple toasts with expand on hover.


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6</script>
7
8<Sonner />
9
10<div class="flex flex-wrap gap-3">
11	<Button
12		onclick={() => {
13			toast.success("First notification");
14			setTimeout(() => toast.info("Second notification"), 200);
15			setTimeout(() => toast.warning("Third notification"), 400);
16			setTimeout(() => toast.error("Fourth notification"), 600);
17		}}
18	>
19		Show 4 Toasts
20	</Button>
21	<Button
22		variant="destructive"
23		onclick={() => toast.dismiss()}
24	>
25		Dismiss All
26	</Button>
27</div>

Custom Styling

Apply custom classes and styles to toasts.


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6</script>
7
8<Sonner />
9
10<div class="flex flex-wrap gap-3">
11	<Button
12		variant="outline"
13		onclick={() => toast.success("Custom styled toast", {
14			description: "This toast has custom border styling.",
15			class: "border-2 border-green-500"
16		})}
17	>
18		Custom Border
19	</Button>
20	<Button
21		variant="outline"
22		onclick={() => toast("Gradient background", {
23			description: "Beautiful gradient styling.",
24			style: "background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white;"
25		})}
26	>
27		Gradient Style
28	</Button>
29</div>

Important Toasts

Important toasts stay on top of the stack.


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6</script>
7<Sonner />
8<div class="flex flex-wrap gap-3">
9	<Button
10		color="danger"
11		onclick={() => {
12			toast.info("Regular notification 1");
13			toast.info("Regular notification 2");
14			toast.error("CRITICAL: System error detected!", {
15				important: true,
16				duration: 10000,
17				action: {
18					label: "Fix Now",
19					onClick: () => toast.success("Issue resolved!")
20				}
21			});
22		}}
23	>
24		Show Important Toast
25	</Button>
26</div>

Sequential Updates

Update the same toast through multiple stages.


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6</script>
7<Sonner />
8<div class="flex flex-wrap gap-3">
9	<Button
10		onclick={async () => {
11			const id = toast.loading("Step 1: Validating data...");
12
13			await new Promise(r => setTimeout(r, 1500));
14			toast.loading("Step 2: Processing...", { id });
15
16			await new Promise(r => setTimeout(r, 1500));
17			toast.loading("Step 3: Saving to database...", { id });
18
19			await new Promise(r => setTimeout(r, 1500));
20			toast.success("All steps completed successfully!", { id });
21		}}
22	>
23		Multi-Step Process
24	</Button>
25</div>

Real-world Examples

Common use cases for toast notifications.

Form Submission

Copy to Clipboard

Delete Confirmation

Network Status

Update Available

Settings Saved


Code Svelte
1
2<script lang="ts">
3	import { Button, SonnerPrimitives } from "@kareyes/aether";
4
5	const { toast } = SonnerPrimitives;
6</script>
7<Sonner />
8<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
9	<div class="p-4 border rounded-lg space-y-3">
10		<h3 class="font-medium">Form Submission</h3>
11		<Button
12			class="w-full"
13			onclick={() => {
14				const id = toast.loading("Submitting form...");
15				setTimeout(() => {
16					toast.success("Form submitted successfully!", {
17						id,
18						description: "We'll get back to you within 24 hours."
19					});
20				}, 1500);
21			}}
22		>
23			Submit Form
24		</Button>
25	</div>
26
27	<div class="p-4 border rounded-lg space-y-3">
28		<h3 class="font-medium">Copy to Clipboard</h3>
29		<Button
30			class="w-full"
31			variant="outline"
32			onclick={() => {
33				navigator.clipboard?.writeText("Copied text!");
34				toast.success("Copied to clipboard!");
35			}}
36		>
37			Copy Text
38		</Button>
39	</div>
40
41	<div class="p-4 border rounded-lg space-y-3">
42		<h3 class="font-medium">Delete Confirmation</h3>
43		<Button
44			class="w-full"
45			color="danger"
46			onclick={() => {
47				toast.error("Delete this item?", {
48					description: "This cannot be undone.",
49					action: {
50						label: "Delete",
51						onClick: () => toast.success("Deleted!")
52					},
53					cancel: {
54						label: "Keep",
55						onClick: () => {}
56					},
57					duration: 10000
58				});
59			}}
60		>
61			Delete Item
62		</Button>
63	</div>
64		<div class="p-4 border rounded-lg space-y-3">
65			<h3 class="font-medium">Network Status</h3>
66			<Button
67				class="w-full"
68				variant="secondary"
69				onclick={() => {
70					toast.error("Connection lost", {
71						description: "Attempting to reconnect...",
72						duration: 3000,
73					});
74					setTimeout(() => {
75						toast.success("Connection restored!");
76					}, 3000);
77				}}
78			>
79				Simulate Offline
80			</Button>
81		</div>
82
83		<div class="p-4 border rounded-lg space-y-3">
84			<h3 class="font-medium">Update Available</h3>
85			<Button
86				class="w-full"
87				color="info"
88				variant="flat"
89				onclick={() => {
90					toast.info("Update available", {
91						description:
92							"A new version is ready to install.",
93						action: {
94							label: "Install Now",
95							onClick: () =>
96								toast.loading(
97									"Installing update...",
98								),
99						},
100						duration: 10000,
101					});
102				}}
103			>
104				Check Updates
105			</Button>
106		</div>
107
108		<div class="p-4 border rounded-lg space-y-3">
109			<h3 class="font-medium">Settings Saved</h3>
110
111			<Button
112				class="w-full"
113				color="success"
114				variant="flat"
115				onclick={() => {
116					toast.success("Settings saved", {
117						description:
118							"Your preferences have been updated.",
119						action: {
120							label: "Undo",
121							onClick: () =>
122								toast.info("Changes reverted"),
123						},
124					});
125				}}
126			>
127				Save Settings
128			</Button>
129		</div>
130</div>