A small & opinionated spinner library for terminal UIs built on OpenTUI.
- Built-in Spinners - Powered by cli-spinners
- Custom Spinners - Create your own with custom frames and intervals
- React Support - First-class React integration via OpenTUI React
- SolidJS Support - First-class SolidJS integration via OpenTUI Solid
- Type-Safe - Full TypeScript support
bun add opentui-spinner @opentui/coreFor React support:
bun add opentui-spinner @opentui/core @opentui/react reactFor SolidJS support:
bun add opentui-spinner @opentui/core @opentui/solid solid-jsimport { createCliRenderer } from "@opentui/core";
import { SpinnerRenderable } from "opentui-spinner";
const renderer = await createCliRenderer();
const spinner = new SpinnerRenderable(renderer, {
name: "dots",
color: "cyan",
});
renderer.root.add(spinner);import {
BoxRenderable,
createCliRenderer,
TextRenderable,
} from "@opentui/core";
import { SpinnerRenderable } from "opentui-spinner";
const renderer = await createCliRenderer();
const container = new BoxRenderable(renderer, {
border: true,
flexDirection: "row",
alignItems: "center",
});
const spinner = new SpinnerRenderable(renderer, {
name: "bouncingBall",
});
const label = new TextRenderable(renderer, {
content: "Loading...",
marginLeft: 1,
});
container.add(spinner);
container.add(label);
renderer.root.add(container);First, import the React extension:
import "opentui-spinner/react";Then use the <spinner> component in your OpenTUI React app:
import { createCliRenderer } from "@opentui/core";
import { createRoot } from "@opentui/react";
import "opentui-spinner/react";
function App() {
return (
<box alignItems="center" flexDirection="row">
<spinner name="bouncingBall" color="cyan" />
<text marginLeft={1}>Loading...</text>
</box>
);
}
const renderer = await createCliRenderer();
createRoot(renderer).render(<App />);First, import the SolidJS extension:
import "opentui-spinner/solid";Then use the <spinner> component in your OpenTUI SolidJS app:
import { render } from "@opentui/solid";
import "opentui-spinner/solid";
function App() {
return (
<box alignItems="center" flexDirection="row">
<spinner name="bouncingBall" color="cyan" />
<text marginLeft={1}>Loading...</text>
</box>
);
}
render(() => <App />);| Option | Type | Default | Description |
|---|---|---|---|
name |
SpinnerName |
"dots" |
Name of a built-in spinner from cli-spinners |
frames |
string[] |
- | Custom animation frames (overrides name) |
interval |
number |
- | Time between frames in milliseconds |
autoplay |
boolean |
true |
Whether to start playing automatically |
color |
ColorInput | ColorGenerator |
"white" |
Foreground color or color generator function |
backgroundColor |
ColorInput |
"transparent" |
Background color |
Start or resume the spinner animation.
spinner.start();Pause the spinner animation.
spinner.stop();All options can be updated dynamically via properties:
// Change spinner type
spinner.name = "line";
// Update color
spinner.color = "green";
// Or use a color generator
spinner.color = createPulse(["red", "yellow", "green"]);
// Update background color
spinner.backgroundColor = "blue";
// Change frames
spinner.frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
// Adjust interval
spinner.interval = 100;The library includes 80+ spinners from cli-spinners. Popular choices include:
dots- Simple dots (⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏)dots2- Alternative dotsdots3throughdots12- Various dot stylesline- Rotating line (- \ | /)pipe- Simple pipe animationstar- Rotating stararc- Arc animationcircle- Circle segmentssquareCorners- Rotating square cornerscircleQuarters- Quarter circlescircleHalves- Half circlesbouncingBar- Bouncing barbouncingBall- Bouncing ballarrow- Arrow animationshamburger- Hamburger menu animationgrowVertical/growHorizontal- Growing barsballoon/balloon2- Balloon animationsnoise/bounce- Various effectsboxBounce- Bouncing boxweather- Weather iconsmoon- Moon phasesrunner- Running characterpong- Pong animationshark- Shark animationdqpb- Letter rotation
See the full list at cli-spinners.
Create your own spinner with custom frames:
const spinner = new SpinnerRenderable(renderer, {
frames: ["◐", "◓", "◑", "◒"],
interval: 80,
color: "magenta",
});Colors can be specified in multiple formats:
// Named colors
spinner.color = "red";
spinner.color = "cyan";
// RGB values
spinner.color = { r: 255, g: 100, b: 50 };
// Hex colors
spinner.color = "#ff6432";The color property also accepts a ColorGenerator function for dynamic color effects:
import { SpinnerRenderable, type ColorGenerator } from "opentui-spinner";
// Custom color generator
const customColorGen: ColorGenerator = (
frameIndex,
charIndex,
totalFrames,
totalChars
) => {
// Return different colors based on frame/character position
return frameIndex % 2 === 0 ? "cyan" : "magenta";
};
const spinner = new SpinnerRenderable(renderer, {
name: "dots",
color: customColorGen,
});Creates a pulsing effect that cycles through colors:
import { SpinnerRenderable, createPulse } from "opentui-spinner";
const spinner = new SpinnerRenderable(renderer, {
name: "dots",
color: createPulse(["red", "orange", "yellow"], 0.5),
});Parameters:
colors: Array of colors to cycle throughspeed: Animation speed multiplier (default: 1.0)
Creates a wave pattern that moves across characters:
import { SpinnerRenderable, createWave } from "opentui-spinner";
const spinner = new SpinnerRenderable(renderer, {
name: "dots",
color: createWave(["#ff0000", "#00ff00", "#0000ff"]),
});Parameters:
colors: Array of colors for the wave gradient
Check out the examples/ directory for complete working examples:
examples/index.ts- Core exampleexamples/react.tsx- React exampleexamples/solid.tsx- SolidJS example
@opentui/core(required)@opentui/react(optional, for React support)@opentui/solid(optional, for SolidJS support)
# Install dependencies
bun install
# Build the library
bun run build
# Lint code
bun run lint
# Auto-fix linting issues
bun run lint:fixMIT
- Built on OpenTUI
- Spinners from cli-spinners by Sindre Sorhus
Contributions are welcome! Please feel free to submit a Pull Request.