loading-state-zoo 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +588 -0
- package/dist/index.cjs +291 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +90 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.js +291 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +291 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +276 -0
- package/dist/react.d.ts +276 -0
- package/dist/react.js +291 -0
- package/dist/react.js.map +1 -0
- package/dist/theme.css +525 -0
- package/docs/AI.md +69 -0
- package/docs/components.json +533 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
# loading-state-zoo
|
|
2
|
+
|
|
3
|
+
**17 loading patterns, one tiny package.** Dots, spinners, shapes, bars and skeletons that tell the user "please wait" — made silky smooth and ready to use in **React**, **plain websites**, and **iOS / Android apps**.
|
|
4
|
+
|
|
5
|
+
Think of it as a small zoo of loading animals. You pick an animal, put it in your app's cage, and it starts moving right away. You can even change its **color**, **size** and **speed** — no scissors or glue required.
|
|
6
|
+
|
|
7
|
+
- **No heavy setup.** Works everywhere a web view works. Zero required runtime dependencies.
|
|
8
|
+
- **Private by design.** Patterns live inside their own shadow DOM — their styles can never leak into your app, and your styles never break them.
|
|
9
|
+
- **Smooth.** Only `transform` and `opacity` ever animate, so it stays at 60fps even on phones.
|
|
10
|
+
- **Tunable.** Every color, size, speed AND every keyframe number is customizable (see [Colors & sizes](#colors-and-sizes) and [Tune the keyframes](#tune-the-keyframes)).
|
|
11
|
+
|
|
12
|
+
> Looking for AI-friendly docs? See **[docs/AI.md](./docs/AI.md)** and the machine-readable **[docs/components.json](./docs/components.json)**.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## The animals in the zoo
|
|
17
|
+
|
|
18
|
+
| Name | Kind | Good for |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| [Bouncing dots](#bouncing-dots) | Dots | Loading a feed or a small section |
|
|
21
|
+
| [Typing dots](#typing-dots) | Dots | Chat apps, message "typing…" feel |
|
|
22
|
+
| [Wave dots](#wave-dots) | Dots | Waiting for a refresh or sync |
|
|
23
|
+
| [Helix dots](#helix-dots) | Dots | Data processing, fun & playful |
|
|
24
|
+
| [Dot grid wave](#dot-grid-wave) | Dots | Brick/grid placeholders, dashboards |
|
|
25
|
+
| [Arc spinner](#arc-spinner) | Spinner | Classic circular loading |
|
|
26
|
+
| [Material double arc](#material-double-arc) | Spinner | Android/Material look and feel |
|
|
27
|
+
| [Scan sweep](#scan-sweep) | Spinner | Radar/sonar, scanning, searching |
|
|
28
|
+
| [Orbit dots](#orbit-dots) | Spinner | Floaty, lightweight loading |
|
|
29
|
+
| [Orbit ring dots](#orbit-ring-dots) | Spinner | Cosmetic ring, data-heavy load |
|
|
30
|
+
| [Eyes](#eyes) | Shape | Fun state, "watching" waiting |
|
|
31
|
+
| [Morphing square](#morphing-square) | Shape | Modern brand moments |
|
|
32
|
+
| [Breathing pulse](#breathing-pulse) | Shape | Subtle, gentle "alive" loading |
|
|
33
|
+
| [Equalizer](#equalizer) | Bars & rings | Music, audio, waveform |
|
|
34
|
+
| [Progress ring](#progress-ring) | Bars & rings | Showing exact percent done |
|
|
35
|
+
| [Indeterminate progress bar](#indeterminate-progress-bar) | Bars & rings | "Doing something, no % yet" bar |
|
|
36
|
+
| [Skeleton shimmer](#skeleton-shimmer) | Skeleton | Placeholder while real content loads |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install loading-state-zoo
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
One package, three styles of use:
|
|
47
|
+
|
|
48
|
+
| Entry point | What you get |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `loading-state-zoo` | Web components (works everywhere) |
|
|
51
|
+
| `loading-state-zoo/react` | The React components |
|
|
52
|
+
| `loading-state-zoo/theme.css` | Plain CSS + markup (no JavaScript) |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Quick start: React
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { BouncingDots, ArcSpinner, SkeletonShimmer, ProgressRing } from "loading-state-zoo/react";
|
|
60
|
+
|
|
61
|
+
export function MyLoader() {
|
|
62
|
+
return (
|
|
63
|
+
<>
|
|
64
|
+
<BouncingDots />
|
|
65
|
+
<ArcSpinner size={64} color="#0a84ff" />
|
|
66
|
+
<SkeletonShimmer width={240} height={20} />
|
|
67
|
+
<ProgressRing percent={65} size={56} strokeWidth={6} />
|
|
68
|
+
</>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
That's it. Importing the package **automatically registers** all 17 elements for you (it's safe to import in many places — duplicates are skipped). It is also safe on the server (SSR/Next.js): on Node there is no browser, so nothing registers and nothing breaks.
|
|
74
|
+
|
|
75
|
+
If you prefer to register manually:
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { defineAll } from "loading-state-zoo"; // or from "loading-state-zoo/react"
|
|
79
|
+
defineAll();
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Quick start: plain website
|
|
85
|
+
|
|
86
|
+
Add the package from a CDN (or bundle it) and write the tags directly in your HTML.
|
|
87
|
+
|
|
88
|
+
```html
|
|
89
|
+
<script type="module">
|
|
90
|
+
import "https://unpkg.com/loading-state-zoo";
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<div style="display:flex; gap:24px; align-items:center">
|
|
94
|
+
<lz-wave-dots></lz-wave-dots>
|
|
95
|
+
<lz-orbit-dots size="56" color="#30d158"></lz-orbit-dots>
|
|
96
|
+
<lz-scan-sweep size="56" color="#0a84ff"></lz-scan-sweep>
|
|
97
|
+
<lz-morphing-square accent="#ff9f0a" speed="0.7"></lz-morphing-square>
|
|
98
|
+
</div>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Mix and match any of the 17 tags — see the full list below.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Quick start: CSS only (no JavaScript at all)
|
|
106
|
+
|
|
107
|
+
Sometimes you just want markup and CSS — great for email-ish constraints, or for shipping the *exact* look to an iOS/Android WebView without any JS.
|
|
108
|
+
|
|
109
|
+
```html
|
|
110
|
+
<link rel="stylesheet" href="https://unpkg.com/loading-state-zoo/theme.css" />
|
|
111
|
+
|
|
112
|
+
<div style="--lz-color:#0a84ff; --lz-speed:0.8">
|
|
113
|
+
<span class="lz-dot-grid-wave" style="--lz-size:8px; --lz-grid-gap:14px">
|
|
114
|
+
<i class="lz-dot"></i><i class="lz-dot"></i><i class="lz-dot"></i>
|
|
115
|
+
<i class="lz-dot"></i><i class="lz-dot"></i><i class="lz-dot"></i>
|
|
116
|
+
</span>
|
|
117
|
+
</div>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Every pattern also ships as a `.lz-<pattern>` CSS class with `.lz-<part>` children. The part markup is identical to what the web components render — open any pattern on [the demo site](https://loading-state-zoo.pages.dev), inspect it, and copy the inner HTML.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Quick start: iOS & Android (WebView)
|
|
125
|
+
|
|
126
|
+
Any of the three styles above (web components **or** the CSS classes) run inside a `WKWebView` (iOS) or an Android `WebView`. The patterns are just HTML + CSS — no framework runtime, no bundler magic, nothing native to install.
|
|
127
|
+
|
|
128
|
+
1. Bundle the ESM file into your app's assets:
|
|
129
|
+
- iOS: copy `dist/index.js` into your Xcode target and load it in `WKWebView`.
|
|
130
|
+
- Android: copy it into `assets/` and inject it with `WebView#evaluateJavascript`, or load it as a local `<script>`.
|
|
131
|
+
2. Or skip JS entirely and embed the HTML + `theme.css` directly (see above).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Colors and sizes
|
|
136
|
+
|
|
137
|
+
**Yes — every component's color and size are customizable**, three different ways. You can also change the accent color, stroke thickness, dot count and more.
|
|
138
|
+
|
|
139
|
+
### 1. By attribute (easiest)
|
|
140
|
+
|
|
141
|
+
```html
|
|
142
|
+
<lz-bouncing-dots size="12" color="#30d158"></lz-bouncing-dots>
|
|
143
|
+
<lz-arc-spinner size="64" stroke-width="6" color="#ff9f0a"></lz-arc-spinner>
|
|
144
|
+
<lz-progress-ring percent="70" size="56" stroke-width="6" color="#0a84ff" track-color="rgba(255,255,255,0.2)"></lz-progress-ring>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
import { BouncingDots, ArcSpinner, ProgressRing } from "loading-state-zoo/react";
|
|
149
|
+
<>
|
|
150
|
+
<BouncingDots size={12} color="#30d158" />
|
|
151
|
+
<ArcSpinner size={64} strokeWidth={6} color="#ff9f0a" />
|
|
152
|
+
<ProgressRing percent={70} size={56} strokeWidth={6} color="#0a84ff" trackColor="rgba(255,255,255,0.2)" />
|
|
153
|
+
</>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### 2. By CSS variable (theme whole groups)
|
|
157
|
+
|
|
158
|
+
Set a variable on a wrapper element and **every pattern inside** inherits it.
|
|
159
|
+
|
|
160
|
+
```html
|
|
161
|
+
<div style="--lz-color:#0a84ff; --lz-accent:#30d158; --lz-speed:0.75">
|
|
162
|
+
<lz-wave-dots></lz-wave-dots>
|
|
163
|
+
<lz-orbit-dots></lz-orbit-dots>
|
|
164
|
+
<lz-morphing-square></lz-morphing-square>
|
|
165
|
+
</div>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 3. Common attributes (available on every pattern)
|
|
169
|
+
|
|
170
|
+
| Attribute | React prop | What it does | Default |
|
|
171
|
+
| --- | --- | --- | --- |
|
|
172
|
+
| `size` | `size` | Main dimension in px (dot diameter, or spinner/box size) | pattern-specific |
|
|
173
|
+
| `color` | `color` | Main foreground color (dots, arcs, bars, eyes) | `#f5f5f7` |
|
|
174
|
+
| `accent` | `accent` | Accent/brand color (morph square, progress bar, ring fill) | `#0a84ff` |
|
|
175
|
+
| `speed` | `speed` | Animation speed — `0.5` half speed, `2` double speed | `1` |
|
|
176
|
+
| `width` | `width` | Width in px (bars & skeletons) | pattern-specific |
|
|
177
|
+
| `height` | `height` | Height in px (bars & skeletons) | pattern-specific |
|
|
178
|
+
|
|
179
|
+
### Shared CSS variables (all patterns)
|
|
180
|
+
|
|
181
|
+
| Variable | What it does | Default |
|
|
182
|
+
| --- | --- | --- |
|
|
183
|
+
| `--lz-color` | Foreground color everywhere | `#f5f5f7` |
|
|
184
|
+
| `--lz-accent` | Accent color | `#0a84ff` |
|
|
185
|
+
| `--lz-speed` | Duration multiplier | `1` |
|
|
186
|
+
| `--lz-surface` | Track / skeleton background | `#1c1c1e` |
|
|
187
|
+
| `--lz-stroke` | Ring thickness (px) | `4px` |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Tune the keyframes
|
|
192
|
+
|
|
193
|
+
Every number inside every animation is also a CSS variable. Change how far dots bounce, how much a pulse grows, how fast eyes blink — on one pattern or on a whole app.
|
|
194
|
+
|
|
195
|
+
```html
|
|
196
|
+
<div style="--lz-bounce:-16px; --lz-typing-peak:1.5; --lz-helix:-18px">
|
|
197
|
+
<lz-bouncing-dots></lz-bouncing-dots>
|
|
198
|
+
<lz-typing-dots></lz-typing-dots>
|
|
199
|
+
<lz-helix-dots></lz-helix-dots>
|
|
200
|
+
</div>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
| Variable | Pattern it changes | What it is | Default |
|
|
204
|
+
| --- | --- | --- | --- |
|
|
205
|
+
| `--lz-bounce` | Bouncing dots | How high the dots jump | `-10px` |
|
|
206
|
+
| `--lz-typing-min` | Typing dots | Smallest dot size | `0.35` |
|
|
207
|
+
| `--lz-typing-peak` | Typing dots | Biggest dot size | `1.15` |
|
|
208
|
+
| `--lz-wave-min` | Wave dots | Smallest dot size | `0.35` |
|
|
209
|
+
| `--lz-wave-peak` | Wave dots | Biggest dot size | `1.1` |
|
|
210
|
+
| `--lz-helix` | Helix dots | How far dots bob up | `-12px` |
|
|
211
|
+
| `--lz-grid-min` | Dot grid wave | Smallest dot size | `0.3` |
|
|
212
|
+
| `--lz-grid-fade` | Dot grid wave | Fade of resting dots | `0.15` |
|
|
213
|
+
| `--lz-breath` | Breathing pulse | How much it grows | `1.14` |
|
|
214
|
+
| `--lz-morph` | Morphing square | Smallest scale | `0.72` |
|
|
215
|
+
| `--lz-morph-radius` | Morphing square | Corner roundness at mid-morph | `17%` |
|
|
216
|
+
| `--lz-gaze-from` | Eyes | Pupil start offset | `-3px` |
|
|
217
|
+
| `--lz-gaze-to` | Eyes | Pupil end offset | `3px` |
|
|
218
|
+
| `--lz-blink` | Eyes | How closed the blink gets | `0.08` |
|
|
219
|
+
| `--lz-sheen-from` | Skeleton shimmer | Sheen start position | `-120%` |
|
|
220
|
+
| `--lz-sheen-to` | Skeleton shimmer | Sheen end position | `220%` |
|
|
221
|
+
| `--lz-orbit-fade` | Orbit ring dots | Fade of resting dots | `0.12` |
|
|
222
|
+
| `--lz-eq-min` | Equalizer | Shortest bar height | `0.3` |
|
|
223
|
+
| `--lz-slide-from` | Indeterminate bar | Slider start position | `-100%` |
|
|
224
|
+
| `--lz-slide-to` | Indeterminate bar | Slider end position | `300%` |
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Full component reference
|
|
229
|
+
|
|
230
|
+
Each section lists:
|
|
231
|
+
- **What it is** — plain words
|
|
232
|
+
- **Good for** — when to pick it
|
|
233
|
+
- **HTML** — the tag + attributes
|
|
234
|
+
- **React** — the component + props
|
|
235
|
+
- **Extra attributes & variables**
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
### Bouncing dots
|
|
240
|
+
|
|
241
|
+
**What it is:** three round dots that hop up and down, one after another. **Good for:** waiting on a list, feed, or small section refresh.
|
|
242
|
+
|
|
243
|
+
```html
|
|
244
|
+
<lz-bouncing-dots></lz-bouncing-dots>
|
|
245
|
+
<lz-bouncing-dots size="12" color="#0a84ff"></lz-bouncing-dots>
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
<BouncingDots />
|
|
250
|
+
<BouncingDots size={12} color="#0a84ff" />
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Attributes: `size` (dot size, default `8`) · `color` · `speed`.
|
|
254
|
+
Variables: `--lz-color` · `--lz-speed` · `--lz-bounce`.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
### Typing dots
|
|
259
|
+
|
|
260
|
+
**What it is:** three dots that blink in a soft typing rhythm. **Good for:** chat, messaging, "typing…" moments.
|
|
261
|
+
|
|
262
|
+
```html
|
|
263
|
+
<lz-typing-dots></lz-typing-dots>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
<TypingDots />
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Attributes: `size` (default `8`) · `color` · `speed`.
|
|
271
|
+
Variables: `--lz-typing-min` · `--lz-typing-peak`.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### Wave dots
|
|
276
|
+
|
|
277
|
+
**What it is:** four dots that swell like a gentle wave. **Good for:** refresh, sync, pull-in-progress.
|
|
278
|
+
|
|
279
|
+
```html
|
|
280
|
+
<lz-wave-dots></lz-wave-dots>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
<WaveDots />
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Attributes: `size` (default `8`) · `color` · `speed`.
|
|
288
|
+
Variables: `--lz-wave-min` · `--lz-wave-peak`.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
### Helix dots
|
|
293
|
+
|
|
294
|
+
**What it is:** a long row of dots that bob like a travelling wave. **Good for:** data crunching, fun playful waits.
|
|
295
|
+
|
|
296
|
+
```html
|
|
297
|
+
<lz-helix-dots count="14"></lz-helix-dots>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
<HelixDots count={14} />
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Attributes: `size` (default `6`) · `count` (default `10`) · `color` · `speed`.
|
|
305
|
+
Variables: `--lz-helix`.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
### Dot grid wave
|
|
310
|
+
|
|
311
|
+
**What it is:** a grid of dots that ripple outward from a corner. **Good for:** brick layouts, dashboards, big empty panels.
|
|
312
|
+
|
|
313
|
+
```html
|
|
314
|
+
<lz-dot-grid-wave rows="4" cols="6" size="8" gap="14"></lz-dot-grid-wave>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
<DotGridWave rows={4} cols={6} size={8} gap={14} />
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Attributes: `size` (default `6`) · `rows` (default `4`) · `cols` (default `5`) · `gap` (default `12`) · `color` · `speed`.
|
|
322
|
+
Variables: `--lz-grid-gap` · `--lz-grid-min` · `--lz-grid-fade`.
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
### Arc spinner
|
|
327
|
+
|
|
328
|
+
**What it is:** one spinning "pac-man" ring. The classic. **Good for:** any circular wait.
|
|
329
|
+
|
|
330
|
+
```html
|
|
331
|
+
<lz-arc-spinner size="64" stroke-width="6" color="#0a84ff"></lz-arc-spinner>
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
<ArcSpinner size={64} strokeWidth={6} color="#0a84ff" />
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Attributes: `size` (default `44`) · `stroke-width` (default `4`) · `color` · `speed`.
|
|
339
|
+
Variables: `--lz-stroke`.
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
### Material double arc
|
|
344
|
+
|
|
345
|
+
**What it is:** two spinning arcs, opposite directions — the Material Design look. **Good for:** Android-style apps, "processing".
|
|
346
|
+
|
|
347
|
+
```html
|
|
348
|
+
<lz-material-double-arc size="56" stroke-width="5"></lz-material-double-arc>
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
```tsx
|
|
352
|
+
<MaterialDoubleArc size={56} strokeWidth={5} />
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Attributes: `size` (default `44`) · `stroke-width` (default `4`) · `color` · `color-weak` (second arc tint) · `speed`.
|
|
356
|
+
Variables: `--lz-stroke` · `--lz-color-weak`.
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
### Scan sweep
|
|
361
|
+
|
|
362
|
+
**What it is:** concentric rings with a sweeping beam — like radar. **Good for:** scanning, searching, syncing data.
|
|
363
|
+
|
|
364
|
+
```html
|
|
365
|
+
<lz-scan-sweep size="64" color="#30d158"></lz-scan-sweep>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
<ScanSweep size={64} color="#30d158" />
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Attributes: `size` (default `44`) · `color` · `color-weak` · `color-sweep` · `speed`.
|
|
373
|
+
Variables: `--lz-track` · `--lz-track-weak` · `--lz-color-weak` · `--lz-color-sweep`.
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
### Orbit dots
|
|
378
|
+
|
|
379
|
+
**What it is:** three dots glide around an invisible circle. **Good for:** light, floaty waits.
|
|
380
|
+
|
|
381
|
+
```html
|
|
382
|
+
<lz-orbit-dots size="56" color="#0a84ff"></lz-orbit-dots>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
<OrbitDots size={56} color="#0a84ff" />
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Attributes: `size` (default `44`) · `color` · `speed`.
|
|
390
|
+
Variables: `--lz-color-weak` (dot tint).
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
### Orbit ring dots
|
|
395
|
+
|
|
396
|
+
**What it is:** eight dots on a ring that fade in a chasing sequence. **Good for:** elegant circular waits, brand moments.
|
|
397
|
+
|
|
398
|
+
```html
|
|
399
|
+
<lz-orbit-ring-dots size="56" dot-size="10"></lz-orbit-ring-dots>
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
```tsx
|
|
403
|
+
<OrbitRingDots size={56} dotSize={10} />
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Attributes: `size` (default `44`) · `dot-size` (default derived) · `color` · `speed`.
|
|
407
|
+
Variables: `--lz-dot-size` · `--lz-orbit-fade`.
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
### Eyes
|
|
412
|
+
|
|
413
|
+
**What it is:** two cartoon eyes that look side to side and blink. **Good for:** fun apps, "watching" moments, kids' stuff.
|
|
414
|
+
|
|
415
|
+
```html
|
|
416
|
+
<lz-eyes size="56"></lz-eyes>
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
```tsx
|
|
420
|
+
<Eyes size={56} />
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
Attributes: `size` (default `44`) · `color` (sclera) · `speed`.
|
|
424
|
+
Variables: `--lz-pupil` (pupil color) · `--lz-gaze-from` · `--lz-gaze-to` · `--lz-blink`.
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
### Morphing square
|
|
429
|
+
|
|
430
|
+
**What it is:** a glowing square that swells, rounds and spins. **Good for:** modern splash states, brand colors.
|
|
431
|
+
|
|
432
|
+
```html
|
|
433
|
+
<lz-morphing-square accent="#bf5af2" size="56"></lz-morphing-square>
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
```tsx
|
|
437
|
+
<MorphingSquare accent="#bf5af2" size={56} />
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
Attributes: `size` (default `44`) · `accent` (default `#0a84ff`) · `speed`.
|
|
441
|
+
Variables: `--lz-glow` (glow color/shadow) · `--lz-morph` · `--lz-morph-radius`.
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
### Breathing pulse
|
|
446
|
+
|
|
447
|
+
**What it is:** one soft circle that gently grows and shrinks. **Good for:** subtle "alive" waits, background states.
|
|
448
|
+
|
|
449
|
+
```html
|
|
450
|
+
<lz-breathing-pulse size="48" color="#30d158"></lz-breathing-pulse>
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
```tsx
|
|
454
|
+
<BreathingPulse size={48} color="#30d158" />
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Attributes: `size` (default `36`) · `color` · `speed`.
|
|
458
|
+
Variables: `--lz-breath`.
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
### Equalizer
|
|
463
|
+
|
|
464
|
+
**What it is:** four bars dancing like a music equalizer. **Good for:** audio, music, waveform loading.
|
|
465
|
+
|
|
466
|
+
```html
|
|
467
|
+
<lz-equalizer size="24" bar-width="4" gap="4" color="#ff375f"></lz-equalizer>
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
```tsx
|
|
471
|
+
<Equalizer size={24} barWidth={4} gap={4} color="#ff375f" />
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
Attributes: `size` (bar height, default `22`) · `bar-width` (default `3`) · `gap` (default `3`) · `color` · `speed`.
|
|
475
|
+
Variables: `--lz-bar-width` · `--lz-gap` · `--lz-eq-min`.
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
### Progress ring
|
|
480
|
+
|
|
481
|
+
**What it is:** a ring that fills to a percentage. **Good for:** uploads, downloads, tasks with a known percent. *(Not animated by itself — you drive it with the `percent` attribute.)*
|
|
482
|
+
|
|
483
|
+
```html
|
|
484
|
+
<lz-progress-ring percent="65" size="56" stroke-width="6" color="#0a84ff" track-color="rgba(255,255,255,0.15)"></lz-progress-ring>
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
```tsx
|
|
488
|
+
<ProgressRing percent={65} size={56} strokeWidth={6} color="#0a84ff" trackColor="rgba(255,255,255,0.15)" />
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
Attributes: `size` (default `44`) · `stroke-width` (default `4`) · `percent` (default `0`, clamped to 0–100) · `color` (fill) · `track-color` · `speed`.
|
|
492
|
+
Variables: `--lz-stroke` · `--lz-track`.
|
|
493
|
+
|
|
494
|
+
Accessibility: it exposes `role="progressbar"` plus `aria-valuenow/min/max`, and updates them when `percent` changes.
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
### Indeterminate progress bar
|
|
499
|
+
|
|
500
|
+
**What it is:** a bar with a slider that slides back and forth. Classic "we're working on it". **Good for:** long unknown tasks.
|
|
501
|
+
|
|
502
|
+
```html
|
|
503
|
+
<lz-indeterminate-progress-bar width="220" height="8" accent="#0a84ff"></lz-indeterminate-progress-bar>
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
```tsx
|
|
507
|
+
<IndeterminateProgressBar width={220} height={8} accent="#0a84ff" />
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
Attributes: `width` (default `160`) · `height` (default `6`) · `accent` (default `#0a84ff`) · `track-color` · `speed`.
|
|
511
|
+
Variables: `--lz-accent` · `--lz-surface` · `--lz-slide-from` · `--lz-slide-to`.
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
### Skeleton shimmer
|
|
516
|
+
|
|
517
|
+
**What it is:** a rounded block with a light that sweeps across. **Good for:** placeholders while real content loads (images, profiles, cards).
|
|
518
|
+
|
|
519
|
+
```html
|
|
520
|
+
<lz-skeleton-shimmer width="240" height="24"></lz-skeleton-shimmer>
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
```tsx
|
|
524
|
+
<SkeletonShimmer width={240} height={24} />
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
Attributes: `width` (default `120`) · `height` (default `28`) · `track-color` · `speed`.
|
|
528
|
+
Variables: `--lz-surface` · `--lz-sheen` (sweep light color) · `--lz-radius` · `--lz-sheen-from` · `--lz-sheen-to`.
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## Accessibility
|
|
533
|
+
|
|
534
|
+
- Every pattern is announced to screen readers: dots/spinners/bars use `role="status"` with `aria-label="Loading"`.
|
|
535
|
+
- The progress ring uses `role="progressbar"` with live `aria-valuenow`, `aria-valuemin` and `aria-valuemax`.
|
|
536
|
+
- **Reduced motion:** the package does *not* force-disable animations, so you keep full control:
|
|
537
|
+
|
|
538
|
+
```css
|
|
539
|
+
@media (prefers-reduced-motion: reduce) {
|
|
540
|
+
lz-bouncing-dots, lz-wave-dots,
|
|
541
|
+
lz-arc-spinner, lz-orbit-dots /* …and so on… */ {
|
|
542
|
+
animation-duration: 4s; /* or hide: animation: none */
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
---
|
|
548
|
+
|
|
549
|
+
## Performance & best practices
|
|
550
|
+
|
|
551
|
+
- Only `transform` and `opacity` animate — the compositor handles them, so the main thread stays free.
|
|
552
|
+
- Fewer moving parts = cheaper. Prefer dots (Bouncing, Wave) for areas that appear often; keep spinners (Arc, Material) for a few spots.
|
|
553
|
+
- Swap `percent` on the progress ring directly from your state — no animation frame loops needed.
|
|
554
|
+
- The web components have **zero global CSS** — they can be dropped into the messiest existing page without side effects.
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## FAQ
|
|
559
|
+
|
|
560
|
+
**Q: Do I need Tailwind or a bundler?** No. The package is standalone.
|
|
561
|
+
|
|
562
|
+
**Q: Does it collect any data?** No. Nothing tracks, stores, or sends user data. It's just drawing.
|
|
563
|
+
|
|
564
|
+
**Q: Do I need a privacy policy for this package?** No. It's a code library, not a service, and it collects nothing.
|
|
565
|
+
|
|
566
|
+
**Q: Can I use it in my commercial app?** Yes — MIT license.
|
|
567
|
+
|
|
568
|
+
**Q: Can I change sizes and colors?** Yes — attributes, React props, or CSS variables. See [Colors and sizes](#colors-and-sizes).
|
|
569
|
+
|
|
570
|
+
**Q: iOS/Android native, not WebView?** Not natively — but every modern nav/load UI is fine in a WebView; use the [CSS-only approach](#quick-start--css-only-no-javascript-at-all) for the smallest footprint.
|
|
571
|
+
|
|
572
|
+
---
|
|
573
|
+
|
|
574
|
+
## For AI assistants (LLMs, coding agents)
|
|
575
|
+
|
|
576
|
+
A condensed, machine-honest summary lives in **[docs/AI.md](./docs/AI.md)** and the full structured spec for every component in **[docs/components.json](./docs/components.json)**.
|
|
577
|
+
|
|
578
|
+
Key facts an AI should always know:
|
|
579
|
+
|
|
580
|
+
1. **Auto-registration:** importing any entry point registers all custom elements exactly once. Do not call `defineAll()` again.
|
|
581
|
+
2. **Entry points:** `loading-state-zoo` (web components), `loading-state-zoo/react` (React), `loading-state-zoo/theme.css` (plain CSS).
|
|
582
|
+
3. **React prop ≈ attribute**, but multi-word attributes are camelCased in React (`stroke-width` → `strokeWidth`, `track-color` → `trackColor`).
|
|
583
|
+
4. **Theming = CSS variables.** `--lz-color`, `--lz-accent`, `--lz-speed` on a parent inherit into all patterns inside it.
|
|
584
|
+
5. **Keyframe numbers are variables too.** There is no need to fork CSS to change motion — set `--lz-bounce`, `--lz-typing-peak`, etc.
|
|
585
|
+
|
|
586
|
+
## License
|
|
587
|
+
|
|
588
|
+
MIT — free to use in commercial projects, no attribution required (but appreciated).
|