npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

poptjs

v2.0.2

Published

Beautiful toast notifications with pill-to-card animations, spring physics, and zero dependencies.

Readme

popt

Beautiful toast notifications with pill-to-card animations, spring physics, and zero dependencies.

~11 KB min JS · ~8 KB min CSS · Zero dependencies · TypeScript ready · llms.txt


Install

npm install poptjs
// ESM
import popt from 'poptjs';
import 'poptjs/dist/popt.css';

// UMD / CDN
<script src="https://unpkg.com/poptjs/dist/popt.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/poptjs/dist/popt.min.css">

Quick Start

// Simple pill notification
popt.success('Event saved!');

// Expanded card with description
popt.error({
  title: 'Payment declined',
  description: 'Card ending in 4242 was declined.'
});

API

Methods

| Method | Description | |--------|-------------| | popt.success(opts) | Green checkmark. Confirmations, saves. | | popt.error(opts) | Red X. Failures, declined payments. | | popt.warning(opts) | Orange alert. Low inventory, expiring sessions. | | popt.info(opts) | Blue info. Updates, announcements. | | popt.action(opts) | Purple arrow. Includes action button. | | popt.show(opts) | Gray default. Custom icon optional. | | popt.confirm(opts) | Two-button confirmation. Returns Promise<boolean>. | | popt.prompt(opts) | Input field with submit/cancel. Returns Promise<string\|null>. | | popt.promise(promise, handlers) | Loading → success/error transition. | | popt.dismiss() | Dismiss the most recent toast. | | popt.dismissAll() | Dismiss all toasts. | | popt.isActive() | Returns true if any toast is visible. | | popt.getStackSize() | Returns the number of active toasts. | | popt.init(config) | Set global defaults. |

Every method accepts a string (title-only pill) or an options object.

Toast Options

| Property | Type | Description | |----------|------|-------------| | title | string | Text shown in the pill header | | description | string \| HTMLElement | Expanded card body content | | duration | number \| null | Auto-dismiss ms. null = persistent | | button | { title, onClick } | Action button inside card | | cancel | { title, onClick } | Cancel button (shown alongside action) | | input | { type, placeholder, value } | Input field (used with prompt) | | icon | string | Custom SVG string for badge | | fill | string | Custom badge/progress color | | position | string | Override position for this toast | | expandDelay | number | Pill → card delay in ms | | onDismiss | () => void | Callback when toast is dismissed |

Init Options

| Property | Type | Default | Description | |----------|------|---------|-------------| | position | string | 'top-center' | Default position | | duration | number | 6000 | Default auto-dismiss ms | | expandDelay | number | 1000 | Pill → card delay | | theme | 'dark' \| 'light' \| 'auto' | 'dark' | Color theme | | maxToasts | number | 3 | Max visible toasts |

Positions

top-left · top-center (default) · top-right · bottom-left · bottom-center · bottom-right


Examples

Action Button

popt.action({
  title: 'Booking saved as draft',
  description: 'Resume checkout anytime.',
  button: {
    title: 'Resume checkout',
    onClick: () => window.location = '/checkout'
  }
});

Confirm Dialog

const accepted = await popt.confirm({
  title: 'Delete item?',
  description: 'This action cannot be undone.',
  confirmText: 'Delete',
  cancelText: 'Keep it'
});

if (accepted) {
  // user confirmed
}

Returns false if cancelled, dismissed, or closed.

Prompt

const name = await popt.prompt({
  title: 'Rename event',
  description: 'Enter a new name for this event.',
  placeholder: 'Event name...',
  submitText: 'Rename'
});

if (name !== null) {
  // user submitted a value
}

Returns null if cancelled or dismissed.

Async Promise

popt.promise(fetch('/api/booking'), {
  loading: 'Processing booking...',
  success: 'Booking confirmed!',
  error: 'Something went wrong'
});

// Dynamic messages
popt.promise(fetch('/api/tickets'), {
  loading: 'Loading...',
  success: (data) => ({
    title: 'Loaded!',
    description: `${data.count} tickets found`
  }),
  error: (err) => ({
    title: 'Failed',
    description: err.message
  })
});

Themes

// Dark (default)
popt.init({ theme: 'dark' });

// Light
popt.init({ theme: 'light' });

// Auto (follows system preference)
popt.init({ theme: 'auto' });

Toast Stacking

Multiple toasts stack visually (up to maxToasts). Oldest are dismissed when the limit is reached.

popt.init({ maxToasts: 5 });

popt.success('First');
popt.info('Second');
popt.warning('Third');

Custom Configuration

popt.init({
  position: 'bottom-right',
  duration: 4000,
  expandDelay: 800,
  theme: 'light',
  maxToasts: 5
});

Custom Color

popt.show({
  title: 'Custom notification',
  description: 'With a custom color.',
  fill: '#e040fb'
});

Features

  • Pill → Card animation — Starts as a compact pill, morphs into an expanded card
  • Spring physics — Natural-feeling linear() easing
  • Toast stacking — Multiple toasts with configurable limit
  • Themes — Dark, light, and auto (system preference)
  • Swipe to dismiss — Touch gesture support on mobile
  • Pause on hover — Timer pauses when user interacts
  • Progress bar — Visual countdown synced with dismiss timer
  • Promise support — Loading → success/error transitions
  • Confirm dialogs — Two-button accept/cancel with async/await
  • Prompt input — Text input with submit/cancel, returns Promise
  • Action buttons — Interactive CTAs inside cards
  • 6 positions — Any corner or center, top/bottom
  • Safe area support — Respects mobile notch
  • Reduced motion — Respects prefers-reduced-motion
  • Accessiblerole="status", aria-live="polite"
  • Zero dependencies — Vanilla JS, no framework needed
  • ESM + UMD — Works with bundlers and CDN
  • TypeScript definitions — Full IntelliSense support

Browser Support

All modern browsers (Chrome, Firefox, Safari, Edge). The linear() easing function requires recent browser versions.


License

MIT