@instabase.com/toast
This is the Instabase library for showing toasts in the UI.
Getting started
yarn add @instabase.com/toast
npm install -S @instabase.com/toast
Usage
Initialization
If your webapp is not in an Instabase environment, you will have to add
ToastContainer
to the root of your app. Otherwise, it's already taken care of
for you.
Creating toasts
Each toast call returns that toast's id.
import toast from '@instabase.com/toast';
toast.info('This is an info toast!');
toast.loading('This is a loading toast!');
toast.success('This is a success toast!');
toast.error('This is an error toast!');
Toast config
Toast configs are optional. If desired, you can provide an object with any of
these fields as the second argument in your toast call:
id
: Used to identify your toast and update an existing toastpriority
: Can be either low
or high
. Low priority toasts are
automatically dismissed after 5 seconds. High priority toasts are shown until
the user closes them.
- By default, info and success toasts have low priority, and loading and
error toasts have high priority.
- If you hover over a toast, it will not be automatically dismissed, even
if it has low priority.
description
: String that provides further context. This cannot contain
any JSX. If the description is over 2 lines long, it will be truncated, and a
"View more" button will be shown to see the rest of the description.progressBar
: This is an object that describes the current progress of a
loading toast. Progress bars are not shown in any non-loading toast. Either
percentage
or fraction
must be provided.
percentage
: number, optionalfraction
: object, optional
value
: number, requiredmax
: number, requiredresourceName
: string, optional, used to show the units of the
progress barresourceNamePlural
: string, optional, used to show the units of the
progress bar
primaryButton
: This is an object that describes the primary button that
the user can click to take an action. Either onClick
or href
must be
provided. This can be overridden by the "View more" button if the
description is too long.
label
: string, requiredonClick
: () => void
, optionalhref
: string, optional
secondaryButton
: This is an object that describes the secondary button
that the user can click to take an action. Its type is the same as for
primaryButton
.
Updating toasts
const toastId = toast.loading('Loading...');
toast.success('Success!', { id: toastId });
Dismissing toasts
Dismissing a toast will trigger the exit animation, so the toast won't
disappear immediately.
const toastId = toast.success('Success!');
toast.dismiss(toastId);
Removing toasts
Removing a toast makes it go away immediately. It is the same as the user
clicking the close button on a toast.
const toastId = toast.success('Success!');
toast.remove(toastId);
Clearing toasts
Clearing all toasts removes all toasts immediately.
toast.clear();
Utils
useStatusToast
useStatusToast
is a hook that renders a toast according to a status that
can be loading, success, or error. The hook takes care of using a
consistent toast ID so that only a single toast is created, even when this
status changes. The hook takes in renderer functions for what toast
message and, optionally, what toast config to use for each status.
callPromiseWithToasts
callPromiseWithToasts
is a util that renders a loading toast, calls a
promise, and renders a success toast or error toast according to the
promise's result. This util takes in only what toast message to show for each
loading/success/error status.
Best practices
- Instead of creating multiple toasts, use a single toast ID for all toasts
related to the same operation.
- Keep the toast message across loading/success/error states for all toasts
related to the same operation.
- Put error messages in the description of error toasts, not the title (i.e. the
first argument of the toast call).
- If the error can easily be fixed by the user changing their input (ex:
filling in a required form field, etc.), set the priority of the error toast
to low so that the toast will automatically disappear.
Design decisions
We wanted to keep all toasts consistent, so we don't allow custom timeouts
or JSX in toast descriptions.
Restricting custom timeouts is necessary to avoid surprising the user when
they don't expect toasts to disappear. For example, error toasts have high
priority by default since most users want error toasts to remain on the page
so that they can screenshot or copy the error message.
So far, we haven't seen any instances where JSX was absolutely necessary in
toast content. By restricting toast content to just strings, we can
provide a consistent user experience for toasts, and we can also encourage
app developers to avoid using toasts to show overly complicated
information. Toasts should mainly be used for simple status-like updates.
Why we decided to write this library
We decided to create our own toast library for two main reasons:
- Making it easy in the future for third-party apps to create toasts on
Instabase
- Having full control over the state management of toasts
In the future, third-party apps can just import @instabase.com/toast
as a peer
dependency to create toasts on Instabase. This allows us to enforce our design
decisions on all apps, instead of requiring apps to use an open-source
library in a very specific way.
We need full control over toast state management because in the future, we
need some way to handle notifications propagated from the backend. If we use an
open-source toast library, we can immediately show these backend notifications
whenever they're received on the frontend. However, it would be difficult to do
anything more complicated if we don't have full control over toast state
management.