SolidJS port and fork of Jakub Antalík's original thinking-orbs, adding new custom states and engine improvements. Dotted thought-orb loading indicators for AI & agent UIs. 13 hand-tuned animated states, each shipped at two purpose-tuned sizes, rendered on a plain 2D canvas — no WebGL.
Live Demo · Original Repository · Documentation
npm install solid-thinking-orbsimport{ThinkingOrb}from'solid-thinking-orbs';functionStatus(){return<ThinkingOrbstate="searching"size={64}/>;}Thirteen verbs an agent can be doing, each a distinct animation:
/* V1 Original States */<ThinkingOrbstate="working"/>{/* particles on tilted orbits */}<ThinkingOrbstate="searching"/>{/* a scan meridian sweeps a dotted globe */}<ThinkingOrbstate="solving"/>{/* bands scramble, then click back solved */}<ThinkingOrbstate="listening"/>{/* a waveform rolls through the rings */}<ThinkingOrbstate="composing"/>{/* an undulating multi-band sash */}<ThinkingOrbstate="shaping"/>{/* dotted outline: circle → triangle → square */}/* V2 Custom States */<ThinkingOrbstate="syncing"/>{/* a fast-spinning 3D wireframe cylinder */}<ThinkingOrbstate="evolving"/>{/* a twisting double-helix ribbon */}<ThinkingOrbstate="building"/>{/* a 3D dotted wireframe cube tumbling */}<ThinkingOrbstate="hypercube"/>{/* a filled 3D cubic matrix with undulating surface waves */}<ThinkingOrbstate="conjuring"/>{/* a 3D logarithmic spiral triangle tumbling in space */}<ThinkingOrbstate="conjuring_static"/>{/* a static upright 3D spiral triangle with flowing energy */}<ThinkingOrbstate="assembling"/>{/* a 3D quantum cube whose particles explode outward & snap back */}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:
<ThinkingOrbstate="working"size={64}/><ThinkingOrbstate="working"size={20}/>Strictly monochrome — light ink for dark backgrounds, dark ink for light backgrounds — with the mode picked automatically from the host project:
<ThinkingOrbtheme="auto"/>{/* default — detects from the project */}<ThinkingOrbtheme="dark"/>{/* pin: light dots for dark backgrounds */}<ThinkingOrbtheme="light"/>{/* pin: dark dots for light backgrounds */}auto resolves in three layers and updates live when any of them change:
- an ancestor
data-theme="dark|light"attribute ordark/lightclass (the Tailwind / shadcn convention), watched viaMutationObserver; - otherwise
prefers-color-scheme, subscribed for live OS theme switches; - SSR-safe — the canvas paints only on the client, after the theme has resolved.
<ThinkingOrbstate="solving"size={20}speed={1.5}// multiplier on the preset's baked speedpaused={false}// freeze on the current framearia-label="Analysing repository…"// overrides the per-state default/>All other <canvas> props (class, style, data-*, …) pass through natively.
role="img"with a sensible per-statearia-labelout of the box.prefers-reduced-motion: reducerenders 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.
bun run dev # Start showcase dev server
bun run build:lib # Build library for publishing
bun run build:demo # Build showcase siteMIT © 2026 Mvkweb (SolidJS Port & Custom V2 States)
Original Implementation MIT © 2026 Jakub Antalík