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

solari-split-flap

v1.0.0

Published

A physically accurate split-flap (Solari board) display built with vanilla HTML, CSS, and JavaScript. No dependencies.

Downloads

109

Readme

Solari Split-Flap Display

A physically accurate split-flap (Solari board) display built with vanilla HTML, CSS, and JavaScript. No dependencies.

See it live →

Split-flap display showing a quote

Features

  • Physically correct drum mechanics: each cell has a single drum that only spins forward, cycling through every intermediate character in sequence (space → A–Z → 0–9 → punctuation), just like real Solari hardware
  • Deceleration: flaps spin fast at the start and slow down as they settle on the target character
  • Synthesized click sound: Web Audio API generates a short filtered-noise burst per flip (no audio files needed). Activates on first user interaction
  • Author names in yellow: lines prefixed with @ render in gold, right-aligned
  • Cascading stagger: cells flip left-to-right, top-to-bottom with a 50ms delay per cell
  • 10 color themes: press T to cycle through dark and light hue variations (classic, mint, ocean, purple, amber, rose, fog, sage, lavender)
  • HSL theme engine: generateTheme(hue, sat, mode) calculates physically correct flap colors: top flap lighter (catches light), bottom flap darker (in shadow), board recessed behind both
  • Responsive: scales down on tablet and mobile
  • Zero dependencies: single HTML file, no build step

Install

npm install solari-split-flap

Usage

Vanilla JS

import { SolariBoard } from 'solari-split-flap';

const board = new SolariBoard(document.getElementById('board'), {
  cols: 20,
  rows: 8,
  theme: 'ocean',
  quotes: [
    ['HELLO WORLD', '', '@SOLARI'],
    ['STAY HUNGRY.', 'STAY FOOLISH.', '', '@STEWART BRAND'],
  ],
});
board.start();

React

import { Solari } from 'solari-split-flap/react';

function App() {
  return (
    <Solari
      cols={20}
      rows={8}
      theme="mint"
      quotes={[
        ['HELLO WORLD', '', '@SOLARI'],
        ['STAY HUNGRY.', 'STAY FOOLISH.', '', '@STEWART BRAND'],
      ]}
    />
  );
}

Props: cols, rows, theme, quotes, sound, flipMs, charDelay, holdMs, autoStart, className, style, onReady (receives the board instance).

CDN

<div id="board"></div>
<script src="https://unpkg.com/solari-split-flap"></script>
<script>
  const board = new SolariBoard(document.getElementById('board'), {
    theme: 'purple'
  });
  board.start();
</script>

Static HTML

Open index.html in a browser. That's it.

Customization

Edit the quotes array in the <script> block. Each quote is an array of lines:

var quotes = [
  ['FIRST LINE',
   'SECOND LINE',
   '',
   '@AUTHOR NAME'],   // @ prefix = yellow, right-aligned

  ['ANOTHER QUOTE',
   '',
   '@SOMEONE'],
];

Configuration variables

| Variable | Default | Description | |----------|---------|-------------| | COLS | 20 | Number of columns (characters per row) | | ROWS | 8 | Number of rows | | FLIP_MS | 150 | Single flap animation duration (ms) | | CHAR_DELAY | 50 | Stagger between cells in cascade (ms) | | HOLD_MS | 5000 | Time to hold a finished quote before cycling (ms) |

Themes

Press T to cycle through the built-in themes. You can also create your own:

// generateTheme(hue, saturation, mode)
// hue: 0-360, sat: 0-100, mode: 'dark' or 'light'
var theme = generateTheme(155, 30, 'dark');  // mint dark
applyTheme(theme);

The theme engine uses HSL to calculate physically correct values:

| Surface | Dark mode | Light mode | Why | |---------|-----------|------------|-----| | Body bg | L: 6% | L: 95% | Deepest layer | | Board bg | L: 10% | L: 88% | Recessed behind flaps | | Top flap | L: 18% | L: 82% | Catches light from above | | Bottom flap | L: 14% | L: 76% | In shadow below split | | Gap line | L: 6% | L: 70% | Shadow between flap halves |

All colors use CSS custom properties (--sf-*), so you can also override them directly in CSS.

For achromatic themes (saturation 0), author names stay yellow. For chromatic themes, author names use the theme's own hue at high saturation for a cohesive feel.

Theme variations

Embedding

Drop the HTML into any page. The display is a self-contained <div> with scoped styles and an IIFE script, no global pollution.

How it works

Each cell contains four layers:

  1. Top half: static, shows the current character's upper portion
  2. Bottom half: static, shows the next character's lower portion
  3. Flip front: animated flap showing the old character (flips down)
  4. Flip back: backside of the flap showing the new character (revealed as flap lands)

The flip uses CSS rotateX(-180deg) with transform-origin: bottom center and backface-visibility: hidden for a realistic 3D fold.

The drum sequence is fixed: ' ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,:;!?\'-'. To go from any character to any other, the drum advances forward through every intermediate position, wrapping around if needed. This matches how mechanical split-flap displays physically operate.

License

MIT