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

sleepy-countdown

v1.0.0

Published

A configurable React countdown timer component with modern, classic, and minimal designs.

Readme

⏳ sleepy-countdown

A drop-in React countdown timer with three pre-designed looks and a CSS-variable theming API.

npm downloads bundle size types license

sleepy-countdown is a single React component that counts down to a date and renders itself as a self-contained card. Pick one of three designs with the type prop (modern, classic, minimal), choose how fine-grained the clock is with resolution, and recolor everything through --sleepy-countdown-* CSS custom properties. Zero runtime dependencies, styles bundled into the JS, full TypeScript types, and the card never changes size — not when units drop off, not when the countdown ends.

Install

npm install sleepy-countdown     # or: pnpm add / yarn add / bun add

react and react-dom (v18 or newer) are peer dependencies — your app provides them. Nothing else is installed: the package ships no runtime dependencies of its own.

Quick start

import { SleepyCountdown } from 'sleepy-countdown';

export function Example() {
  return (
    <SleepyCountdown
      target={new Date('2027-01-01T00:00:00')}
      type="modern"
      resolution="second"
      title="New Year"
      description="Counting down to 2027"
      end_message="Happy New Year!"
    />
  );
}

That's the whole setup. No CSS import is required — the styles are injected by the bundle, so the component looks right the moment it renders.

The three types

Each type renders the same computed numbers with a different treatment. All three sit inside an identical frame (title → description → fixed-height timer), so you can mix them in one grid without the layout going ragged.

| Type | Look | | --- | --- | | modern (default) | Rounded cards, accent-colored digits, small caption labels | | classic | Flip-clock cards split across the middle — each digit change replays a flip-in animation | | minimal | Bare colon-separated numbers with tiny labels, no card chrome |

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | target | Date \| string \| number | (required) | When the countdown ends — a Date, an ISO string, or epoch milliseconds. | | type | 'modern' \| 'classic' \| 'minimal' | 'modern' | Pre-designed visual style. An unknown value falls back to modern. | | resolution | 'day' \| 'hour' \| 'minute' \| 'second' | 'day' | Finest unit shown; finer units are hidden. | | title | ReactNode | — | Heading shown above the timer. | | description | ReactNode | — | Muted text shown below the title. | | end_message | ReactNode | 'Countdown has ended.' | Replaces the timer once target passes. | | className | string | — | Extra class on the root element. | | style | CSSProperties | — | Inline styles / CSS-variable overrides on the root element. |

title, description, and end_message are ReactNodes, so they take markup — not just strings.

How resolution works

Units are always coarse → fine, and resolution sets where the list stops. Nothing is rolled up: at resolution="hour" the days card still shows days, and the leftover minutes and seconds are simply not displayed.

| resolution | Units rendered | | --- | --- | | day | Days | | hour | Days · Hours | | minute | Days · Hours · Minutes | | second | Days · Hours · Minutes · Seconds |

Values are zero-padded to two digits, and the component re-renders once per second regardless of resolution.

Theming

Every cosmetic value is a CSS custom property with a sensible default, so you can recolor the component from your own stylesheet or the style prop. The default palette is Catppuccin Mocha; override any variable to switch flavors — or to your own brand.

Fonts are deliberately not set — text inherits your app's typography. See docs/style_inheritence.md for the full contract.

| Variable | Default (Catppuccin Mocha) | Controls | | --- | --- | --- | | --sleepy-countdown-fg | #cdd6f4 (Text) | Primary text color | | --sleepy-countdown-muted | #a6adc8 (Subtext0) | Muted text (description, unit labels) | | --sleepy-countdown-accent | #cba6f7 (Mauve) | Accent color (modern digits) | | --sleepy-countdown-surface | #1e1e2e (Base) | The card's background | | --sleepy-countdown-border | 1px solid #313244 | The card's border (full shorthand) | | --sleepy-countdown-surface-radius | 18px | The card's corner rounding | | --sleepy-countdown-padding | 22px 26px | The card's inner padding | | --sleepy-countdown-shadow | soft dark drop shadow | The card's shadow | | --sleepy-countdown-card-bg | #313244 (Surface0) | The individual time-unit cards | | --sleepy-countdown-card-fg | #cdd6f4 (Text) | Text on the time-unit cards (classic) | | --sleepy-countdown-radius | 12px | Unit-card corner rounding | | --sleepy-countdown-gap | 10px | Space between unit cards | | --sleepy-countdown-unit-width | 68px | Width of one unit card | | --sleepy-countdown-timer-height | 96px | Height of the timer area |

/* Example: override to Catppuccin Latte (the light flavor). */
.my-page .sleepy-countdown {
  --sleepy-countdown-surface: #eff1f5;
  --sleepy-countdown-border: 1px solid #ccd0da;
  --sleepy-countdown-card-bg: #ccd0da;
  --sleepy-countdown-accent: #8839ef;
  --sleepy-countdown-fg: #4c4f69;
  --sleepy-countdown-muted: #6c6f85;
}

Target .sleepy-countdown, not :root. The component sets its defaults directly on .sleepy-countdown, and a custom property set on an element always beats one inherited from an ancestor — so :root overrides silently do nothing.

Class names are stable and sleepy--prefixed (.sleepy-countdown, .sleepy-countdown--modern, .sleepy-modern__value, …) precisely so this kind of override keeps working. They're part of the public API.

Behavior notes

  • The card never resizes. The timer area is a fixed-height box, so dropping units via resolution, switching type, or ending the countdown all leave the footprint untouched. Grids of timers stay aligned.
  • Ends gracefully. Once target passes, end_message takes the timer's place in the same box; the ticking stops mattering (the remaining time clamps at zero).
  • target is reactive. Change it and the countdown re-syncs immediately rather than waiting for the next tick.
  • One interval per component, cleared on unmount.

TypeScript

Types ship with the package — no @types/ install. The public surface:

import type {
  SleepyCountdownProps,
  Resolution,      // 'day' | 'hour' | 'minute' | 'second'
  CountdownType,   // 'modern' | 'classic' | 'minimal'
} from 'sleepy-countdown';

Both ESM (import) and CommonJS (require) builds are published.

Seen in the wild

countdown-timers — a self-hostable web app that renders a grid of these timers from a single YAML file. Available as a Docker image.

Development

npm install
npm run demo     # live demo app from examples/, via Vite
npm test         # vitest
npm run build    # tsup → dist/ (ESM + CJS + .d.ts)

Documentation

License

MIT