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

@thinkdx/storybook-addon-chronokit

v1.1.0

Published

Mock time in your Storybook stories — freeze the clock or fast-forward it with a single decorator.

Downloads

2,230

Readme

storybook-addon-chronokit

Mock time in your Storybook stories. Chronokit replaces the global clock so a story can render at any moment you choose — frozen for a deterministic screenshot, or fast-forwarded so a minutes-long flow plays out in seconds.

▶︎ Live demo & docs: https://thinkdx.github.io/storybook-addon-chronokit/

A flash-sale banner counting down through its warning and critical states and expiring in seconds, driven by a mocked clock running 30× real time

It's a single preview decorator driven by one story parameter:

parameters: {
  date: {
    now: new Date('2025-06-01T12:00:00').getTime(),
    canProgress: true, // false = frozen
    clockSpeed: 30,     // optional real-time multiplier
  },
}

Why?

Anything that renders differently depending on "what time is it now?" is painful to build and review against the real clock:

  • Countdowns and timers — you'd have to wait for them to reach interesting states.
  • Relative timestamps ("2 minutes ago") — never look the same twice.
  • Expiry / scheduling UI — sales, sessions, holds, tokens.

Chronokit makes those states deterministic (freeze the clock) or fast (speed it up) without touching your component code — it mocks Date and the scheduling APIs (setTimeout, setInterval, requestAnimationFrame).

Requirements

  • Storybook 9 or later

Installation

Status: chronokit isn't published to npm yet — see Status. The setup below shows the intended API.

npm install --save-dev @thinkdx/storybook-addon-chronokit

Setup

Register the decorator globally in .storybook/preview:

// .storybook/preview.ts
import type { Preview } from '@storybook/react-vite'
import { mockDateDecorator } from '@thinkdx/storybook-addon-chronokit'

const preview: Preview = {
  decorators: [mockDateDecorator],
}

export default preview

Recommended setup

The pattern we recommend: register the decorator globally, pin a single canonical now, and let the clock run only for interactions:

// .storybook/preview.ts
const STORYBOOK_NOW = new Date('2025-06-01T12:00:00').getTime()

const preview: Preview = {
  decorators: [mockDateDecorator],
  parameters: {
    date: {
      now: STORYBOOK_NOW,
      canProgress: (ctx) => !!ctx.playFunction,
    },
  },
}

Why this is a good default:

  • Deterministic snapshots. Every story renders at the same frozen instant, so visual-regression tools (e.g. Chromatic) stop flapping on dates, relative timestamps, and "today" highlights.
  • Interactions still work. Stories with a play function usually rely on waits and timers — the predicate gives those a live clock automatically, so you never have to remember canProgress: true per story.

Any story can still override now / canProgress / clockSpeed for its own needs.

Usage

Control the clock with the date parameter on any story, a component's meta, or globally in preview.

Freeze the clock (static time)

export const Frozen = {
  // Shorthand — a string, number (ms), or Date freezes the clock at that instant.
  parameters: { date: '2025-06-01T12:00:00' },
}

Let it run, optionally fast (dynamic time)

export const FastForward = {
  parameters: {
    date: {
      now: '2025-06-01T12:00:00',
      canProgress: true,
      clockSpeed: 20, // 20× faster than wall time
    },
  },
}

The date parameter

| Field | Type | Default | Description | | ------------- | ------------------------------------------ | ------- | ------------------------------------------------------------------------------------------ | | now | string \| number \| Date | — | The mocked "current" time. Required (in object form). | | canProgress | boolean \| ((context) => boolean) | false | false freezes the clock at now; true lets it advance. May be a predicate (see below). | | clockSpeed | number | 1 | Real-time multiplier while progressing — 30 runs time 30× faster. |

Deciding canProgress per story

canProgress can be a function that receives the story context and returns a boolean, so you can set the rule once instead of per story. A common case: stories with a play function usually rely on waits and timers, so you want the clock running for those — set this globally in preview:

const preview: Preview = {
  decorators: [mockDateDecorator],
  parameters: {
    date: {
      now: '2025-06-01T12:00:00',
      canProgress: (ctx) => !!ctx.playFunction, // run the clock for play stories
    },
  },
}

Individual stories can still override with an explicit canProgress: true | false.

Using it in docs (MDX) pages

The decorator replaces global browser APIs, so two stories with different mocked clocks can't share one document. When you embed multiple examples on a single docs page, render each in its own iframe so each gets an isolated clock:

// .storybook/preview.ts
const preview: Preview = {
  decorators: [mockDateDecorator],
  parameters: {
    docs: { story: { inline: false } },
  },
}

How it works

On each story, the decorator swaps the global Date, setTimeout, setInterval, requestAnimationFrame, and cancelAnimationFrame for mocked versions tied to the date parameter, then restores the originals when the story unmounts — so a mocked clock in one story never leaks into the next.

Because the swap is global, your components don't need to know chronokit exists: they call Date.now() / requestAnimationFrame as usual and transparently see the mocked clock.

Status

This is the first edition. The addon and a full set of examples and documentation live in this Storybook (see the demo link above). Packaging for npm (exports, build, published artifact) is in progress.

License

MIT