Toast Component for Anvil

Inspired By React-toastify | React-Toastify, I decided to create something similar for Anvil. Toast components can be a beautiful replacement for default Anvil Notifications (and I made sure that it is easy to replace them).

image

Test Playground to test it out https://anvil-toastify.anvil.app/

Clone Link Anvil | Login


Usage

from toastify import toastify
toastify.Toast("Hello World", style="info", timeout = 5, position = "top-right")

With Server Calls

with toastify.Toast("Making call to Server", style="loading") as toast:
    try:
        anvil.server.call_s('get_data_from_server')
        toast.update("success","Data fetched from Server")
    except:
        toast.update("danger","Failed to Fetch Data from Server")

API Reference

Toast

  • message - The text to dispaly in Toa

  • style - The style of Toast
    success , info, warning, danger, loading
    Default: info

  • position - The position of Toast on screen
    top-left, top-right, top-center, bottom-left, bottom-right, bottom-center
    Default: top-right

  • timeout - Duration to display the Toast in seconds
    Default: 2

  • hide() - Hides the Toast

  • update(new_style, new_text) - Updates the style and text of an existing Toast


Some Extra Features

  • Animation on entry and exit
  • A progress bar showing the duration left for the toast (based on timeout property
  • Swipe to dismiss (great for mobile devices)

Replacing Notifications with Toasts

The Toast component accepts the same parameters as Notification. Hence, you just need to change the reference for it to work.

#with Notification
with Notification("Doing Operation", style="info", timeout = 4):
         ...
#with Toasts
with toastify.Toast("Doing Operation", style="info", timeout = 4):
         ...

If you do not wish to replace all references manually, you can apply Toasts as a patch on the entire Notification component. However, this approach will make the default Anvil Notifications inaccessible and hence not recommended.

from toastify import toastify
toastify.patch_anvil_notifications() #Call this at startup module/form

from anvil import * #Make sure that the Anvil import happens after applying patch

Differences in Notifications and Toast

  • title is not displayed in Toast. However, it is still accepted as an argument to prevent code from breaking
  • show() method is not required. All Toasts are shown automatically. However, the method is still there to prevent your code from breaking.

Let me know your feedback on the component (or if anything goes wrong). All of the styling and features are taken from React-toastify | React-Toastify but built from scratch (mostly) in Anvil

13 Likes

Very interesting! I definitely will play with this in my apps!

1 Like

Oh man. This looks awesome!

1 Like

This is cool, thank you!

1 Like

Great work! This is beautiful. I would love to use this for indicating progress of a task.

@divyeshlakhotia is it possible to manually control the progress bar to allow this to work as a progress indicator?

I would love to update the toast progress indicator from a timer tick event with the progress of a background task.

1 Like

That feature is now added. Just clone the dependency again and you should see a new method update_progress

Note: This will suppress the timeout

Usage

toast = toastify.Toast("Performing Some Acitivity", style="info", timeout = 4)
...
toast.update_progress(0.3)
...
toast.update_progress(0.5)
...
toast.update_progress(1)
3 Likes

Just noticed a minor glitch with the previous versions that was preventing some elements on screen edges from being clicked. Fixed that in the new version.

So awesome! Thank you @divyeshlakhotia for adding this functionality!

I extended this to allow the hide() method to accept a delay keyword parameter. This allowed me to change to a success state then call hide(delay=1) and not have it immediately disappear.

Added the simple demo:

    def progress_button_click(self, **event_args):
    """ Demo the manual update of the toast progress bar """
      toast = toastify.Toast("Progress", style='info')

      n = 10
      for i in range(n):
        toast.update_progress(i/n)
        time.sleep(0.25)
      toast.update_progress(1)
      toast.update('success', 'Progress')
      toast.hide(delay=1)

Also hooked up the close button to .hide()

Here is the clone: clone

4 Likes

Thanks you great Work & Help.

1 Like

Thanks, this is great!

1 Like