emilkowalski / sonner Goto Github PK
View Code? Open in Web Editor NEWAn opinionated toast component for React.
Home Page: https://sonner.emilkowal.ski
License: MIT License
An opinionated toast component for React.
Home Page: https://sonner.emilkowal.ski
License: MIT License
Hello
I am using the toaster component and after updating some packages, i am getting error with the Toaster component.
This is the ss of the errors. When i comment out the Toaster call in main layout, the site is working fine. Because of the error, nothing is visible on the site, just plain white color.
It was working fine till yesterday only, then i updated all the packages using npm-check-update and since then the Toaster is giving errors. I think there is some issue of sonner with the version of other packages.
Any help?
Is there any hard reason for it? It seems to work fine but npm is not liking the requirement when run under a react 17 codebase. Thanks in advance.
It would be super useful to allow calling toast.dismiss()
without arguments to close all of the toasts.
I would like to create some kind of toast confirmation. My first attempt was to update the toast by passing an id
const id = toast("Are you sure...", {
action: {
label: "Save",
onClick: () => {
toast.promise(promise, {
id,
loading: "Loading...",
success: "Saved",
error: "Something went wrong"
});
}
}
The first error with this is that when clicking on "Save" the toast is closed and there seems to be no way to disable this. The second error is the title Are you sure...
has not been updated to Loading...
.
I think this can be handled in two ways:
toast.confirm
API for these casesid
to options
.I would say that the second option is preferable because it offers more flexibility. For example, if the second option is implemented, it would be nice if the toast promise options could return an object to update the toast
const id = toast("Are you sure...", {
action: {
label: "Save",
onClick: () => {
toast.promise(promise, {
id,
loading: "Loading...",
success: () => {
return {
title: 'Saved',
action: {
label: "Undo",
onClick: () => { ... }
}
},
error: "Something went wrong"
});
}
}
});
When the viewport width is less than 600px, the toast is displayed in the wrong place if I use the "bottom-center" or "top-center" position.
Hey,
Thanks for creating such a great tool, it's really awesome.
I want to know is there is any specific way for conditionally opening and closing the toast?
Reproduction: https://codesandbox.io/s/wonderful-brook-9wrw4c?file=/src/App.tsx
Loom of what I see: https://www.loom.com/share/45ce40b6c6294585b503ef1d00725bca
The repro is obviously a worst-case, but we observe the behavior in file-uploading code that concurrently uploads 5 files at a time from a batch uploader and streams back processing results. It creates toasts far less rapidly, but still suffers from this issue.
Otherwise, cool library!
If I write this code, I want to change the theme.
export const SonnerContainer = () => {
const isDark = useIsDark()
return (
<Toaster
richColors
closeButton
duration={6666}
theme={isDark ? 'dark' : 'light'}
/>
)
}
But props theme
is not reactive.
https://github.com/emilkowalski/sonner/blob/main/src/index.tsx#L385
Hi @emilkowalski 👋
Thanks for this awesome simple & clean toast package, really love it 🤟
I've found an issue when using this package, whenever I click the ESC
Key, the following error comes up:
Sadly this makes the package almost not usable cause we have different EventListenser for the Escape Key (Dismiss Dialog, dismiss Focus, etc..). I've noticed that this bug also occurs on https://sonner.emilkowal.ski/
I see you can run toast.dismiss()
to clear all, but it would be good if there was default UI for this button, as it needs to respond to the current UI as difficult to place.
How do I change the with of the sonner toaster without it affecting the position of the toaster. I did this to change the width: toastOptions={{style: { width: 'fit-content' }, className: 'my-toast'}}
. However it causes the toaster not be centred anymore. It shifts to the left
Unable to install package using yarn, it's a different package
yarn add sooner
First of all, great work, looks amazing and has a delightful user experience!!
One thing is, I would like to be able to use the toast like this:
const promise = settingsMutation.mutate(...)
toast('Your settings have been updated', { promise })
Instead of writing it like this, since often times the mutation can have quite a bit of code inside, so wrapping it all with the toast feels unergonomic.
toast('Your settings have been updated', { promise() {
return settingsMutation.mutate(...)
}}
If you feel like this is a reasonable change, I would be glad to submit a Pull Request!
Hi! I was trying the svelte port, but the animations were not working. I checked this library, and I had the same problem. See wobsoriano/svelte-sonner#1
Neither when passing it to the <Toast />
component nor when using it inside the options of the toast()
call does the className
options do anything. Tested it with both Tailwind classes as well as my own globally defined ones. The style of the toast stays the same. style
works though!
toast title initial-height is affected by line-height, causing layout shifts when hover.
The instructions in the README appear to be correct, that offset
accepts a px string, e.g. "20px".
I would've fixed this but couldn't find interface ToasterProps
in this repo, I only found it in the distribution. 🤷🏻♂️
interface ToasterProps {
invert?: boolean;
theme?: 'light' | 'dark';
position?: Position;
hotkey?: string[];
richColors?: boolean;
expand?: boolean;
duration?: number;
visibleToasts?: number;
closeButton?: boolean;
toastOptions?: ToastOptions;
className?: string;
style?: React.CSSProperties;
offset?: number;
}
I am not sure how to best address this issue, please close if it is out of scope.
I have a spinner with tailwind animate-spin
which under the hood uses keyframes spin
. After importing sonner to my project, it stopped working as sonner has a keyframes with same name spin
.
Thanks for awesome library.
Customisable themes please 🥺 Make it so you can style the default, success, and error toasts (change bg & fg colour mainly)
Hi, thanks for making an awesome toaster!
Tested today (May 14th) at https://sonner.emilkowal.ski/ using macOS Chrome 113.0.5672.92(x86_64)
We have a option to add custom component to the toast with
toast.custom(
<div>
{/* Custom stuff */}
</div>
)
What if we would be able to have default custom component from the Root provider? For example
import { Toaster, toast } from 'sonner';
const Custom = (toasterProps: SomeToasterProps) => {
return (
<div>
{/* Custom stuff */}
</div>
)
}
const App = () => {
return (
<div>
<Toaster custom={Custom} />
<button onClick={() => toast('I am using custom toast')}>Give me a toast</button>
</div>
);
}
The default component could inherit props from the library, and then for example even the toast.error
, would use the custom toast. I had to use the react-toastify
recently, and I had to create custom function to reuse the custom component everywhere. I believe it's the same here.
Hi, There is a possibility to pass the position of toast through toast.custom.
toast.custom(
(t) => (
<div>Hello world</div>
),
{
...
position: top-center
}
);
What if a sound plays When the toast appears or the toast is closed ?
Just to share that I tried to translate sooner in Vue.js with gpt-4, spent 10h on it and couldn't make it properly.
Then I found out : https://github.com/devilwjp/veaury
And tried and in 5 min it worked.
So, Your plugin is now used in a Vue 3 app: https://github.com/Cap-go/capgo
Thanks for the work <3
Can we add duration prop to toast.promise?
for ex:
const promise = () => registerNewPatient(req);
toast.promise(promise, {
loading: 'Hasta kayıt ediliyor',
success: data => {
const patientId = data.patientId;
const fullname = data.fullname;
const sleep = () => new Promise(resolve => setTimeout(resolve, 5000));
toast.promise(sleep, {
loading: '5 saniye içinde hasta detay sayfasına yönlendiriliyor olacaksınız...',
success: data => {
history(
`/patient/${patientId}?step=treatment&treatment=1&payment=1&new_register=true`,
);
return null
// return `Tablo alanı üzerinde sağ tıklayarak yeni tedavi kaydı oluşturabilirsiniz`;
},
error: 'Error',
});
return `${fullname} isimli hasta başarı ile kaydedildi`;
},
error: 'Error',
});
I want to show success toast messages longer than it is. But I don't want to set global duration.
toast.promise(promise, {}, { duration: 5000 })
thank you to create this library.
Hi there,
first of all – I don't expect this to be resolved on this repositories level as it's basically a browser-implementation thing. I just wanted to write this down for anyone else trying to do a similar thing and searching through issues.
will-change
prevents backdrop-filter: blur()
from being applied. That's easy to circumvent through:
[data-sonner-toast] {
will-change: initial;
}
But while the css transition of transition: transform 0.4s, opacity 0.4s, height 0.4s, box-shadow 0.2s;
is happening, it appears non-rendered. Trying out setting transition: none
has no flash of unblurred backdrop, so it's really only during said transition (but that would obviously remove all the animations, which obviously is far worse).
Here's a quick demo video (scrub to see more clearly):
After playing around a little, it seems that any opacity change messes with the backdrop-filter, see this codepen https://codepen.io/tom2strobl/pen/XWybQWO .modal:hover
where the commented out opacity change makes everything work fine, but as soon as opacity is in the mix, it refuses to render properly.
So what I'm guessing is that since opacity is used extensively throughout it's also not really feasible to try catch to catch all opacity changes with overrides, so I'd say this is just simply not possible with the current implementation and not enough of a case to urge any kind of change either.
Also, just as an expreriment trying to be clever like this doesn't make the blur work during transition:
[data-sonner-toast] {
transition: transform 0.4s, height 0.4s, box-shadow 0.2s;
&[data-swiping='true'] {
transition: none;
}
& > * {
opacity: 1 !important;
transition: initial;
}
&[data-removed='true'][data-front='false'][data-swipe-out='false'][data-expanded='false'] {
opacity: 1;
transition: transform 500ms;
}
}
Btw I'm closing this issue straight away – it's really first and foremost meant as an endpoint for people that search.
Great job on this package, it works perfectly and uses the same API as https://github.com/timolins/react-hot-toast :)
I did have a few problems when integrating it:
@import 'sonner/styles.css'
or something similarSome e2e tests to avoid regression would be useful.
Here's an example of how that might look like - https://github.com/pacocoursey/cmdk/tree/main/test.
Listen to height changes on each toast to avoid bugs like this one - #66 (comment).
Hello! 👋,
I as just wondering if I could create a Vue Component for this, either I can integrate with current repo but downside is It would have to be restructured for Vue and React components but also setting up a monorepo. Either way just let me know thanks.
Once it's in Vue it then can compiled down into a Custom Element
which would be framework agnostic.
Thanks!
CP
PS. Thanks for creating this amazing toast!
Awesome work on this 👏 !
This is more of an open question than an issue.
I'd like to be able to pass in custom components as the message (and ideally one or two more ToastTypes, we have Info and Warning)
This could be done by using custom components with their own Error/Success styling, but it would be great to be able to tap into the underlying structure here, to get data-type="ToastType"
out of the box.
Alternatively, allowing string | React.Element
instead of just string
for the toast message (this actually works to some extent out of the box when I pass in messageComponent as string
– dirty, but it let me test that it would work.
Or maybe allowing some more options to be set using toast.custom(() => void, options: { icon, type, action })
?
I'm curious if something like this goes against the "opinionation" of this amazing little component?
Hello,
I've recently come across Sonner and found it to be an extremely useful toast component for React applications. However, I noticed that there could be more comprehensive documentation that elaborates on its features, use-cases, and provides more detailed setup and usage instructions. I believe this would be immensely beneficial to developers who are new to Sonner or those who would like to fully utilize its functionalities.
I have considerable experience with React and would love to contribute to enhancing the documentation for this project.
Here's what I propose to work on:
Please let me know if this is something you'd be interested in, and if so, if there are any specific guidelines or prerequisites I should follow.
Looking forward to your feedback.
Best regards,
Augustine
Currently, if we pass a number to the offset
, it'll break the position of the Toast because it isn't the type it expects.
Pass a number to the offset
.
<Toaster offset={12} />
offset
should be set according to the number value passed to it.
Operating System:
Platform: darwin
Arch: arm64
Binaries:
Node: 18.12.0
pnpm: 7.14.2
Relevant packages:
sonner: 0.2.0
next: 13.2.4
react: 18.2.0
react-dom: 18.2.0
the repo: https://github.com/xiaoluoboding/vue-sonner
the docs: https://vue-sonner.vercel.app/
Can you add a callback that gets executed whenever a toast is dismissed? Handling both timeouts and manually closing. Would be really helpful, thanks!
Sometimes need to use result of promise variant (success or error) with action button.
Would love to have this for VueJS
Any ETA?
Hi first of all i would like to appreciate your efforts in developing such a beautiful notification mechanism, hopefully the project would grow into something more spectacular.
I wanted to ask if the toast message during its promise can be changed for example lets say data is being uploaded to 3 different servers i would like the toast to showcase on which endpoints the data has been uploaded, is it possible to showcase that??
If I write this code, I want to change the theme.
export const SonnerContainer = () => {
const isDark = useIsDark()
return (
<Toaster
richColors
closeButton
duration={6666}
theme={isDark ? 'dark' : 'light'}
/>
)
}
But props theme
is not reactive.
https://github.com/emilkowalski/sonner/blob/main/src/index.tsx#L385
Currently the type of description
is typed as string
but it can be React Node.
Is there anyway we could create a toast with a custom ID? Would be a very useful feature as well when we want to specifically create toasts with certain IDs and dismiss them at a later time, without us having to store the IDs in some state to map them back to the auto-generated sonner ID
Hi
Have you thought about exporting ExternalToast type to make wrappers easier?
I want to render a toast whenever an error message changes, for that I am using useEffect hook, but the console prompts this warning:
Warning: flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task
Open this stackblitz project https://stackblitz.com/edit/react-ts-thceyi?file=App.tsx
Click on change state button. See the console and watch the warning on every state change.
Edit: Easier way to replicate
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.