Headless & Custom
Take full control over the markup and styling of your toasts.
Usage
Use the toast.custom method to render a custom component. The component will receive id and toast props, along with any props passed via componentProps.
<script>
import { toast } from 'varsel';
import HeadlessToast from './HeadlessToast.svelte';
</script>
<button
class="rounded-md bg-vs-foreground px-4 py-2 h-9 text-sm font-medium text-foreground-invert hover:bg-foreground/80 shadow-sm transition-[background-color,scale] duration-150 ease-out active:scale-[0.975] cursor-pointer"
onclick={() => {
toast.custom(HeadlessToast, {
duration: 100000,
componentProps: {
title: "This is a headless toast",
description:
"You have full control of styles and markup, while still having the animations.",
button: {
label: "Reply",
onClick: () => console.log("Reply clicked"),
},
},
});
}}
>
Render toast
</button>;Creating the component
Your custom component receives the id prop, which you can use to dismiss the toast programmatically.
<!-- HeadlessToast.svelte -->
<script lang="ts">
import { toast as varselToast } from "varsel";
import type { PositionedToast } from "varsel";
let {
id,
title,
description,
button,
}: {
id: string;
title: string;
description: string;
button: { label: string; onClick: () => void };
toast: PositionedToast;
} = $props();
</script>
<div
class="flex w-full max-w-[364px] items-center rounded-lg bg-white p-4 shadow-lg ring-1 ring-black/5 dark:bg-zinc-900 dark:ring-white/10"
>
<div class="flex flex-1 items-center">
<div class="w-full">
<p class="text-sm font-medium text-gray-900 dark:text-gray-100">{title}</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{description}</p>
</div>
</div>
<div
class="ml-5 shrink-0 rounded-md text-sm font-medium text-indigo-600 hover:text-indigo-500 focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:outline-hidden dark:text-indigo-400 dark:hover:text-indigo-300"
>
<button
class="cursor-pointer rounded bg-indigo-50 px-3 py-1 text-sm font-semibold text-indigo-600 hover:bg-indigo-100 dark:bg-indigo-950/50 dark:text-indigo-400 dark:hover:bg-indigo-900/50"
onclick={() => {
button.onClick();
varselToast.dismiss(id);
}}
>
{button.label}
</button>
</div>
</div>