shadcn-svelte icon indicating copy to clipboard operation
shadcn-svelte copied to clipboard

Toast

Open ftognetto opened this issue 1 year ago • 17 comments

Describe the feature in detail (code, mocks, or screenshots encouraged)

Hello, is there any plan to add the toast component? https://www.melt-ui.com/docs/builders/toast

Thank you I'm so happy I finally found a component library :)

What type of pull request would this be?

None

Provide relevant links or additional information.

No response

ftognetto avatar Aug 21 '23 12:08 ftognetto

Hey @ftognetto, this is definitely something we plan to add!

We're working on how to best approach it since the toast is typically a singleton component that is placed on the root layout and then invoked via a function!

huntabyte avatar Aug 21 '23 13:08 huntabyte

How I'm currently using this in my project:

I created a Toaster component which can be placed in the root layout. This contains a portal and loops through the toasts as provided by the state from the melt builder. Users can add new toasts by invoking an imported function from a centralized util. I like the example Melt provides too, where it uses the Svelte context module instead https://svelte.dev/docs/svelte-components#script-context-module to expose the helper function

leonardsimonse avatar Aug 21 '23 15:08 leonardsimonse

Hi yes me too I made a temp version for this, using melt and applying shadcn style

<script lang="ts" context="module">
	export type ToastData = {
		title?: string;
		description: string;
		variant?: 'default' | 'destructive';
	};

	const {
		elements: { content, title, description, close },
		helpers,
		states: { toasts },
		actions: { portal }
	} = createToaster<ToastData>();

	export const addToast = (data: ToastData) => helpers.addToast({ data });
</script>

<script lang="ts">
	import { createToaster } from '@melt-ui/svelte';
	import { X } from 'lucide-svelte';
	import { flip } from 'svelte/animate';
	import { fly } from 'svelte/transition';
</script>

<div
	class="fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]"
	use:portal
>
	{#each $toasts as { id, data } (id)}
		<div
			{...$content(id)}
			use:content
			animate:flip={{ duration: 500 }}
			in:fly={{ duration: 150, x: '100%' }}
			out:fly={{ duration: 150, x: '100%' }}
			class="group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md p-6 pr-8 shadow-lg transition-all {data.variant ===
			'destructive'
				? 'border-destructive bg-destructive text-destructive-foreground'
				: 'border bg-background text-foreground'}"
		>
			<div class="grid gap-1">
				{#if data.title}
					<div {...$title(id)} use:title class="text-sm font-semibold">
						{data.title}
					</div>
				{/if}
				<div {...$description(id)} use:description class="text-sm opacity-90">
					{data.description}
				</div>
			</div>
			<button
				{...$close(id)}
				use:close
				class="absolute right-4 top-4 grid place-items-center rounded-full opacity-0 transition-opacity focus:opacity-100 group-hover:opacity-100 {data.variant ===
				'destructive'
					? 'text-red-300 hover:text-red-50'
					: 'text-foreground/50 hover:text-foreground'} "
			>
				<X class="h-4 w-4" />
			</button>
		</div>
	{/each}
</div>

Then in +layout.svelte

<script lang="ts">
	import Toaster, { addToast } from '$lib/components/ui/toast/toaster.svelte';
	import { getFlash } from 'sveltekit-flash-message/client';
	import '../app.postcss';

	/** Can be integrated with sveltekit-flash-messages too */
	const flash = getFlash(page);
	flash.subscribe(($flash) => {
		if (!$flash) return;

		if ($flash.type == 'success') {
			addToast({
				description: $flash.message
			});
		} else {
			addToast({
				description: $flash.message,
				variant: 'destructive'
			});
		}
		// Clearing the flash message could sometimes
		// be required here to avoid double-toasting.
		flash.set(undefined);
	});
</script>

<Toaster />
<slot />

ftognetto avatar Oct 21 '23 11:10 ftognetto

Any updates on this one?

sjaghori avatar Nov 11 '23 12:11 sjaghori

MeltUI is growing so fast, I hope to see this component here too

njacob1001 avatar Nov 16 '23 11:11 njacob1001

Hey @ftognetto, this is definitely something we plan to add!

We're working on how to best approach it since the toast is typically a singleton component that is placed on the root layout and then invoked via a function!

@huntabyte I think it will be better to allow the user to figure out how to best utilize the component. Such as in many places one might not want it on the root layout. And how to invoke it.

Shadcn UI just introduced this new toast https://ui.shadcn.com/docs/components/sonner. Which is a standard react library installed from npm. Thus being able to import and call functions such as toast(). However, I believe it will be better to allow the user to handle invocation from various places, which can eliminate the need for a npm installed library.

sksar avatar Dec 27 '23 06:12 sksar

Why can't just use sonner? What's the difference?

akubima avatar Jan 28 '24 06:01 akubima

@peprmint1 They already use sonner: https://www.shadcn-svelte.com/docs/components/sonner I honestly dont know, why this issue is still open @ftognetto

Creative-Difficulty avatar Jan 28 '24 09:01 Creative-Difficulty

@peprmint1 They already use sonner: https://www.shadcn-svelte.com/docs/components/sonner I honestly dont know, why this issue is still open @ftognetto

I've noticing it before I posted in this, I thought that sonner was not intended to be use as toasts but it's serves the same purpose anyway.

akubima avatar Jan 28 '24 10:01 akubima

I'm also using Sonner at the moment. I don't know if @huntabyte wants to proceed with the development of Toast anyway but, as far as I'm concerned, this issue can be closed

ftognetto avatar Jan 28 '24 11:01 ftognetto

I'm also using Sonner at the moment. I don't know if @huntabyte wants to proceed with the development of Toast anyway but, as far as I'm concerned, this issue can be closed

Having a Toast instead of a Sonner would be nice too.

akubima avatar Feb 08 '24 10:02 akubima

As a user looking for toast component, the idea to check sonner never occurs. I'd be best to adhere to standard naming conventions and rename/alias sonner to toast so we can close this issue.

MentalGear avatar Feb 28 '24 18:02 MentalGear

Yeah, the original shadcn/ui Toast feels like a worse Sonner, with no extra advantages.

Renaming (or alisasing) Sonner to "Toast", and adding some configuration options (like showing only one toast at a time, or never hiding unless user closes them), would be more than sufficient here.

What do you think @huntabyte?

Skaldebane avatar May 17 '24 20:05 Skaldebane

We're gonna keep Sonner named as such for the time being. Bits UI is being rewritten for Svelte 5 and may include a Toast and Toaster component that, while not as clean and smooth as Sonner, will be easier to customize for specific use cases.

huntabyte avatar May 18 '24 15:05 huntabyte

If you don't mind, can I know will this be release? This seems like important component yet its missing.

meoawww avatar Jul 06 '24 08:07 meoawww

If you don't mind, can I know will this be release? This seems like important component yet its missing.

I think the official path to its release would look like: Svelte 5 stable release -> Bits UI rewrite release -> shadcn-svelte update. How quickly we get there will directly depend on how much help @huntabyte gets, so if you're able to support in any way, I would suggest reaching out to him

leonardsimonse avatar Jul 06 '24 08:07 leonardsimonse