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

thinking-orbs-colorized

v0.2.0

Published

Dotted thought-orb loading indicators for AI & agent UIs — six tuned states, two sizes, auto dark/light, 22 curated color palettes

Readme

thinking-orbs-colorized

npm version License: MIT

Dotted thought-orb loading indicators for AI & agent UIs. Six hand-tuned animated states at two purpose-tuned sizes, auto dark/light, 22 curated color palettes — rendered on a plain 2D canvas, no WebGL, no filters, identical in Chrome, Safari and Firefox.

A colorized fork of thinking-orbs by Jakub Antalik — the original dotted thought-orb library this project builds upon. All engine credit goes to the original work; this fork adds color palettes, a product site, and bilingual docs on top of it.

Live demo · Repository · Report an issue · Español

Thinking orbs hero — states and palettes preview

Features

  • Six statesworking, searching, solving, listening, composing, shaping; each a distinct, hand-tuned animation.
  • Two tuned sizes64 for chat-avatar scale, 20 for inline text. Separate designs, not a scale factor.
  • Auto dark/light — resolves from your project's theme (Tailwind/shadcn dark class or data-theme) or the OS, live-updating.
  • 22 curated palettes — or pass any CSS color and get derived ramps; register your own with registerPalette.
  • Accessiblerole="img" with per-state aria-label, prefers-reduced-motion support.
  • Performant — pauses offscreen & in hidden tabs, shares one clock, DPR capped at 2, zero dependencies.
  • SSR-safe — the canvas only paints on the client.

Install

npm install thinking-orbs-colorized

Quick start

import { ThinkingOrb } from 'thinking-orbs-colorized';

function Status() {
  return <ThinkingOrb state="searching" size={64} palette="ocean" />;
}

States

Six verbs an agent can be doing, each a distinct animation:

<ThinkingOrb state="working" />    {/* particles on tilted orbits */}
<ThinkingOrb state="searching" />  {/* a scan meridian sweeps a dotted globe */}
<ThinkingOrb state="solving" />    {/* bands scramble, then click back solved */}
<ThinkingOrb state="listening" />  {/* a waveform rolls through the rings */}
<ThinkingOrb state="composing" />  {/* an undulating multi-band sash */}
<ThinkingOrb state="shaping" />    {/* dotted outline: circle → triangle → square */}

Sizes

Two tuned presets — separate designs, not a scale factor. 64 for chat-avatar scale, 20 for inline-text scale. Each carries its own dot count, dot size and speed tuning:

<ThinkingOrb state="working" size={64} />
<ThinkingOrb state="working" size={20} />

Theme

auto (default) picks the mode from the host project and updates live — dark renders light ink (for dark backgrounds), light renders dark ink:

<ThinkingOrb theme="auto" />   {/* default — detects from the project */}
<ThinkingOrb theme="dark" />   {/* pin: light dots for dark backgrounds */}
<ThinkingOrb theme="light" />  {/* pin: dark dots for light backgrounds */}

auto resolves in three layers:

  1. an ancestor data-theme="dark|light" attribute or dark/light class (the Tailwind / shadcn convention), watched via MutationObserver;
  2. otherwise prefers-color-scheme, subscribed for live OS theme switches;
  3. SSR-safe — the canvas paints only on the client, after the theme has resolved.

Colors & palettes

Omit palette for the classic monochrome orb. Pass any of the 22 curated palette ids, a CSS-color shorthand (dual light/dark ramps are auto-derived), or an inline palette object:

<ThinkingOrb palette="ember" />
<ThinkingOrb palette="#0ea5e9" />                     {/* shorthand → derived ramps */}
<ThinkingOrb palette={{ id: 'brand', light: { ink: '#7c3aed', fade: '#ede9fe' }, dark: { ink: '#c4b5fd', fade: '#1e1b4b' } }} />

Palette gallery — all 22 curated palettes, light and dark

The 22 curated palettes

Every palette is a same-hue ink → fade ramp per theme: light substrate gets dark ink on a pale fade, dark substrate gets light ink on a deep fade. Palettes marked Accents also paint active/particle (and sometimes band/outline) dots at a second hue — the fade stop always stays the base ramp's. Full accent values live in src/palette-data.ts.

| Palette | id | Light (ink · fade) | Dark (ink · fade) | Accents | | --- | --- | --- | --- | --- | | Mono | mono | #000000 #ffffff | #ffffff #000000 | — | | Graphite | graphite | #454a54 #eaeaeb | #afb5c0 #1f2023 | — | | Slate | slate | #385275 #e8eaee | #97b2d8 #1a2028 | — | | Paper | paper | #725b3b #f6f5f4 | #ebe2d6 #2d251b | — | | Ember | ember | #8b3d23 #f0e8e6 | #f4997b #2e1b14 | ✓ | | Sunset | sunset | #8b5323 #f0eae6 | #f4b47b #2e2014 | ✓ | | Aurora | aurora | #238b68 #e6f0ec | #7bf4cc #142e26 | ✓ | | Ocean | ocean | #23578b #e6ebf0 | #7bb8f4 #14212e | ✓ | | Arctic | arctic | #297ea3 #e6edf0 | #7bd0f4 #14262e | ✓ | | Nebula | nebula | #49238b #e9e6f0 | #a77bf4 #1e142e | ✓ | | AI Gradient | ai-gradient | #53238b #eae6f0 | #b47bf4 #20142e | ✓ | | Mint | mint | #238b5a #e6f0eb | #7bf4bc #142e22 | ✓ | | Synthwave | synthwave | #8b2376 #f0e6ee | #f47bdc #2e1429 | ✓ | | Cyberpunk | cyberpunk | #8b238b #f0e6f0 | #f47bf4 #2e142e | ✓ | | Matrix | matrix | #238b23 #e6f0e6 | #7bf47b #142e14 | ✓ | | Macaron | macaron | #7b324b #f5f0f1 | #df90ab #2a181e | ✓ | | Fog | fog | #546978 #eef0f1 | #a8bac7 #242a2e | ✓ | | Forest | forest | #238b3d #e6f0e8 | #7bf499 #142e1b | ✓ | | Moss | moss | #5f8b23 #ebf0e6 | #c2f47b #232e14 | ✓ | | Desert | desert | #8b6523 #f0ece6 | #f4c87b #2e2514 | ✓ | | Holiday | holiday | #8b2331 #f0e6e7 | #f47b8b #2e1417 | ✓ | | Midnight | midnight | #23238b #e6e6f0 | #9797f7 #14142e | ✓ |

Per-role colors overlay

Override individual dot roles — wins over palette accents for the listed roles, and the depth (fade) stop stays the base ramp's:

<ThinkingOrb palette="ocean" colors={{ active: '#ef4444', particle: '#f59e0b' }} />

Roles: ghost, particle, field, active, band, outline.

Custom palettes with registerPalette

import { registerPalette } from 'thinking-orbs-colorized';

registerPalette({
  id: 'brand',
  name: 'Brand',
  light: { ink: '#7c3aed', fade: '#ede9fe' },
  dark: { ink: '#c4b5fd', fade: '#1e1b4b' }
});
// now usable: <ThinkingOrb palette="brand" />

Invalid palettes are rejected with a dev-only warning; mono is reserved and cannot be overridden. Unknown ids and unresolvable colors always fall back to mono with a dev warning — resolution never throws. See docs/COLOR_PALETTEGuide.md for the full API.

Custom palettes — register, inline object, CSS shorthand, colors overlay

Props

<ThinkingOrb
  state="solving"       // 'working' | 'searching' | 'solving' | 'listening' | 'composing' | 'shaping'
  size={64}             // 64 | 20
  theme="auto"          // 'auto' | 'dark' | 'light'
  speed={1.5}           // multiplier on the preset's baked speed
  paused={false}        // freeze on the current frame
  palette="ocean"       // palette id, CSS color shorthand, or OrbPalette object
  colors={{ active: '#ef4444' }}  // per-role ink overlay
  aria-label="Analysing repository…"  // overrides the per-state default
/>

All other <canvas> props (className, style, data-*, …) pass through.

Local Storybook

Explore every state, size, palette and control:

npm run storybook

Runs on http://localhost:6006 — gallery, theme and Playground stories with live controls.

Accessibility & performance

  • role="img" with a sensible per-state aria-label out of the box.
  • prefers-reduced-motion: reduce renders a static representative frame — no animation — and still follows the live theme.
  • Every instance pauses automatically when scrolled offscreen (IntersectionObserver) or when the tab is hidden, and resumes in phase — all instances share one clock.
  • Plain 2D canvas arcs only: no ctx.filter, no SVG filters, no WebGL — the same pixels everywhere, cheap on low-end devices. Device-pixel-ratio capped at 2.
  • Palette resolution happens once per mount and degrades gracefully; the monochrome default keeps its byte-identical fast path.

Author

Made by Libardo Lozano (@Bardolog_1) — a colorized fork of thinking-orbs by Jakub Antalik & Alex Brinza.

License

MIT © Jakub Antalik — the original author and the work this fork is based on.

Copyright (c) 2026 Libardo Lozano (Bardolog1) — modifications, color palettes, site and docs.