Thinking Orb
A canvas thinking indicator that shares one clock and stops when offscreen.
Usage
Thinking Orb
Loading demo...
Best Practices
- To get a new orb per thought, key the component by that thought. Changing
statewill not reroll it. - Pass an explicit
statewhere you need determinism; a random form makes screenshot tests and screen recordings differ every run. - Keep
sizeat20or64and adjust the visual size withdisplaySize; other values distort the tuned presets. - Supply
labelon non-English surfaces — the defaults are English. - Show one orb per thought. Several stay in phase, but they blur what exactly is in progress.
API Reference
Props
| Name | Type | Default | Description |
|---|---|---|---|
state | OrbState | 'random' | 'random' | Which orb to draw. 'random' rolls once, on mount. |
size | 20 | 64 | 20 | Preset geometry size. Only these two are tuned. |
displaySize | number | same as size | Rendered CSS size in px; does not affect the drawing parameters. |
speed | number | 1 | Animation speed multiplier. |
paused | boolean | false | Whether to pause the animation. |
theme | 'auto' | 'dark' | 'light' | 'auto' | Colour theme; auto follows the environment. |
label | string | an English label per form | Accessible name. |
Events
TxThinkingOrb emits no component events.
Slots
TxThinkingOrb exposes no slots. It is a pure drawing surface — put any text in a sibling node.
Overview
statedefaults to'random', and the form is rolled once on mount and kept for the component's lifetime. To get a different orb, remount it with a newkey— changing the prop will not do it.- The nine forms are
working,searching,solving,listening,connecting,weaving,composing,breathingandshaping. - Every mounted orb shares one clock (
performance.now), so several on screen stay in phase rather than drifting apart. - The loop stops when the orb scrolls offscreen (
IntersectionObserver) and when the tab is hidden, so a long list of orbs does not keep burning CPU. - Under
prefers-reduced-motion: reducethe animation does not run; a single representative frame is drawn instead, and it still follows theme changes. sizeaccepts only20and64— the preset geometry is hand-tuned for those two. UsedisplaySizefor any other rendered size; it changes the CSS box only, not the drawing parameters.- The canvas is scaled by
devicePixelRatio, capped at 2. - Where there is no canvas (jsdom, for instance)
getContext('2d')returns null, and the component keeps the element but skips painting rather than throwing. - The accessible name defaults to an English label for the form (
Searching…and so on);labeloverrides it.