Loaders
Fourteen motion-friendly loaders. Text-family pieces support `TextPulseGranularity` (`line` | `word` | `letter`) and `speed` (1 = default, higher = faster). Primitives accept optional `speed` for motion timing.
Default loaders
Dots, ring, wave bars, orbit, morph blob, progress line, and skeleton card in a responsive grid.
Motion primitives for buttons, cards, and overlays-no copy. Use speed on each (default 1, higher = faster).
PulseDotsLoader · speed 1.4
SpinnerRing
WaveBarsLoader
OrbitLoader · speed 1.2
MorphBlobLoader
ProgressLineLoader · speed 1.5
SkeletonCardLoader
default-example.tsx
1import {2 MorphBlobLoader,3 OrbitLoader,4 ProgressLineLoader,5 PulseDotsLoader,6 SkeletonCardLoader,7 SpinnerRing,8 WaveBarsLoader,9} from "@/registry/ui";1011export function LoadersDefaultExample() {12 return (13 <div className="space-y-3">14 <p className="text-sm text-muted-foreground">15 Motion primitives for buttons, cards, and overlays-no copy. Use{" "}16 <code className="text-foreground">speed</code> on each (default{" "}17 <code className="text-foreground">1</code>, higher = faster).18 </p>19 <div className="mx-auto grid max-w-6xl grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">20 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">21 <span className="text-xs font-medium text-muted-foreground">22 PulseDotsLoader · speed 1.423 </span>24 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">25 <PulseDotsLoader speed={1.4} />26 </div>27 </div>28 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">29 <span className="text-xs font-medium text-muted-foreground">30 SpinnerRing31 </span>32 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">33 <SpinnerRing />34 </div>35 </div>36 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">37 <span className="text-xs font-medium text-muted-foreground">38 WaveBarsLoader39 </span>40 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">41 <WaveBarsLoader />42 </div>43 </div>44 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">45 <span className="text-xs font-medium text-muted-foreground">46 OrbitLoader · speed 1.247 </span>48 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">49 <OrbitLoader speed={1.2} />50 </div>51 </div>52 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">53 <span className="text-xs font-medium text-muted-foreground">54 MorphBlobLoader55 </span>56 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">57 <MorphBlobLoader />58 </div>59 </div>60 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">61 <span className="text-xs font-medium text-muted-foreground">62 ProgressLineLoader · speed 1.563 </span>64 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">65 <ProgressLineLoader className="w-full max-w-56" speed={1.5} />66 </div>67 </div>68 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">69 <span className="text-xs font-medium text-muted-foreground">70 SkeletonCardLoader71 </span>72 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">73 <SkeletonCardLoader className="w-full max-w-[16rem]" />74 </div>75 </div>76 </div>77 </div>78 );79}
Text & chat
Defaults plus a second grid: per-word / per-letter shimmers, prefix granularity on user typing, multi-line skeleton, faster caret and typing dots.
Defaults: whole-line pulse, static prefix + ellipsis, motion skeleton lines.
TextShimmerLoader · per line
Syncing…
TypingIndicator
UserTypingStatus
User is typing...
AIThinkingLoader · per word
AI is thinking...
StreamingTextSkeleton · 3 lines
CursorBlinkLoader · Draft
Draft
granularity="word" or "letter" staggers opacity per token; speed tightens timing.
TextShimmerLoader · per word · speed 1.3
Saving your changes
TextShimmerLoader · per letter (phrase + space)
Almost ready
AIThinkingLoader · per word
AI is thinking...
UserTypingStatus · prefix per letter
User is typing...
UserTypingStatus · prefix per word
Someone is typing...
StreamingTextSkeleton · 5 lines · fast
CursorBlinkLoader · Compose · speed 1.8
Compose
TypingIndicator · speed 1.5
text-and-chat-example.tsx
1import {2 AIThinkingLoader,3 CursorBlinkLoader,4 StreamingTextSkeleton,5 TextShimmerLoader,6 TypingIndicator,7 UserTypingStatus,8} from "@/registry/ui";910export function LoadersTextAndChatExample() {11 return (12 <div className="space-y-10">13 <div className="space-y-3">14 <p className="text-sm text-muted-foreground">15 Defaults: whole-line pulse, static prefix + ellipsis, motion skeleton16 lines.17 </p>18 <div className="mx-auto grid max-w-6xl grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">19 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">20 <span className="text-xs font-medium text-muted-foreground">21 TextShimmerLoader · per line22 </span>23 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">24 <TextShimmerLoader text="Syncing…" granularity="line" />25 </div>26 </div>27 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">28 <span className="text-xs font-medium text-muted-foreground">29 TypingIndicator30 </span>31 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">32 <TypingIndicator />33 </div>34 </div>35 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">36 <span className="text-xs font-medium text-muted-foreground">37 UserTypingStatus38 </span>39 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">40 <UserTypingStatus />41 </div>42 </div>43 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">44 <span className="text-xs font-medium text-muted-foreground">45 AIThinkingLoader · per word46 </span>47 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">48 <AIThinkingLoader />49 </div>50 </div>51 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">52 <span className="text-xs font-medium text-muted-foreground">53 StreamingTextSkeleton · 3 lines54 </span>55 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">56 <StreamingTextSkeleton className="max-w-56" lines={3} />57 </div>58 </div>59 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">60 <span className="text-xs font-medium text-muted-foreground">61 CursorBlinkLoader · Draft62 </span>63 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">64 <CursorBlinkLoader text="Draft" />65 </div>66 </div>67 </div>68 </div>6970 <div className="space-y-3">71 <p className="text-sm text-muted-foreground">72 <code className="text-foreground">granularity="word"</code>{" "}73 or <code className="text-foreground">"letter"</code>{" "}74 staggers opacity per token;{" "}75 <code className="text-foreground">speed</code> tightens timing.76 </p>77 <div className="mx-auto grid max-w-6xl grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">78 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">79 <span className="text-xs font-medium text-muted-foreground">80 TextShimmerLoader · per word · speed 1.381 </span>82 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">83 <TextShimmerLoader84 text="Saving your changes"85 granularity="word"86 speed={1.3}87 />88 </div>89 </div>90 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">91 <span className="text-xs font-medium text-muted-foreground">92 TextShimmerLoader · per letter (phrase + space)93 </span>94 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">95 <TextShimmerLoader96 text="Almost ready"97 granularity="letter"98 speed={1.05}99 />100 </div>101 </div>102 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">103 <span className="text-xs font-medium text-muted-foreground">104 AIThinkingLoader · per word105 </span>106 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">107 <AIThinkingLoader granularity="word" />108 </div>109 </div>110 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">111 <span className="text-xs font-medium text-muted-foreground">112 UserTypingStatus · prefix per letter113 </span>114 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">115 <UserTypingStatus prefixGranularity="letter" speed={1.2} />116 </div>117 </div>118 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">119 <span className="text-xs font-medium text-muted-foreground">120 UserTypingStatus · prefix per word121 </span>122 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">123 <UserTypingStatus124 prefix="Someone is typing"125 prefixGranularity="word"126 />127 </div>128 </div>129 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">130 <span className="text-xs font-medium text-muted-foreground">131 StreamingTextSkeleton · 5 lines · fast132 </span>133 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">134 <StreamingTextSkeleton135 className="max-w-56"136 lines={5}137 speed={1.6}138 />139 </div>140 </div>141 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">142 <span className="text-xs font-medium text-muted-foreground">143 CursorBlinkLoader · Compose · speed 1.8144 </span>145 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">146 <CursorBlinkLoader text="Compose" speed={1.8} />147 </div>148 </div>149 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">150 <span className="text-xs font-medium text-muted-foreground">151 TypingIndicator · speed 1.5152 </span>153 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">154 <TypingIndicator speed={1.5} />155 </div>156 </div>157 </div>158 </div>159 </div>160 );161}
Voice status
VoiceStatusLoader variants for listening, recording, and processing.
Compact row for dictation or voice UI. speed scales the pulse dot.
VoiceStatusLoader · Listening
Listening
VoiceStatusLoader · Recording · speed 1.3
Recording
VoiceStatusLoader · Processing · speed 1.6
Processing
voice-example.tsx
1import { VoiceStatusLoader } from "@/registry/ui";23export function LoadersVoiceExample() {4 return (5 <div className="space-y-3">6 <p className="text-sm text-muted-foreground">7 Compact row for dictation or voice UI.{" "}8 <code className="text-foreground">speed</code> scales the pulse dot.9 </p>10 <div className="mx-auto grid max-w-6xl grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">11 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">12 <span className="text-xs font-medium text-muted-foreground">13 VoiceStatusLoader · Listening14 </span>15 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">16 <VoiceStatusLoader status="Listening" />17 </div>18 </div>19 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">20 <span className="text-xs font-medium text-muted-foreground">21 VoiceStatusLoader · Recording · speed 1.322 </span>23 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">24 <VoiceStatusLoader status="Recording" speed={1.3} />25 </div>26 </div>27 <div className="flex min-h-[148px] flex-col gap-4 rounded-xl border border-border/60 bg-muted/10 p-5">28 <span className="text-xs font-medium text-muted-foreground">29 VoiceStatusLoader · Processing · speed 1.630 </span>31 <div className="flex min-h-12 w-full min-w-0 flex-1 items-center justify-center">32 <VoiceStatusLoader status="Processing" speed={1.6} />33 </div>34 </div>35 </div>36 </div>37 );38}
Inline row
Compact strip for toolbars or footers (mixed primitives).
inline-example.tsx
1import {2 MorphBlobLoader,3 OrbitLoader,4 PulseDotsLoader,5 SpinnerRing,6 TypingIndicator,7 WaveBarsLoader,8} from "@/registry/ui";910export function LoadersInlineExample() {11 return (12 <div className="flex flex-wrap items-center gap-6 rounded-xl border border-border/60 bg-background p-6">13 <PulseDotsLoader />14 <SpinnerRing />15 <WaveBarsLoader />16 <TypingIndicator />17 <OrbitLoader />18 <MorphBlobLoader />19 </div>20 );21}
Installation & source
Install via the shadcn CLI or copy the registry files manually.
bash
npx shadcn@latest add @tt-ui/loaders
Props
| Name | Type | Default | Description |
|---|---|---|---|
| TextPulseGranularity | "line" | "word" | "letter" | - | Exported type: line = whole-string pulse; word/letter = staggered opacity tokens |
| speed | number | 1 | Most loaders: clamped ~0.25–4; scales durations (higher = faster). Applies to motion primitives, text pulses, skeleton lines, caret, ellipsis, voice dot |
| TextShimmerLoader / AIThinkingLoader | components | granularity: line; AI text default | text, className, granularity, speed - AIThinkingLoader also accepts custom `text` |
| UserTypingStatus | component | prefixGranularity: none | prefix, prefixGranularity (none | line | word | letter), speed - ellipsis rate follows speed |
| StreamingTextSkeleton | component | lines: 3 | lines (1–8), speed - per-line opacity loop with stagger |
| CursorBlinkLoader | component | text: "" | text, className, speed - caret blink duration scales with speed |
| PulseDotsLoader / SpinnerRing / WaveBarsLoader / OrbitLoader / MorphBlobLoader / TypingIndicator / ProgressLineLoader / VoiceStatusLoader | components | speed: 1 | className + optional speed for motion timing |
| SkeletonCardLoader | component | - | className on the bordered placeholder card |