Unicode Spinners Pro · loaders made of text · v1.0
Loaders made of text.
40 braille, block and box-drawing spinners, AI “thinking” and streaming loaders, step rows that turn into ✓ or ✗, and progress bars that fill a fraction of a character at a time. Crisp at any size, in your text color, never shifting your layout. A script tag, a React component or a Framer component.
One-time payment · Instant download · Single-project license · Free v1.x updates
- 40 spinners in 7 categories
- AI thinking & streaming loaders
- No layout shift · accessible
- No dependencies · 8 KB gzipped
Just need raw frames for a terminal? unicode-animations is our free MIT package with 18 braille spinners as frame data. Pro is the extended set for websites: 22 more spinners, AI and progress loaders, colors and finished, accessible components. See the difference.
Every spinner, live
40 spinners in seven categories. Copy a ready-made tag, or the frames and interval for anything else you build.
- braille spinnerbraille10 frames · 80msalso in free unicode-animations
- braillewave spinnerbraillewave8 frames · 100msalso in free unicode-animations
- dna spinnerdna12 frames · 80msalso in free unicode-animations
- scan spinnerscan10 frames · 70msalso in free unicode-animations
- rain spinnerrain12 frames · 100msalso in free unicode-animations
- scanline spinnerscanline6 frames · 120msalso in free unicode-animations
- pulse spinnerpulse5 frames · 180msalso in free unicode-animations
- snake spinnersnake16 frames · 80msalso in free unicode-animations
- sparkle spinnersparkle6 frames · 150msalso in free unicode-animations
- cascade spinnercascade14 frames · 60msalso in free unicode-animations
- columns spinnercolumns26 frames · 60msalso in free unicode-animations
- orbit spinnerorbit8 frames · 100msalso in free unicode-animations
- breathe spinnerbreathe17 frames · 100msalso in free unicode-animations
- waverows spinnerwaverows16 frames · 90msalso in free unicode-animations
- checkerboard spinnercheckerboard4 frames · 250msalso in free unicode-animations
- helix spinnerhelix16 frames · 80msalso in free unicode-animations
- fillsweep spinnerfillsweep11 frames · 100msalso in free unicode-animations
- diagswipe spinnerdiagswipe16 frames · 60msalso in free unicode-animations
- ring spinnerring12 frames · 70ms
- bounce spinnerbounce14 frames · 70ms
- heartbeat spinnerheartbeat12 frames · 70ms
- equalizer spinnerequalizer8 frames · 90ms
- matrix spinnermatrix8 frames · 90ms
- spiral spinnerspiral16 frames · 60ms
- shimmer spinnershimmer14 frames · 60ms
- typing spinnertyping8 frames · 120ms
- cursor spinnercursor6 frames · 90ms
- blocks spinnerblocks14 frames · 100ms
- blockwave spinnerblockwave10 frames · 70ms
- shade spinnershade10 frames · 90ms
- quadsnake spinnerquadsnake12 frames · 80ms
- corners spinnercorners4 frames · 120ms
- tracer spinnertracer8 frames · 70ms
- chevrons spinnerchevrons8 frames · 110ms
- dash spinnerdash8 frames · 80ms
- compass spinnercompass8 frames · 100ms
- arc spinnerarc6 frames · 100ms
- halfmoon spinnerhalfmoon4 frames · 180ms
- diamond spinnerdiamond4 frames · 150ms
- line spinnerline4 frames · 100ms
AI thinking and streaming loaders
Thinking… then done.
A label with a light that sweeps across it, a cursor at the end of a streamed answer, and agent rows that turn from a spinner into ✓ or ✗. Screen readers hear “Thinking…”, then the result: never the frames.
Thinking
Why do my spinners jump around?
<pf-spinner name="shimmer" label="Thinking…"
shimmer-label color-mode="gradient">Token stream cursor
Writing
answer.append(token)
<pf-spinner name="cursor" label-position="hidden">Agent steps
- Searching the docs
- Running the tests
- Checking the API
- Writing the answer
row.done("Read 12 pages") // ✓
row.fail("Rate limited") // ✗Progress bars
A fraction of a character at a time.
Blocks fill in eighths of a cell, braille dot by dot. Percent and an estimated time left, or an indeterminate band. Always the width you set, read out as a real progress bar.
Playground
Pick a spinner or type your own frames, then change the speed, color, label, size and state. The code under the preview follows along: copy it for a script tag, React or Framer.
Inline in a sentence: Loading it keeps the text's size and never moves it.
<script src="/js/unicode-spinners.min.js" defer></script>
<pf-spinner
name="helix"
color-mode="gradient"
colors="#f0b27a, #22d3ee"
label="Thinking…"
shimmer-label
size="32">
</pf-spinner>
<script>
// when the work is done:
// document.querySelector("pf-spinner").done("Done")
</script>Like what you made? The snippet runs with the script from the download.
Buy Unicode Spinners Pro · $9Free package or Pro?
unicode-animations stays free on npm. The 18 spinners in it are in Pro too, unchanged, so names carry over; what you pay for is everything around them.
| Feature | unicode-animations (free) | Unicode Spinners Pro ($9) |
|---|---|---|
| Spinners | 18 braille spinners | 40: the same 18 plus 22 braille, block, box-drawing, arrow and AI designs |
| What you get | Frame data ({ frames, interval }): you write the loop and the markup | Finished components: <pf-spinner> and <pf-progress>, React components and a hook, a Framer component |
| AI and streaming | — | Shimmering “Thinking…”, token-stream cursor, typing dots, agent rows that turn into ✓ / ✗ |
| Progress bars | — | Five styles with sub-cell precision, percent, time left, indeterminate |
| Customizing | Edit the frames in code | Custom frames as a string or an array, speed, interval, solid / gradient / cycling / shimmer color, size |
| Layout and accessibility | Up to you | Fixed monospace cells (no layout shift), role="status", polite announcements, aria-busy, frames hidden from screen readers, Reduce Motion |
| License | MIT, free | $9 one-time, one website or project |
Works with
- FramerCode component with a properties panel: spinner or progress bar, label, colors, fontIn the v1.0 download
- WebflowPaste the footer code, then an Embed with <pf-spinner>In the v1.0 download
- Plain HTML / any siteOne script + <pf-spinner name="helix">In the v1.0 download
- WordPressCustom HTML block with the script and the tagIn the v1.0 download
- ShopifyTheme asset + a Custom Liquid sectionIn the v1.0 download
- Squarespace, WixCode Injection / embed block (plan must allow custom code)In the v1.0 download
- React, Next.js, Vite<Spinner>, <Progress>, <AgentSteps>, useSpinner(): server-rendered still frameIn the v1.0 download
What it does
- 40 spinners. Classic braille, braille grids (scan, helix, rain, heartbeat, equalizer...), AI and streaming, block elements, box drawing, arrows and geometric shapes. Every one is plain text: crisp at any size, in your font color.
- Made for AI interfaces. A “Thinking…” label with a light that sweeps across it, a cursor that sits at the end of a streamed answer, typing dots, and step rows for an agent's tool calls that turn from a spinner into ✓ or ✗, announcing the result.
- Progress bars with sub-cell precision. Blocks fill in eighths of a character, braille dot by dot, plus shade, line and ASCII styles. Percent and an estimated time left, or an indeterminate band.
- Yours to change. Your own frames as a string or an array, speed and interval, one color, a gradient across the characters, colors that cycle, or a shimmer. Size with font-size.
- Nothing shifts. Every character sits in its own fixed monospace cell, every frame is the same width, and ✓ / ✗ keep that width. The text around a spinner never moves.
- Accessible. role="status" with polite announcements and aria-busy while it spins. Screen readers hear the label, never the frames, and hear “Done” when it finishes. Bars are progressbars with their value spoken. Reduce Motion shows a still frame or a slow version.
- Light. 8 KB gzipped for all of it, no dependencies, no fonts to load. One animation loop for the whole page; spinners pause offscreen and in background tabs.
What's in the download
- unicode-spinners.min.js: <pf-spinner> and <pf-progress> for any website (18.7 KB, 8 KB gzipped)
- unicode-spinners.esm.js + TypeScript types, for bundlers
- react/UnicodeSpinners.tsx: Spinner, Progress, AgentSteps and useSpinner (React 18+, one file)
- framer/UnicodeSpinner.tsx: the Framer code component
- spinners.json: every spinner's frames and interval
- demo.html, and a README with a quick start for every platform
- Free updates to v1.x
Single-project license (LICENSE.md in the download): one website or project per license. The 18 unicode-animations spinners stay MIT (© Gunnar Gray); six frame sequences follow cli-spinners (MIT, © Sindre Sorhus). Both notices are in LICENSE.md.
Install in about a minute
Upload unicode-spinners.min.js from the download to your site.
Add the script once, then the tags wherever you need a loader.
Call done() or fail() when the work finishes.
<script src="/js/unicode-spinners.min.js" defer></script>
<pf-spinner name="shimmer" label="Thinking…" shimmer-label></pf-spinner>
<pf-progress value="42" label="Uploading" eta></pf-progress>
<script>
document.querySelector("pf-spinner").done("Answer ready")
</script>Paste script/webflow/footer-code.html from the download into Site settings → Custom code → Footer code (nothing to host).
Add an Embed element with the tag below where the loader goes.
Publish. Custom code runs on the published site.
<pf-spinner name="orbit" label="Loading"></pf-spinner>Custom code needs a paid Webflow site plan.
Upload unicode-spinners.min.js to your theme folder (or with a file manager plugin) and copy the URL.
Add a Custom HTML block with the script and the tag.
<script src="https://your-site.com/wp-content/themes/your-theme/js/unicode-spinners.min.js" defer></script>
<pf-spinner name="scan" label="Loading posts"></pf-spinner>On WordPress.com, you need a plan that allows custom code.
Online Store → Themes → Edit code → Assets: upload unicode-spinners.min.js.
Add a Custom Liquid section with the script and the tag.
<script src="{{ 'unicode-spinners.min.js' | asset_url }}" defer></script>
<pf-spinner name="dna" label="Checking stock"></pf-spinner>Copy react/UnicodeSpinners.tsx into your project. It needs only React 18+.
Use the components, or the hook for your own markup.
import { Spinner, Progress, AgentSteps, useSpinner } from "./UnicodeSpinners"
<Spinner name="shimmer" label="Thinking…" shimmerLabel />
<Progress value={percent} label="Uploading" eta />
<AgentSteps steps={[{ label: "Search", state: "done" }, { label: "Write", state: "running" }]} />
const frame = useSpinner("orbit") // "⠃", then "⠉"...Next.js: the server renders a still frame and the label; the animation starts in the browser.
In your Framer project, go to Assets → Code → + → New component file, and name it UnicodeSpinner.
Replace the file's contents with framer/UnicodeSpinner.tsx from the download, and save.
Drag it onto the canvas, then pick Spinner or Progress Bar, the spinner, a label, colors and a font.
On the Framer canvas you see a still frame, which keeps the editor fast. Set On Canvas to Live to watch it there.
Squarespace and Wix: add the script and the tag in a Code or Embed block (your plan must allow custom code). The download's README has a quick start for every platform and the full settings reference.
Unicode Spinners Pro
$9 one-time
- Script tag, React and Framer builds
- 40 spinners, AI loaders and progress bars
- Free v1.x updates
- Single-project license
Secure checkout by Polar. Instant download after payment.
Get all 8 for $49 with the All-Access PassFAQ
Isn't unicode-animations free?
Yes, and it stays free: unicode-animations is an MIT-licensed npm package with 18 braille spinners as raw frame data, for when you want to write the loop and markup yourself (it's great in terminals). Unicode Spinners Pro includes those 18 unchanged so the names match, and adds 22 more spinners, the AI and streaming loaders, progress bars, custom frames and colors, the accessibility and layout work, and finished script-tag, React and Framer components.
Where does it work?
Anywhere you can add a script tag: Webflow, WordPress, Shopify, Squarespace, Wix, plain HTML. Also React/Next.js and Framer. Site builders need a plan that allows custom code.
Will the characters show up on every device?
Braille patterns, block elements, box drawing and arrows are in the default fonts of macOS, iOS, Windows, Android and most Linux systems. Spinners use the visitor's monospace font; no fonts are downloaded.
Will it move my layout around?
No. Every character sits in its own fixed cell, every frame of a spinner has the same width, and the ✓ / ✗ that replace it keep that width. Bars are always the width you set.
What do screen readers hear?
The label, or “Loading” when there's no visible label, never the frames. A spinner is a polite status that's busy while it spins; when you call done() or fail(), screen readers hear the done or error label. Bars are progressbars that read their value, like “42%, about 8s left”.
What about Reduce Motion?
With Reduce Motion on, a spinner shows a still frame (the one that reads best as a loader), or a slow, plain version if you set reduced-motion="slow". The label shimmer stops too.
Is it a text animation like Kinetic Type?
No. Kinetic Type animates your headlines. These are loading indicators: spinners, status rows and progress bars. The token-stream cursor sits after text your app streams in; it doesn't reveal or animate the text itself.
What's the license?
Single project: one website or project per purchase. The details are in LICENSE.md in the download, with the MIT notices for the unicode-animations spinners and the frame sequences that follow cli-spinners.
Do I get updates?
Yes, free updates for v1.x.
Questions before buying?
Email hi@gunnargray.com.
Hear about updates
The launch, new spinners, v1.x releases and the occasional new tool. No more than that.