Spring-Animated Toast Notifications for JavaScript – Ding

Category: Javascript , Notification , Recommended | November 9, 2026
AuthorYusufCeng1z
Last UpdateNovember 9, 2026
LicenseMIT
Views0 views
Spring-Animated Toast Notifications for JavaScript – Ding

Ding is a JavaScript toast notification library that shows one message at a time and morphs it with spring physics as new notifications arrive.

Features

  • Success, error, warning, info, and loading notifications.
  • Interrupted animations retain their spring momentum.
  • Descriptions, avatar images, and trailing metadata.
  • Primary and secondary action buttons.
  • Promise-driven status changes and progress bars.
  • Timed dismissal, hover and focus pauses, and duplicate counters.
  • Six screen positions and light, dark, or system themes.
  • Optional notification sounds and keyboard controls.
  • Optional adapters for React & Svelte.

See It In Action

How To Use It

Installation

Install the package for your stack.

  • Plain JavaScript: npm install @yusufceng1z/ding
  • React 18+: npm install @yusufceng1z/ding-react
  • Svelte 5: npm install @yusufceng1z/ding-svelte

Basic Usage

For a plain HTML page, import the ES module and mount the toaster once:

<button id="save-button" type="button">Save</button>
<script type="module">
  import { mountToaster, toast } from 'https://cdn.jsdelivr.net/npm/@yusufceng1z/ding/dist/index.js';
  mountToaster({ position: 'top-center' });
  document.querySelector('#save-button').addEventListener('click', () => {
    toast.success('Changes saved');
  });
</script>

For a bundled JavaScript app, use the installed package. mountToaster() returns a cleanup function for unmounting the renderer.

import { mountToaster, toast } from '@yusufceng1z/ding';
const unmount = mountToaster({ position: 'top-center' });
toast.success('Changes saved');

React And Svelte Integration

Render one Toaster near the application root and import toast from the same framework package.

React:

import { Toaster, toast } from '@yusufceng1z/ding-react';
export default function App() {
  return (
    <>
      <Toaster position="top-center" theme="system" />
      <button onClick={() => toast.success('Changes saved')}>Save</button>
    </>
  );
}

Svelte:

<script>
  import { Toaster, toast } from '@yusufceng1z/ding-svelte';
</script>
<Toaster position="top-center" theme="system" />
<button onclick={() => toast.success('Changes saved')}>Save</button>

For a React project using the shadcn registry, this command adds the Ding package and a ding-toaster.tsx wrapper:

npx shadcn@latest add @ding/ding

Promise And Progress Notifications

Pass a Promise-returning saveSettings() function that rejects on failure. Handle the returned Promise’s rejection in the calling code.

toast.promise(saveSettings(), {
  loading: 'Saving settings',
  success: 'Settings saved',
  error: (error) => error instanceof Error ? error.message : 'Save failed',
}).catch(console.error);

Keep the ID from toast.loading() to report progress. If a newer notification takes over the visible toast, Ding ignores updates from the older caller.

const id = toast.loading('Uploading image', { progress: 0 });
toast.update(id, { progress: 0.6 });
toast.update(id, {
  type: 'success',
  title: 'Image uploaded',
  progress: null,
});

Add An Undo Action

An action can change the message after a click. Here, restoreDraft() is your application’s restore function.

toast.success('Draft deleted', {
  action: {
    label: 'Undo',
    onClick: () => {
      restoreDraft();
      return { type: 'info', title: 'Draft restored' };
    },
  },
});

Configure The Toaster

Use toast.configure() for the shared position, theme, sound, and screen-reader labels. The example sets Spanish accessible names for the notification region and dismiss button.

toast.configure({
  position: 'bottom-right',
  theme: 'dark',
  sound: true,
  volume: 0.5,
  labels: {
    region: 'Avisos',
    dismiss: 'Cerrar notificación',
  },
});

Public API Reference

Notification Methods

MethodDescription
toast.success(title, options?)Shows a success notification and returns its string ID.
toast.error(title, options?)Shows an error notification, persistent by default, and returns its ID.
toast.warning(title, options?)Shows a warning notification and returns its ID.
toast.info(title, options?)Shows an information notification and returns its ID.
toast.loading(title, options?)Shows a persistent loading notification and returns its ID.
toast.promise(input, messages)Shows loading and the resolved or rejected state. input is a Promise or a function returning one. Returns that Promise.
toast.update(id, patch)Updates the notification owned by the supplied caller ID; returns no value.
toast.dismiss(id?)Dismisses the specified notification or every notification when called with no ID.
toast.configure(settings)Changes position, theme, accessible labels, or audio settings for the shared toaster.
mountToaster(options?)Mounts the plain DOM renderer; returns an unmount function.

Promise Messages

toast.promise(input, messages) requires the following message fields:

FieldDescription
loadingString displayed while the Promise is pending.
successString or (value) => string callback for the resolved value.
errorString or (error) => string callback for the rejection reason.

Toast Options

OptionDescription
idOptional string identifying the caller. Reuse it for related notifications from the same source.
descriptionAdditional line of text below the title.
actionPrimary button object with label and onClick.
secondarySecondary button object with label and onClick.
imageAvatar or thumbnail URL that replaces the status icon.
metaShort text displayed after the title.
progressNumber from 0 to 1 for a progress bar.
durationAuto-dismiss time in milliseconds. 0 persists. Ordinary status notifications default to 5000.

Update Patch

toast.update(id, patch) accepts the following fields. Changing type or the action buttons recalculates the default dismissal behavior unless the same patch supplies duration.

FieldDescription
titleReplaces the notification title.
descriptionReplaces the description string.
typesuccess, error, warning, info, or loading.
durationChanges the dismissal time in milliseconds.
progressNumber from 0 to 1; null removes the bar.
actionReplaces the primary button; null removes it.
secondaryReplaces the secondary button; null removes it.
metaReplaces trailing text; null removes it.
imageReplaces the avatar URL; null restores the status icon.

Global Settings And Toaster Props

toast.configure(settings) accepts every setting below. mountToaster(options?) and the React/Svelte <Toaster /> components accept only position, theme, and labels.

SettingAccepted values and default
positiontop-left, top-center (default), top-right, bottom-left, bottom-center, bottom-right.
themesystem (default), light, dark.
labelsOptional region and dismiss strings. Defaults: Notifications and Dismiss notification.
soundfalse (default), true for built-in tones, or (type) => void for custom sound.
volumeNumber from 0 to 1; default 0.5 for built-in sound.

Keyboard And Accessibility

The toaster uses an assertive live region for errors and a polite region for other messages.

Escape dismisses a notification unless focus is inside a dialog, menu, or editable control. Alt+T focuses the notification.

Ding respects prefers-reduced-motion and mirrors its position on right-to-left pages.

Alternatives

FAQs

Q: Why does toast.promise() show success for an HTTP error response?
A: fetch() resolves for HTTP error responses. Check response.ok and reject or throw on failure before resolving the request Promise.

Q: Why doesn’t the first notification play a sound?
A: Browsers restrict audio until a user interacts with the page. Enable sound and trigger the notification from a click or key press.

You Might Be Interested In:


Leave a Reply