Published on

Shadcn Toasts Duration Issues: Fixing Custom Timer Problems

Authors
  • Name
    Ripal & Zalak
    Twitter

Introduction

Shadcn UI toasts provide a sleek and flexible notification system inspired by the popular react-hot-toast library. However, developers often encounter issues when trying to set custom durations or implement timer bars that reflect the toast's lifetime. This guide provides solutions to these challenges while maintaining a clean implementation.


The Problem

The primary issue arises when custom durations for toasts do not override the default duration set by the Shadcn UI or its underlying Radix ToastProvider. Despite passing the duration prop, the toasts seem to adhere to a hardcoded default duration (usually 5000ms). Additionally, aligning a custom progress bar with the toast's duration can be challenging.


Solutions

1. Pass duration to ToastProvider

To ensure custom durations are respected, pass a duration prop to the ToastProvider component. This sets the default duration for all toasts, which can then be overridden by individual toast durations.

Example:

<ToastProvider duration={3000}>
  <Toast key={id} duration={duration}>
    <div className="flex w-full flex-col">
      <div className="flex w-full items-center justify-start gap-2 p-2">
        <ToastTitle>{title}</ToastTitle>
        <ToastDescription>{description}</ToastDescription>
      </div>
      <TimerBar max={duration || 3000} />
    </div>
  </Toast>
</ToastProvider>

2. Update use-toast.ts Reducer

Ensure the custom duration passed to a toast is respected by modifying the reducer logic in use-toast.ts.

Updated Reducer:

case "ADD_TOAST":
  return {
    ...state,
    toasts: [
      {
        ...action.toast,
        duration: action.toast.duration || TOAST_REMOVE_DELAY,
      },
      ...state.toasts,
    ].slice(0, TOAST_LIMIT),
  };

This ensures that each toast uses the duration provided in the toast() function call or falls back to the default TOAST_REMOVE_DELAY.

3. Sync Timer Bar with Duration

Create a TimerBar component that visually represents the toast's remaining duration.

TimerBar Example:

import React, { useEffect, useState } from 'react'

export const TimerBar = ({ max }: { max: number }) => {
  const [progress, setProgress] = useState(100)

  useEffect(() => {
    const interval = setInterval(() => {
      setProgress((prev) => Math.max(prev - 100 / (max / 10), 0))
    }, 10)

    return () => clearInterval(interval)
  }, [max])

  return (
    <div className="h-1 w-full bg-gray-300">
      <div
        className="h-full bg-blue-500"
        style={{ width: `${progress}%`, transition: 'width 0.1s linear' }}
      ></div>
    </div>
  )
}

4. Debug Duration Conflicts

Check if conflicting duration values are passed in different layers (e.g., ToastProvider, individual toast instances, or the reducer). Use console.log to verify which duration is applied.

Debugging Example:

console.log('Toast Duration:', action.toast.duration)
console.log('Default Duration:', TOAST_REMOVE_DELAY)

Best Practices

  • Consistent Duration Defaults: Use a central constant like TOAST_REMOVE_DELAY for default durations.
  • Customizable Timer Bar: Ensure the timer bar dynamically adjusts to the duration for seamless UX.
  • Avoid Hardcoding: Pass durations explicitly where necessary to avoid falling back to unintended defaults.

FAQs

1. Why doesn’t my custom duration work? Check if the duration prop is correctly passed to both ToastProvider and individual toasts. Ensure the reducer logic respects the custom duration.

2. How can I make the timer bar reflect the toast duration? Use a dynamic component like TimerBar that updates its progress based on the duration.

3. What’s the default duration for Shadcn toasts? The default is typically 5000ms, but it can vary depending on the implementation or library version.


Conclusion

Customizing toast durations and implementing timer bars in Shadcn UI requires understanding how ToastProvider, reducers, and individual toasts handle durations. By ensuring proper duration handling and syncing timer bars, you can create a polished and user-friendly notification system. Experiment with the solutions provided to enhance your toasts further.