Toggle Sidebar B
AppearanceLight & dark mode D

Thinking Orb

Dotted thought orb for AI and agent UIs. Six hand tuned animated states at any size, drawn on a plain 2D canvas (no WebGL, no filters). Vue port of thinking-orbs by Jakub Antalik, MIT licensed.

Default

Renders the working state at 64px. The animation starts on mount and stays in phase with every other orb on the page.

Dark previewReplay preview

States

Six verbs an agent can be doing, each a distinct animation rather than a recolour of the same loop.

Dark previewReplay preview
workingParticles on tilted orbits
searchingA scan meridian sweeps a dotted globe
solvingBands scramble, then click back solved
listeningA waveform rolls through the rings
composingAn undulating multi band sash
shapingCircle, triangle, square

Sizes

size takes any number of CSS pixels. Two of them are hand tuned and act as anchors: 64 for chat avatar scale and 20 for inline text scale. They are separate designs, not a scale factor, since each carries its own dot count, dot size and speed tuning. Sizes between the anchors blend that tuning, and sizes outside the range keep the nearest anchor's while the drawing follows the canvas.

Dark previewReplay preview
64px (anchor)
40px (blended)
28px (blended)
20px (anchor)

In chat pills

The intended home for the orb: a status pill next to the label of whatever the agent is doing. Pass the size the pill needs, and let the label shimmer while the work is in flight.

Dark previewReplay preview
Solving…
Thinking…
Agent listening…
Agent shaping…

Speed

speed multiplies the preset's baked speed. Values below 1 slow the loop down, values above 1 speed it up.

Dark previewReplay preview
0.5x
1x
2x

Paused

Set paused to freeze the loop. One frame is always painted, so a paused orb still shows the shape instead of an empty canvas.

Dark previewReplay preview

Theme

The orb is strictly monochrome: light ink on dark substrates, dark ink on light ones. auto follows the nearest data-theme attribute or dark/light class and updates live when the page theme flips. Pin it with light or dark when the orb sits on a fixed surface.

Dark previewReplay preview
theme="light"
theme="dark"
theme="auto"

Playground

Every prop on one panel. State uses Toggle Group, size and speed use Slider Ruler, and the button freezes the loop.

Dark previewReplay preview
State
Size
Size64
Speed
Speed1
<ThinkingOrb state="listening" :size="64" />

API Reference

ThinkingOrb

PropTypeDefaultDescription
state"working" | "searching" | "solving" | "listening" | "composing" | "shaping""working"Which animation to show. Each state is a separate hand tuned loop.
sizenumber64Rendered size in CSS pixels. 64 and 20 are the hand tuned anchors: sizes in between blend their tuning, sizes outside hold the nearest one. No CSS override needed.
theme"auto" | "dark" | "light""auto"auto resolves from an ancestor data-theme or dark/light class, then from prefers-color-scheme. dark and light pin the palette.
speednumber1Multiplier on top of the preset's baked speed.
pausedbooleanfalseFreeze the animation on the current frame.
ariaLabelstringOverrides the per state default label ("Working…", "Searching…", and so on).
classstringMerged onto the canvas element.

Accessibility

Keyboard shortcuts and ARIA behavior.

  • The canvas ships as role="img" with a per state aria-label, so screen readers announce what the agent is doing. Override it with ariaLabel when the surrounding copy already says it.
  • prefers-reduced-motion: reduce renders a single static representative frame instead of animating, and still follows the live theme.
  • Every instance pauses itself when scrolled offscreen (IntersectionObserver) or when the tab is hidden, then resumes in phase with the other orbs.
  • Rendering is plain 2D canvas arcs: no ctx.filter, no SVG filters, no WebGL. Device pixel ratio is capped at 2.