ToastJam: An Opinionated Toast Notification Component

Introduction

Toast notifications are a vital part of modern user interfaces, providing users with real-time feedback without disrupting their workflow. With ToastJam, I set out to create a highly opinionated toast component that simplifies implementation while offering a polished default experience.

This component focuses on two things:

  1. Style and animation – Predefined, visually appealing designs.
  2. Developer control over the essentials – The type of notification (info, warning, success, error) and key attributes like duration and message.

Why Opinionated?

The philosophy behind ToastJam is to make toast notifications effortless for developers by handling styling and animations internally. Instead of offering an endless list of configurations, it provides well-crafted defaults that suit most use cases. This opinionated approach eliminates the need to make countless design decisions, allowing developers to focus on the functionality of their applications.

However, ToastJam doesn’t sacrifice flexibility where it matters:

  • You can easily define the type of notification (e.g., success or error).
  • You can control how long the toast stays visible and its content via a simple API.

How ToastJam Works

Setup

To use ToastJam, you start by placing the ToastProvider at the root of your application tree. This provider manages the state of all active toasts and ensures they are rendered at the correct position on the screen.

Here’s a basic setup:

import { ToastProvider } from './components/ToastProvider'

function App() {
  return (
    <ToastProvider position="top-right">
      <MainApp />
    </ToastProvider>
  )
}

The position prop determines where the notifications will appear (e.g., top-right, bottom-center, etc.).

Triggering Toasts with the useToast Hook

Once the provider is in place, you can use the useToast hook to create notifications from any component in your application. The hook exposes a createToast function, which accepts an options object with the following arguments:

  • variant: The type of notification (info, warning, success, error).
  • duration: How long the toast stays visible (in milliseconds).
  • message: The content of the toast.

Example usage:

import { useToast } from './useToast'

function ExampleButton() {
  const { createToast } = useToast()

  return (
    <button
      onClick={() =>
        createToast({
          variant: 'success',
          duration: 3000,
          message: 'Your changes were saved successfully!',
        })
      }
    >
      Show Toast
    </button>
  )
}

Features

1. Predefined Styles and Animations

ToastJam takes care of the visuals:

  • Smooth entry and exit animations powered by Framer Motion.
  • Professionally crafted styles for each variant (info, warning, success, error).

Developers no longer need to worry about CSS or animation tuning.

2. Flexible Notification Types

ToastJam provides four notification types out of the box:

  • Success: Indicates a positive action, such as saving changes.
  • Error: Highlights something that went wrong.
  • Warning: Alerts users about potential issues.
  • Info: Displays general information.

Each type comes with its own icon and color scheme, ensuring consistent user experience.

3. Developer-Friendly API

ToastJam’s API is designed to be minimal and intuitive:

  • The ToastProvider handles all the heavy lifting.
  • The useToast hook simplifies creating notifications with just one function.

Here’s how it looks in action:

const { createToast } = useToast()

createToast({
  variant: 'error',
  duration: 5000,
  message: 'Something went wrong!',
})

Example Use Case: Dynamic Notifications

Let’s say you want to render a toast with a random message when a user clicks a button. Here’s how you can achieve it with ToastJam:

import { useToast } from './useToast'
import { TOAST_MESSAGES } from './constants'

function RandomToastButton() {
  const { createToast } = useToast()

  function getRandomMessage() {
    return TOAST_MESSAGES[Math.floor(Math.random() * TOAST_MESSAGES.length)]
  }

  return (
    <button
      onClick={() =>
        createToast({
          variant: 'info',
          duration: 3000,
          message: getRandomMessage(),
        })
      }
    >
      Show Random Toast
    </button>
  )
}

Challenges and Decisions

Opinionated Styling

ToastJam deliberately enforces a consistent visual style. While this simplifies development, it may not suit developers who prefer full control over the design. However, customization could be added in future versions.

Focus on Essentials

Instead of adding features like queueing or persistent toasts, ToastJam prioritizes simplicity. Notifications are ephemeral by design.

Accessibility for Keyboard Users

ToastJam is designed to be accessible for all users, including those who rely on keyboards for navigation. One key feature is the ability to dismiss toast notifications by pressing the Escape key. This allows users to quickly close notifications without the need for a mouse, making interactions smoother and more inclusive.

Live Demo and Repository

Curious to see ToastJam in action? Check out the live demo or visit the GitHub repository to explore the source code, installation instructions, and examples.

Conclusion

ToastJam is an opinionated toast notification component that simplifies how developers implement notifications. By focusing on styling, animations, and essential customization options, it delivers a polished experience out of the box. Whether you need success messages, error alerts, or just a splash of information, ToastJam is a perfect fit for modern React applications.

Try it today and see how ToastJam can transform your UI notifications! 🎉