A monorepo of small, opinionated UI components for OpenTUI: animations,
overlays, and one-off pieces. Sibling library to opentui-glyphfit and
opentui-tape.
Status: Sprints 1–4 shipped, CP24 (Sprint 4 batch 10). Every package below has a running demo and a recorded showcase. 307/307 tests passing. See HANDOFF.md if you're picking this up cold; DEVLOG.md for the dated checkpoint history.
| Package | Demo | |
|---|---|---|
![]() |
@aestheta/shimmer |
Time-keyed cell intensity — Pulse · Wave · custom paint |
![]() |
@aestheta/loaders |
Spinner catalog — frame-cycle + shape-driven |
![]() |
@aestheta/skeleton |
Loading placeholders — Skeleton + SkeletonBlock |
![]() |
@aestheta/drawer |
Slide-in panel — translateX overlay, no layout reflow |
![]() |
@aestheta/diff-flash |
Row-keyed ticker — atomic uptick/downtick flashes |
![]() |
@aestheta/marquee |
Scrolling viewports — wrap + bounce + easing |
![]() |
@aestheta/glow |
Breathing borders — line + block, any colour |
![]() |
@aestheta/confetti |
One-shot deterministic particle burst |
@opentui/core ships static primitives (Text, Input, Select, Slider,
Markdown). opentui-glyphfit ships static rasterisation. opentui-tape
ships streaming domain renderables that update on tick deltas — but with
no time-based animation. @opentui-ui covers dialogs and toasts.
What's missing is the time axis — primitives that pulse, fade, sweep, and decay. Aestheta provides that layer:
- A
ShimmerRenderable that drives phase-keyed cell repaint. - A catalog of indicators (
Dots,Bars,Eclipse,PulseRing, …) built either as frame-cycle strings or as shape-driven intensity fields composed on top ofShimmer+ glyphfit. - One mutable allocation per frame ceiling. No
Math.randomin the library — all motion is deterministic given a phase value, so visual snapshots stay stable.
See DESIGN.md for the full rationale and roadmap.
| Package | What it does | Status |
|---|---|---|
@aestheta/shimmer |
Time-keyed cell-intensity primitive. Shimmer Renderable + Pulse/Wave/TextShimmer presets + pure phase/easings helpers. |
Sprint 1 |
@aestheta/loaders |
Curated indicator catalog. Six frame-cycle loaders + three shape-driven loaders. pulsePeriod compound (CP24). |
Sprint 1 |
@aestheta/skeleton |
Shimmer-backed placeholder. Skeleton, SkeletonBlock, SkeletonReveal (CP23). |
Sprint 2 |
@aestheta/drawer |
Slide-in side panel via translateX/Y. setSide runtime swap (CP23). |
Sprint 2 |
@aestheta/diff-flash |
Cell-level flash decay. Row/cell modes, keyed-row API, FLASH_THEMES palette (CP22). |
Sprint 2 |
@aestheta/marquee |
Scrolling viewport with bounce + gradient (CP24) + pause/resume (CP21). | Sprint 3 |
@aestheta/glow |
Breathing border with directional pulse origin (CP21). | Sprint 3 |
@aestheta/confetti |
One-shot deterministic burst. gravity option (CP22). |
Sprint 3 |
@aestheta/cli |
shadcn-style aestheta {list,info,add} (CP19). |
Sprint 4 |
Long-term goal: a copy-into-your-project workflow modelled on shadcn/ui. Run a single command, pick the components you want, and the source files drop into your repo — owned and modifiable by you, no version-pinning friction.
# shipped in CP19
bunx @aestheta/cli list
bunx @aestheta/cli add diff-flash --dest ./src/uiThe CLI rewrites cross-component imports as it copies, so add diff-flash
also installs shimmer and rewrites from "@aestheta/shimmer" →
from "../shimmer/index.ts". Foreign imports (@opentui/core, etc.)
pass through untouched. See packages/cli for full
usage.
Each component is its own publishable package for users who prefer versioned dependencies, and its own copyable source tree for users who want to adapt it. The two distribution modes share one source of truth.
opentui-aestheta/
├── DESIGN.md ← purpose / problem / non-goals / approach / API
├── DEVLOG.md ← dated checkpoint history
├── packages/
│ ├── shimmer/ ← time-keyed cell-intensity primitive
│ └── loaders/ ← indicator catalog
├── registry/ ← shadcn-style component manifest (Sprint 4)
└── apps/
└── demo/ ← end-to-end demo composing every component
Each packages/<name>/ follows the same conventions as
opentui-glyphfit and opentui-tape: Bun build, ESM exports, peer dep
on @opentui/core, strict TypeScript, snapshot tests.
If a previous run (CP1–CP3) left your terminal in mouse-tracking
mode and your shell is still receiving stray ^[[<35;…M sequences
or other escape garbage, reset it:
# Disable SGR 1006 + any-event + button-event + X10 mouse modes
printf '\033[?1006l\033[?1003l\033[?1002l\033[?1000l'
# Or full reset:
tput resetThe Sprint 1 demos in this repo all pass useMouse: false so this
shouldn't recur. If it does after running a current demo, please
file an issue with your terminal emulator + version.
bun install
bun run typecheck # all packages
bun test # all packages
bun run demo # gallery in your terminalPer-package demos:
bun run d:shimmer
bun run d:loadersAll four sprints shipped — see HANDOFF.md for the
detailed state and DEVLOG.md for the dated
checkpoint history. The "Next (≤5)" block at the top of the DEVLOG
captures the open follow-ups (registry hosting, real-terminal
verification, cross-repo adoption in opentui-tape).
| Component | Status | Notes |
|---|---|---|
shimmer |
Sprint 1 (CP1) | Time-keyed cell-intensity primitive. |
loaders |
Sprint 1 (CP1) | Frame-cycle + shape-driven indicators. pulsePeriod compound in CP24. |
skeleton |
Sprint 2 (CP~5) | Shimmer-backed placeholder rect. SkeletonReveal in CP23. |
drawer |
Sprint 2 (CP~5) | Slide-in side panel via translate. setSide runtime swap in CP23. |
diff-flash |
Sprint 2 (CP~5) | Cell-level flash decay. FLASH_THEMES in CP22. |
marquee |
Sprint 3 (CP~9) | Scrolling viewport. pauseFor/pause/resume in CP21, gradientFrom/To in CP24. |
glow |
Sprint 3 (CP~9) | Breathing border. Directional origin in CP21. |
confetti |
Sprint 3 (CP~9) | Deterministic seeded burst. gravity in CP22. |
tui-test |
Sprint 3.5 (CP~12) | PTY + xterm-headless harness with semantic locators. |
cli + registry |
Sprint 4 (CP19) | Manifest generator + aestheta {list,info,add}. |
@opentui/core(upstream) — rendering primitives. We are a consumer.opentui-glyphfit(sibling) — glyph rendering and charsets. Used by aestheta's shape-driven loaders only; frame-cycle loaders do not depend on it.opentui-tape(sibling) — financial domain primitives. Tape's demos compose aestheta components but tape itself does not depend on them.@opentui-ui(sibling) — dialog/toast. Orthogonal to aestheta.
MIT (per package).








