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

flicker-dot

v0.2.0

Published

The runtime player for Flicker — dot-grid loading spinners you design at flicker.laurie.fyi.

Readme

Flicker: a dot-grid spinner library

Tests npm version license

flicker-dot

A dot-grid loading spinner for React and SwiftUI. 49 dots, one flip-dot animation, zero runtime dependencies.

Every spinner ships from flicker.laurie.fyi, where you design the frame-by-frame pattern by hand. This package is the player. It's the part that actually renders what you built, in your own app.

npm install flicker-dot
import { FlickerSpinner } from 'flicker-dot';

<FlickerSpinner grids={myGrids} />

That's the whole API surface for the common case. Everything else in this README is what happens when "the common case" isn't quite enough.

Why this exists

Most loading spinners are one of three things: a spinning circle, a pulsing skeleton, or somebody's Lottie file that's slightly too big for what it's doing. Flip-dot displays, the mechanical split-flap boards you see in old train stations, do something different. Each dot is binary, on or off, and the whole picture is just a sequence of frames. That's a great fit for CSS keyframes: no JS timer, no re-renders, and a hard mechanical snap between states instead of an eased fade.

flicker-dot is that idea, packaged. You design the dot pattern visually, export it, and this component plays it back as a real SVG, styled with CSS custom properties, honoring prefers-reduced-motion by default.

More on why this exists as its own thing: Flicker's origin story.

Usage

import { FlickerSpinner } from 'flicker-dot';

function LoadingState() {
  return (
    <FlickerSpinner
      grids={grids}
      onColor="#262626"
      offColor="#e5e5e5"
    />
  );
}

grids is the one required prop, an ordered array of frames, where each frame is a flat array of 49 booleans (a 7×7 grid, indexed row * 7 + col). You'll get this from the Flicker editor as a paste-ready export; you're not meant to hand-write it.

To get it: open flicker.laurie.fyi, open or create a spinner, and go to its Code panel. The CLI tab gives you the npm install command plus a live usage snippet wired to that spinner's grids. The Manual tab exports the same pattern as a static SVG, React component, Flutter widget, or Lottie JSON, if you'd rather copy the output directly instead of pulling in this package.

Props

| Prop | Type | Default | What it does | |---|---|---|---| | grids | FlickerGrids | — | Required. The frame data. | | onColor | string | #262626 | Color of a lit dot. Any valid CSS color. | | offColor | string | #e5e5e5 | Color of an unlit dot. | | theme | { on, off } | — | Shorthand for the pair above. Explicit onColor/offColor win if both are set. | | variant | '7x7' \| '5x5' | '7x7' | Full grid, or the derived inner 5×5 "safe area." | | size | number | 28 (7×7) / 16 (5×5) | Render size in px. | | playing | boolean | true | Pause the animation without unmounting it. | | speed | number | 1 | Playback rate multiplier. 2 runs twice as fast. | | reverse | boolean | false | Plays the frame sequence backward. | | fit | 'contain' \| 'cover' \| 'fill' | 'contain' | How the grid scales in a non-square box. | | title | string | 'Loading' | Accessible label (aria-label + <title>). | | className | string | — | Passed to the root <svg>. | | style | CSSProperties | — | Merged into the root <svg> style, after the color vars. |

Theming with CSS variables

onColor and offColor accept anything CSS accepts, including var(--your-token) or currentColor. That means you can theme a spinner from your app's existing design tokens with no extra plumbing:

<FlickerSpinner
  grids={grids}
  onColor="var(--fg)"
  offColor="var(--bg-subtle)"
/>

If your CSS variable changes on a [data-theme="dark"] toggle, the spinner follows it automatically, no re-render, no JS theme detection. This is the whole reason the colors are CSS custom properties on the SVG root instead of baked into the markup.

Reduced motion

Every spinner instance carries a scoped prefers-reduced-motion: reduce rule that disables the animation entirely. You don't opt into this. It's on by default.

What this package is not

flicker-dot renders. It does not export SVG strings, React components, or Flutter code. The design-time export tooling lives in the Flicker app itself, not in this package. If you're looking to generate spinner code rather than render a live component, that's a different tool, and it's closed source.

There's also no imperative playback controller in this version. No ref.play() / ref.pause(). The playing and speed props cover the declarative 90% of cases. An imperative API is a real rewrite (particularly for a future Flutter player), and it's parked until there's a concrete reason to build it. If you hit that wall, an issue with your use case is the fastest way to move it up the list.

SwiftUI

The same player for iOS, macOS, tvOS, watchOS and visionOS, as a Swift package in this repo. It reads the same grids data and matches the React player's geometry, timing and props, drawing each frame in a SwiftUI Canvas instead of CSS keyframes.

In Xcode, go to File → Add Package Dependencies… and paste https://github.com/laurieesc/flicker-dot. Or in Package.swift:

.package(url: "https://github.com/laurieesc/flicker-dot", from: "0.2.0")
import FlickerDot

FlickerSpinner(grids: grids, onColor: .primary, offColor: .secondary.opacity(0.2))

grids is the same flat 49-boolean frames the React player takes. The editor doesn't have a Swift tab yet, so for now copy the grids array from the CLI tab's snippet into a .json file in your app and decode it:

let grids = try JSONDecoder().decode(FlickerGrids.self, from: data)

| Parameter | Type | Default | What it does | |---|---|---|---| | grids | FlickerGrids | — | Required. The frame data. | | onColor | Color? | #262626 | Color of a lit dot. | | offColor | Color? | #e5e5e5 | Color of an unlit dot. | | theme | FlickerTheme? | — | Shorthand for the pair above. Explicit onColor/offColor win if both are set. | | variant | FlickerVariant | .grid7x7 | Full grid, or the derived inner 5×5 (.grid5x5). | | size | CGFloat? | 28 (7×7) / 16 (5×5) | Render size in points. | | playing | Bool | true | Pausing holds the current frame; resuming carries on from it. | | speed | Double | 1 | Playback rate multiplier. 2 runs twice as fast. | | reverse | Bool | false | Plays the frame sequence backward. | | title | String | "Loading" | Accessibility label. |

className and style become ordinary SwiftUI modifiers. There's no fit, since the spinner is always square. Colors are SwiftUI Colors, so .primary or an asset-catalog color follows light and dark mode the way a CSS variable does on the web. Reduce Motion holds the spinner on its first frame.

Supports iOS 15, macOS 12, tvOS 15, watchOS 8 and visionOS 1 and later. The Swift package and the npm package share one version number and one changelog, so every release tags both.

Implementations

| Platform | Package | Status | |---|---|---| | React | flicker-dot (this repo) | Stable | | SwiftUI | FlickerDot Swift package (this repo) | New | | Flutter | — | Not yet published. Ping the maintainer if you're building one. |

Contributing

See CONTRIBUTING.md. Short version: there's a test suite, CI runs it on every PR, and a green check is the bar.

License

MIT © 2026 Laura Escobar