YusufCeng1z/ding has 509 GitHub stars and 12 forks. GitHot measured +178 stars in 24 hours. Last checked 2026-11-11 09:28 UTC. Last push 2026-11-06.
Notificaciones emergentes con física de muelles real. Una sola notificación cambia de forma en el mismo sitio. Sin dependencias. Compatible con React, Svelte y DOM nativo.
Crecimiento de estrellas medido
- in 24h
- +178
- in 7 days
- Actualización retrasada
- in 15 days
- Actualización retrasada
- in 1 month
- Actualización retrasada
Cambios netos en períodos que se solapan, no totales diarios. Los datos no disponibles se dejan en blanco. Las estrellas indican interés, no calidad.
README.md
Original
Ding
Toasts with real spring physics.
One toast that morphs in place. No dependencies. React, Svelte or plain DOM.
Why Ding
- One toast at a time. A new call morphs the toast on screen instead of stacking a second one.
- Real springs. Size, shape and text move on a spring solver, so interrupting an animation keeps its momentum.
- No stylesheet. Styles are injected from JavaScript. Nothing to import.
- Light, dark and system themes, six positions, right-to-left support.
- Rich content. Description, avatar, buttons, progress bar, a countdown line, small trailing text.
- Accessible by default. Persistent live regions, keyboard dismiss,
prefers-reduced-motion. - Optional sound. A soft built-in tone per status, or plug in your own.
- Strict TypeScript, ESM and CommonJS builds.
Install
npm i @yusufceng1z/ding-react # React 18+
npm i @yusufceng1z/ding-svelte # Svelte 5
npm i @yusufceng1z/ding # plain DOM
Each framework package depends on the small @yusufceng1z/ding core, so you install only one.
Quick start
Render the toaster once, then call toast from anywhere.
React
import { Toaster, toast } from '@yusufceng1z/ding-react';
export default function App() {
return (
<>
<Toaster position="top-center" theme="system" />
<button onClick={() => toast.success('Saved')}>Save</button>
</>
);
}
Svelte 5
<script>
import { Toaster, toast } from '@yusufceng1z/ding-svelte';
</script>
<Toaster position="top-center" theme="system" />
<button onclick={() => toast.success('Saved')}>Save</button>
Plain DOM
import { mountToaster, toast } from '@yusufceng1z/ding';
mountToaster({ position: 'top-center' });
toast.success('Saved');
Usage
toast.success('Saved');
toast.error('Payment failed', { description: 'Card declined' });
toast.warning('Storage almost full');
toast.info('New version available');
toast.loading('Uploading…');
Every call returns the toast id.
Promises and updates
toast.promise(save(), {
loading: 'Saving…',
success: 'Saved',
error: (err) => `Could not save: ${err.message}`,
});
const id = toast.loading('Uploading photo…', { progress: 0 });
toast.update(id, { progress: 0.6 });
toast.update(id, { type: 'success', title: 'Photo uploaded', progress: null });
Only the newest caller can update the shared toast, so a slow request that finishes late cannot overwrite a newer message.
Actions
An onClick may return a patch. The toast then morphs in place instead of closing.
toast.success('Message deleted', {
action: {
label: 'Undo',
onClick: () => {
restore();
return { type: 'info', title: 'Restored' };
},
},
});
Options
| Option | Description |
|---|---|
description |
Second line of text |
action |
{ label, onClick }, the main button |
secondary |
{ label, onClick }, a quieter button beside the action |
image |
Avatar or thumbnail URL, replaces the status icon |
meta |
Small trailing text, such as now or ⌘V |
progress |
0 to 1, draws a thin bar at the bottom |
duration |
Milliseconds before it closes. 0 keeps it until dismissed. Default 5000 |
id |
Reuse an id so repeated calls from one place stay one caller |
Errors, loading toasts and toasts with a button stay until dismissed. Hover and keyboard focus pause the timer. Repeating the same toast adds a counter (×2).
Configure
toast.configure({
position: 'bottom-right', // top-left, top-center, top-right, bottom-left, bottom-center, bottom-right
theme: 'dark', // system, light, dark
sound: true,
volume: 0.5,
});
toast.dismiss(id); // one toast
toast.dismiss(); // all
Sound
Off by default. With sound: true each status plays its own soft tone: success rises, error falls, warning double-taps, info is a single note. Loading is silent and progress updates never make a sound. Browsers keep audio locked until a click or key press.
To use your own sounds, pass a function. It receives success, error, warning, info or loading:
toast.configure({ sound: (type) => mySounds.play(type) });
Accessibility
- Messages go through persistent live regions: errors are assertive, everything else is polite.
Escdismisses.Alt+Tmoves focus into the toast.- Respects
prefers-reduced-motion. - Mirrors automatically on right-to-left pages.
Packages
| Package | Description |
|---|---|
@yusufceng1z/ding |
Springs, timers, store, sound and the plain DOM renderer |
@yusufceng1z/ding-react |
React renderer |
@yusufceng1z/ding-svelte |
Svelte 5 renderer |
The core owns all behavior. The framework packages only render.
Development
pnpm install
pnpm test # unit tests
pnpm typecheck
pnpm build # build all packages
pnpm dev # docs and demo site
The docs site lives in apps/docs. A machine-readable summary is in apps/docs/public/llms.txt.
License
Explorar proyectos relacionados
ytdl-org/youtube-dl
Programa de línea de comandos para descargar vídeos de YouTube.com y otros sitios de vídeo
141,527 estrellasexcalidraw/excalidraw
Pizarra virtual para esbozar diagramas con aspecto de dibujo a mano
135,492 estrellasgodotengine/godot
Godot Engine – Motor de videojuegos 2D y 3D multiplataforma
119,942 estrellasmrdoob/three.js
Biblioteca 3D de JavaScript.
118,122 estrellas