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

telop-ui

v0.5.0

Published

Japanese TV-broadcast style React UI kit for projectors, signage and live presentations — telops, lower thirds, big numbers, rankings and wipes.

Readme

telop-ui

Japanese TV-broadcast style UI for React — for the screen at the front of the room. Projectors, lobby signage, live quizzes and votes, ceremonies, countdowns.

▶ Live demo · 日本語

  • Telops and lower thirds: slanted caption boxes, speaker name cards, headline boxes
  • Numbers that perform: count-up, slot-machine digit rollers, split-flap boards, countdowns
  • Live charts: rankings whose rows slide to their new place, choice bars with a stamp on the answer, a drumroll reveal
  • Broadcast effects: wipes, sweep banners, slide-in tickers, credits rolls, spotlight, eyecatch curtain between slides
  • Made for projection: sizes scale with min(vw, vh), two colors plus ink, a dark mode for dim rooms, controls that hide until the mouse moves

No CSS framework needed. React 17+, TypeScript types included, no runtime dependencies.

Install

npm install telop-ui

Quick start

import { TelopRoot, Stage, StageHeader, LBand, LBandItem, Telop, BigNumber, SegBar } from "telop-ui";

export function Submissions({ done, total }: { done: number; total: number }) {
  return (
    <TelopRoot locale="en">
      <Stage
        header={<StageHeader logo="/logo.svg" title="Live Quiz" subtitle="Room A" />}
        band={<LBand tag="LIVE"><LBandItem>Room A</LBandItem></LBand>}
      >
        <Telop className="tu-wipe">Submitted</Telop>
        <BigNumber value={done} size="hero" tone="primary" />
        <SegBar total={total} filled={done} tall />
      </Stage>
    </TelopRoot>
  );
}

TelopRoot injects the stylesheet once. If you prefer a static file, pass injectStyles={false} and import "telop-ui/styles.css".

Themes

Three presets: broadcast (navy + red), variety (ink + orange) and ceremony (green + gold). For your own, two brand colors are enough:

import { createTheme, TelopRoot } from "telop-ui";

const school = createTheme("school", { primary: "#1d6b46", accent: "#b07f00" });

<TelopRoot theme={school} mode="dark">…</TelopRoot>

createTheme derives everything else for both modes:

  • tinted background, panel, text and muted text from primary
  • text on each fill — white while it reads (3:1 for bold captions), dark otherwise
  • dark-mode versions of your colors, lifted until they read on the dark background

Any field can still be set by hand (bg, fg, panel, onPrimary, onAccent, mute, track), and a third argument overrides dark-mode fields.

Contrast check. In development, a theme that would be hard to read on a projector is reported once in the console. checkTheme(theme) returns the same list, and contrastRatio, readableOn, mix and ensureContrast are exported if you build colors yourself. Try colors in the demo (Theme → Custom): it shows the warnings and the createTheme call, and the link keeps your colors.

Every color is also a CSS variable (--tu-bg, --tu-fg, --tu-primary, --tu-accent, --tu-on-accent, --tu-panel, --tu-mute, --tu-track …), so you can override them in plain CSS.

Use accent sparingly. It is for the one thing people must look at: the hardest question, the winner, the last ten seconds. If everything is red, nothing is.

Global style: shape · motion · density

Three switches on TelopRoot change every part at once:

<TelopRoot shape="round" motion="calm" density="compact">…</TelopRoot>

| Prop | Values | What changes | |---|---|---| | shape | slant (default) · square · round | Every box: slanted TV captions, upright blocks, or rounded corners | | motion | calm · normal (default) · snappy | Every animation (×1.6 / ×1 / ×0.6). Timers that wait for an animation scale with it | | density | comfortable (default) · compact | Spacing in lists and panels |

They are CSS variables underneath (--tu-skew, --tu-radius, --tu-speed, --tu-density), so you can also fine-tune them in CSS.

On a web page

TelopRoot is built for a full-screen show: it fills the viewport, hides overflow and blocks text selection, and every size follows min(vw, vh). Inside an ordinary scrolling page, pass surface="page":

<TelopRoot surface="page" loadFont={false}>
  <Telop size="xl" wrap>Autumn Festival 2026 — Program and Timetable</Telop>
  <LowerThird label="Venue">Main Hall, 2F — doors open 13:30</LowerThird>
</TelopRoot>
  • Natural height, nothing clipped, text can be selected and copied, the page keeps its own background and font.
  • Sizes switch to rem-based tables (PAGE_TEXT · PAGE_TELOP · PAGE_NUMBER), so text stays readable on a portrait phone. Size names (sm, xl…) mean the same thing on both surfaces.
  • The top band and body paint are off unless you pass band / paintBody.
  • <Telop wrap> lets a long caption break onto more lines (a TV telop is one line by default).

Entrances on a long page. An animation that runs on mount has finished before anyone scrolls to it, so give the entrance on="view":

<Telop animate="sweep" on="view">Program</Telop>        {/* a bar runs across, then the caption */}
<Reveal on="view" delay={200}><Text>…</Text></Reveal>  {/* wipes in when it scrolls into view */}
<Stagger on="view"><p>…</p><p>…</p></Stagger>          {/* one after another */}

useInView() gives the same trigger to your own parts. Without IntersectionObserver everything shows at once, and prefers-reduced-motion skips the movement.

The page surface is for the small parts — Telop, Text, LowerThird, Tag, Pill, BigNumber. Full-screen layouts (Stage, SlideDeck, the TV segments) still assume a screen.

Live data

import { usePolling, useNow, StatusScreen, Countdown } from "telop-ui";

const { data, error, stale, skew, refresh } = usePolling(() => fetch("/api/live").then((r) => r.json()), {
  interval: 4000,
  serverTimeOf: (d) => d.serverTime, // correct the projector's clock
});
const now = useNow(1000, skew);

if (!data) return <StatusScreen message={error} onRetry={refresh} />;

When a refresh fails after data is on screen, the old data stays and stale is set — a projector should never go blank in front of an audience.

Components

| Group | Components | |---|---| | Root & hooks | TelopRoot useTelop useMessages useSizes · usePolling useNow useCountUp useInView useAutoHide useHotkeys useStoredMode · formatClock formatCountdown toggleFullscreen | | Layout | Stage StageHeader ControlBar CtrlButton Split Panel CardGrid Card LBand LBandItem Marquee StatusScreen | | Text | Telop Text Tag Pill LiveDot HeadlineBox LowerThird PersonLowerThird TitleCard BigMessage Typewriter | | Numbers | BigNumber StatBlock SegBar ProgressBar Countdown Clock DigitRoller SplitFlap | | Charts | RankingList RankingRow RankingRace BarList StackedBar ChoiceBars Stamp DrumrollReveal | | Effects | TickerStack SweepBanner Reveal Stagger CreditsRoll Spotlight | | TV segments | MekuriBoard JudgeScores VersusMeter ScoreBug RankReveal NewsFlash | | Slides | SlideDeck (curtain / fade / slide transitions, auto-advance, ← → / Space) |

TV segments

Formats borrowed from specific kinds of Japanese TV. Each is driven by the parent — the presenter decides the moment.

| Component | What it is | Forms | |---|---|---| | MekuriBoard | Wide-show flip board: answers under paper strips, peeled one by one | peel: right · up · flip — columns | | JudgeScores | Judges' panel: scores one by one, then the total counts up | reveal: flip · rise · count — columns, hideTotal | | VersusMeter | Two teams on one meter (red vs white, sports day) | variant: bar · split | | ScoreBug | Corner scoreboard of a sports broadcast | variant: stack · inline | | RankReveal | Countdown ranking, announced from the bottom up | layout: list · podium | | NewsFlash | Breaking-news bar from the screen edge | position: top · bottom — tone: flash · alert |

Most other parts have forms too — e.g. Telop variant="underline", ProgressBar variant="ring", Countdown variant="ring", SegBar variant="dots", TitleCard align="center", SlideDeck transition="fade". The demo lists every parameter with its default.

Utility classes: tu-wipe (wipe in), tu-wipe is-start / is-trail (stagger), tu-muted, tu-spacer.

Built-in strings come in ja (default), en and zh; override any of them with messages.

Demo

Online: https://tyoukyou23.github.io/telop-ui/ — open a scene and press F for full screen.

To run it locally:

git clone https://github.com/tyoukyou23/telop-ui && cd telop-ui
npm install
npm run dev

Five complete scenes (live quiz, live vote, departure board, ceremony slides, countdown) and every component with a code snippet. Switch language, theme and light/dark at the top. Open a scene and press F for full screen.

Design notes

  • Everything in a list is on screen within 0.7 s. Staggered entrances look nice the first time and slow the tenth time.
  • No glow, no gradients. Flat color blocks and slanted boxes read from the back of a room.
  • Theme switches are instant. The background never transitions, or dark boxes float on a light page for half a second.
  • prefers-reduced-motion slows the endless loops (marquee, credits) and disables the big moves.
  • Don't rank people in front of an audience. The ranking components are for questions, options and teams.

License

MIT © tyoukyou23