modern-loaders 1.2.2 → 1.2.3
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 +226 -116
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,15 +24,16 @@ npm install modern-loaders
|
|
|
24
24
|
|
|
25
25
|
## What is modern-loaders?
|
|
26
26
|
|
|
27
|
-
A library of **212 loading animations** for React, all behind a single
|
|
27
|
+
A library of **212 loading animations** for React, all behind a single
|
|
28
|
+
`<Loader />` component.
|
|
28
29
|
|
|
29
|
-
**The problem.** Every app needs loading states. Building them by hand means
|
|
30
|
-
again and again. Most loader packages give you a handful
|
|
31
|
-
animation runtime you did not ask for.
|
|
30
|
+
**The problem.** Every app needs loading states. Building them by hand means
|
|
31
|
+
writing CSS keyframes again and again. Most loader packages give you a handful
|
|
32
|
+
of spinners, or pull in a JavaScript animation runtime you did not ask for.
|
|
32
33
|
|
|
33
|
-
**This package.** Pick a loader by name, set the size, speed and colours if you
|
|
34
|
-
Every animation is plain CSS, so nothing runs on the main
|
|
35
|
-
alongside it.
|
|
34
|
+
**This package.** Pick a loader by name, set the size, speed and colours if you
|
|
35
|
+
want, and ship. Every animation is plain CSS, so nothing runs on the main
|
|
36
|
+
thread and there is nothing to install alongside it.
|
|
36
37
|
|
|
37
38
|
### Why developers use it
|
|
38
39
|
|
|
@@ -45,9 +46,7 @@ alongside it.
|
|
|
45
46
|
|
|
46
47
|
---
|
|
47
48
|
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
### 1. Install
|
|
49
|
+
## Installation
|
|
51
50
|
|
|
52
51
|
```bash
|
|
53
52
|
npm install modern-loaders
|
|
@@ -58,12 +57,25 @@ npm install modern-loaders
|
|
|
58
57
|
|
|
59
58
|
```bash
|
|
60
59
|
yarn add modern-loaders
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```bash
|
|
61
63
|
pnpm add modern-loaders
|
|
62
64
|
```
|
|
63
65
|
|
|
64
66
|
</details>
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
**No CSS import needed.** The stylesheet is bundled and injects itself — nothing
|
|
69
|
+
to configure in Vite, Next.js, CRA, or Tailwind.
|
|
70
|
+
|
|
71
|
+
<sub>If your bundler strips side-effect imports, add
|
|
72
|
+
<code>import "modern-loaders/styles.css"</code>.</sub>
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
### 1. Render a loader
|
|
67
79
|
|
|
68
80
|
```tsx
|
|
69
81
|
import { Loader } from "modern-loaders";
|
|
@@ -73,54 +85,48 @@ export default function App() {
|
|
|
73
85
|
}
|
|
74
86
|
```
|
|
75
87
|
|
|
76
|
-
|
|
77
|
-
remember, nothing to configure in Vite, Next.js, CRA, or Tailwind.
|
|
88
|
+
### 2. Pick a variant
|
|
78
89
|
|
|
79
|
-
|
|
90
|
+
Every loader has a name. Pass it as `variant`:
|
|
80
91
|
|
|
81
|
-
|
|
92
|
+
```tsx
|
|
93
|
+
<Loader variant="wave" />
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 3. Customise it
|
|
82
97
|
|
|
83
|
-
|
|
98
|
+
Set the size, speed and colours:
|
|
84
99
|
|
|
85
100
|
```tsx
|
|
86
|
-
<Loader
|
|
101
|
+
<Loader
|
|
102
|
+
variant="wave"
|
|
103
|
+
size={72}
|
|
104
|
+
speed={0.8}
|
|
105
|
+
colors={["#f97316", "#ef4444", "#a855f7"]}
|
|
106
|
+
/>
|
|
87
107
|
```
|
|
88
108
|
|
|
89
|
-
Not sure which one to pick?
|
|
109
|
+
Not sure which one to pick?
|
|
110
|
+
[**Browse all 212 in the live gallery →**](https://modern-loaders.netlify.app/)
|
|
90
111
|
|
|
91
112
|
---
|
|
92
113
|
|
|
93
114
|
## Contents
|
|
94
115
|
|
|
95
|
-
- [
|
|
96
|
-
- [Which loader should I use?](#which-loader-should-i-use)
|
|
116
|
+
- [Choosing a loader](#choosing-a-loader)
|
|
97
117
|
- [Recipes](#recipes)
|
|
118
|
+
- [Customization](#customization)
|
|
119
|
+
- [API](#api)
|
|
98
120
|
- [All 212 variants](#all-212-variants)
|
|
99
|
-
- [Theming](#theming)
|
|
100
121
|
- [Accessibility](#accessibility)
|
|
101
122
|
- [Bundle size](#bundle-size)
|
|
102
|
-
- [Named exports](#named-exports)
|
|
103
123
|
- [Browser support](#browser-support)
|
|
104
|
-
- [
|
|
124
|
+
- [Contributing](#contributing)
|
|
105
125
|
- [License](#license)
|
|
106
126
|
|
|
107
127
|
---
|
|
108
128
|
|
|
109
|
-
##
|
|
110
|
-
|
|
111
|
-
| prop | type | default | description |
|
|
112
|
-
|---|---|---|---|
|
|
113
|
-
| `variant` | `LoaderVariant` | `"aurora"` | Which loader to render — any of the 212 ids below. |
|
|
114
|
-
| `size` | `number \| string` | `48` | Overall size. A number means pixels; strings pass through (`"3rem"`). |
|
|
115
|
-
| `speed` | `number \| string` | `1` | Base duration. A number means seconds; lower is faster. |
|
|
116
|
-
| `colors` | `string[]` | indigo / pink / cyan | One to three colors. Fewer are cycled, so a single color gives a clean monochrome loader. |
|
|
117
|
-
| `label` | `string \| null` | `"Loading"` | Screen-reader text. Pass `null` to mark the loader decorative. |
|
|
118
|
-
|
|
119
|
-
Every other `div` prop — `className`, `style`, `id`, `onClick`, `data-*` — passes straight through.
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## Which loader should I use?
|
|
129
|
+
## Choosing a loader
|
|
124
130
|
|
|
125
131
|
| situation | reach for | why |
|
|
126
132
|
|---|---|---|
|
|
@@ -138,49 +144,177 @@ Every other `div` prop — `className`, `style`, `id`, `onClick`, `data-*` — p
|
|
|
138
144
|
|
|
139
145
|
## Recipes
|
|
140
146
|
|
|
141
|
-
|
|
147
|
+
### A button that keeps its width while loading
|
|
142
148
|
|
|
143
149
|
```tsx
|
|
144
150
|
<button disabled={busy}>
|
|
145
|
-
{busy
|
|
146
|
-
|
|
147
|
-
|
|
151
|
+
{busy ? (
|
|
152
|
+
<Loader
|
|
153
|
+
variant="pulse-dots"
|
|
154
|
+
size={16}
|
|
155
|
+
colors={["currentColor"]}
|
|
156
|
+
label={null}
|
|
157
|
+
/>
|
|
158
|
+
) : (
|
|
159
|
+
"Save"
|
|
160
|
+
)}
|
|
148
161
|
</button>
|
|
149
162
|
```
|
|
150
163
|
|
|
151
|
-
`colors={["currentColor"]}` inherits the button's own text
|
|
152
|
-
readers announcing "Loading" twice when the button
|
|
164
|
+
`colors={["currentColor"]}` inherits the button's own text colour.
|
|
165
|
+
`label={null}` stops screen readers announcing "Loading" twice when the button
|
|
166
|
+
already conveys it.
|
|
153
167
|
|
|
154
|
-
|
|
168
|
+
### A skeleton shaped like the thing you're waiting for
|
|
155
169
|
|
|
156
170
|
```tsx
|
|
157
|
-
{isLoading ?
|
|
171
|
+
{isLoading ? (
|
|
172
|
+
<Loader
|
|
173
|
+
variant="sk-card"
|
|
174
|
+
size={64}
|
|
175
|
+
/>
|
|
176
|
+
) : (
|
|
177
|
+
<ArticleCard {...article} />
|
|
178
|
+
)}
|
|
158
179
|
```
|
|
159
180
|
|
|
160
|
-
|
|
181
|
+
### A full-page overlay
|
|
161
182
|
|
|
162
183
|
```tsx
|
|
163
|
-
<div
|
|
164
|
-
|
|
184
|
+
<div
|
|
185
|
+
style={{
|
|
186
|
+
position: "fixed",
|
|
187
|
+
inset: 0,
|
|
188
|
+
display: "grid",
|
|
189
|
+
placeItems: "center",
|
|
190
|
+
}}
|
|
191
|
+
>
|
|
192
|
+
<Loader
|
|
193
|
+
variant="aurora"
|
|
194
|
+
size={80}
|
|
195
|
+
label="Loading your dashboard"
|
|
196
|
+
/>
|
|
165
197
|
</div>
|
|
166
198
|
```
|
|
167
199
|
|
|
168
|
-
|
|
200
|
+
### Build your own picker
|
|
201
|
+
|
|
202
|
+
The manifest is exported, so you can map over it:
|
|
169
203
|
|
|
170
204
|
```tsx
|
|
171
205
|
import { VARIANTS, Loader } from "modern-loaders";
|
|
172
206
|
|
|
173
|
-
VARIANTS
|
|
174
|
-
|
|
207
|
+
VARIANTS
|
|
208
|
+
.filter((variant) => variant.group === "Skeletons")
|
|
209
|
+
.map((variant) => (
|
|
210
|
+
<Loader
|
|
211
|
+
key={variant.id}
|
|
212
|
+
variant={variant.id}
|
|
213
|
+
/>
|
|
214
|
+
));
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Customization
|
|
220
|
+
|
|
221
|
+
The `colors` prop covers most cases. For anything else, override the CSS custom
|
|
222
|
+
properties — they cascade, so one rule themes a whole subtree:
|
|
223
|
+
|
|
224
|
+
```css
|
|
225
|
+
.dashboard {
|
|
226
|
+
/* palette */
|
|
227
|
+
--c1: #6366f1;
|
|
228
|
+
--c2: #ec4899;
|
|
229
|
+
--c3: #22d3ee;
|
|
230
|
+
|
|
231
|
+
/* size and timing */
|
|
232
|
+
--size: 64px;
|
|
233
|
+
--speed: .9s;
|
|
234
|
+
|
|
235
|
+
/* rail behind progress bars */
|
|
236
|
+
--track: #1e1e2e;
|
|
237
|
+
|
|
238
|
+
/* shared gradient */
|
|
239
|
+
--grad: linear-gradient(
|
|
240
|
+
90deg,
|
|
241
|
+
var(--c1),
|
|
242
|
+
var(--c3)
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`--track` and `--grad` derive from `--c1`–`--c3` automatically; set them
|
|
248
|
+
directly for finer control.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## API
|
|
253
|
+
|
|
254
|
+
### Props
|
|
255
|
+
|
|
256
|
+
| prop | type | default | description |
|
|
257
|
+
|---|---|---|---|
|
|
258
|
+
| `variant` | `LoaderVariant` | `"aurora"` | Which loader to render — any of the 212 ids below. |
|
|
259
|
+
| `size` | `number \| string` | `48` | Overall size. A number means pixels; strings pass through (`"3rem"`). |
|
|
260
|
+
| `speed` | `number \| string` | `1` | Base duration. A number means seconds; lower is faster. |
|
|
261
|
+
| `colors` | `string[]` | indigo / pink / cyan | One to three colours. Fewer are cycled, so a single colour gives a clean monochrome loader. |
|
|
262
|
+
| `label` | `string \| null` | `"Loading"` | Screen-reader text. Pass `null` to mark the loader decorative. |
|
|
263
|
+
|
|
264
|
+
Every other `div` prop — `className`, `style`, `id`, `onClick`, `data-*` —
|
|
265
|
+
passes straight through.
|
|
266
|
+
|
|
267
|
+
### Exports
|
|
268
|
+
|
|
269
|
+
| export | what it is |
|
|
270
|
+
|---|---|
|
|
271
|
+
| `Loader` | The component. |
|
|
272
|
+
| `VARIANTS` | Manifest of all 212: `{ id, label, group, cells }`. |
|
|
273
|
+
| `LOADER_VARIANTS` | Just the 212 ids, in display order. |
|
|
274
|
+
| `GROUPS` | The 20 families: `{ name, description }`. |
|
|
275
|
+
|
|
276
|
+
`Loader` is the main export. The original ten also have named wrappers, kept for
|
|
277
|
+
backward compatibility with 1.0.x:
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
import {
|
|
281
|
+
Aurora, Orbit, Rings, Wave, Bars,
|
|
282
|
+
Blob, Cube, Spiral, Bar, Grid,
|
|
283
|
+
} from "modern-loaders";
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Everything else is reached with `<Loader variant="…" />`. Two hundred named
|
|
287
|
+
exports would bloat the API surface for no real gain, and `variant`
|
|
288
|
+
autocompletes just as well.
|
|
289
|
+
|
|
290
|
+
### TypeScript
|
|
291
|
+
|
|
292
|
+
Types ship with the package — no `@types` install:
|
|
293
|
+
|
|
294
|
+
```tsx
|
|
295
|
+
import type {
|
|
296
|
+
LoaderProps,
|
|
297
|
+
LoaderVariant,
|
|
298
|
+
LoaderGroup,
|
|
299
|
+
VariantMeta,
|
|
300
|
+
} from "modern-loaders";
|
|
301
|
+
|
|
302
|
+
// a union of all 212 ids; typos fail to compile
|
|
303
|
+
const variant: LoaderVariant = "aurora";
|
|
304
|
+
|
|
305
|
+
// wrap Loader without re-declaring its props
|
|
306
|
+
function Busy(props: LoaderProps) {
|
|
307
|
+
return <Loader {...props} />;
|
|
308
|
+
}
|
|
175
309
|
```
|
|
176
310
|
|
|
177
311
|
---
|
|
178
312
|
|
|
179
313
|
## All 212 variants
|
|
180
314
|
|
|
181
|
-
Every id maps to a `.ldr--<id>` CSS class. The tables below are the full
|
|
182
|
-
moving, use the [live gallery](https://modern-loaders.netlify.app/) — it renders
|
|
183
|
-
colours, and copies the JSX for you.
|
|
315
|
+
Every id maps to a `.ldr--<id>` CSS class. The tables below are the full
|
|
316
|
+
reference; to *see* them moving, use the [live gallery](https://modern-loaders.netlify.app/) — it renders
|
|
317
|
+
every variant with your own size, speed and colours, and copies the JSX for you.
|
|
184
318
|
|
|
185
319
|
<details>
|
|
186
320
|
<summary><b>Spinners</b> · 10 — Rings and arcs — the classic shape, modernised.</summary>
|
|
@@ -556,35 +690,11 @@ colours, and copies the JSX for you.
|
|
|
556
690
|
|
|
557
691
|
---
|
|
558
692
|
|
|
559
|
-
## Theming
|
|
560
|
-
|
|
561
|
-
The `colors` prop covers most cases. For anything else, override the custom properties — they
|
|
562
|
-
cascade, so one rule themes a whole subtree:
|
|
563
|
-
|
|
564
|
-
```css
|
|
565
|
-
.dashboard {
|
|
566
|
-
--c1: #6366f1; /* primary */
|
|
567
|
-
--c2: #ec4899; /* secondary */
|
|
568
|
-
--c3: #22d3ee; /* tertiary */
|
|
569
|
-
--size: 64px; /* box size */
|
|
570
|
-
--speed: .9s; /* base duration */
|
|
571
|
-
|
|
572
|
-
--track: #1e1e2e; /* rail behind progress bars */
|
|
573
|
-
--grad: linear-gradient(90deg, var(--c1), var(--c3)); /* shared gradient */
|
|
574
|
-
}
|
|
575
|
-
```
|
|
576
|
-
|
|
577
|
-
`--track` and `--grad` derive from `--c1`–`--c3` automatically; set them directly for finer control.
|
|
578
|
-
|
|
579
|
-
---
|
|
580
|
-
|
|
581
693
|
## Accessibility
|
|
582
694
|
|
|
583
695
|
- Each loader renders as `role="status"` with `aria-label`, so assistive tech announces it once.
|
|
584
|
-
- A decorative loader — one sitting beside visible "Loading…" text — should take `label={null}`,
|
|
585
|
-
|
|
586
|
-
- Under `prefers-reduced-motion: reduce`, every animation slows to a single calm 4s linear cycle
|
|
587
|
-
rather than stopping. A frozen loader reads as a crashed app, which is worse than gentle motion.
|
|
696
|
+
- A decorative loader — one sitting beside visible "Loading…" text — should take `label={null}`, which switches it to `aria-hidden` and prevents a double announcement.
|
|
697
|
+
- Under `prefers-reduced-motion: reduce`, every animation slows to a single calm 4s linear cycle rather than stopping. A frozen loader reads as a crashed app, which is worse than gentle motion.
|
|
588
698
|
|
|
589
699
|
---
|
|
590
700
|
|
|
@@ -595,57 +705,57 @@ cascade, so one rule themes a whole subtree:
|
|
|
595
705
|
| JS | ~18 kB | **~4 kB** |
|
|
596
706
|
| CSS (all 212 variants) | ~166 kB | **~24 kB** |
|
|
597
707
|
|
|
598
|
-
One caveat, stated plainly: **the CSS is not tree-shakeable.** Class-based
|
|
599
|
-
dead-code eliminated, so importing a single variant still ships
|
|
600
|
-
gzipped that is a fair trade for most apps, but
|
|
601
|
-
|
|
602
|
-
|
|
708
|
+
One caveat, stated plainly: **the CSS is not tree-shakeable.** Class-based
|
|
709
|
+
styles cannot be dead-code eliminated, so importing a single variant still ships
|
|
710
|
+
the sheet for all 212. At ~24 kB gzipped that is a fair trade for most apps, but
|
|
711
|
+
it is real weight. If you need only a handful and every kilobyte counts, copy
|
|
712
|
+
the specific `.ldr--*` blocks out of [`src/styles/`](./src/styles) into your own
|
|
713
|
+
CSS and skip the package — each block is self-contained apart from the shared
|
|
603
714
|
keyframes in [`00-base.css`](./src/styles/00-base.css).
|
|
604
715
|
|
|
605
716
|
---
|
|
606
717
|
|
|
607
|
-
## Named exports
|
|
608
|
-
|
|
609
|
-
`Loader` is the main export. The original ten also have wrappers, kept for backward compatibility
|
|
610
|
-
with 1.0.x:
|
|
611
|
-
|
|
612
|
-
```tsx
|
|
613
|
-
import { Aurora, Orbit, Rings, Wave, Bars, Blob, Cube, Spiral, Bar, Grid } from "modern-loaders";
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
Everything else is reached with `<Loader variant="…" />`. Two hundred named exports would bloat
|
|
617
|
-
the API surface for no real gain, and `variant` autocompletes just as well.
|
|
618
|
-
|
|
619
|
-
---
|
|
620
|
-
|
|
621
718
|
## Browser support
|
|
622
719
|
|
|
623
|
-
Chrome 111+ · Safari 16.4+ · Firefox 113+ — the floor is set by `color-mix()`,
|
|
624
|
-
`aspect-ratio`, `clip-path`, and the individual `translate` /
|
|
625
|
-
browsers degrade to solid shapes rather
|
|
720
|
+
Chrome 111+ · Safari 16.4+ · Firefox 113+ — the floor is set by `color-mix()`,
|
|
721
|
+
alongside `mask`, `aspect-ratio`, `clip-path`, and the individual `translate` /
|
|
722
|
+
`rotate` / `scale` properties. Older browsers degrade to solid shapes rather
|
|
723
|
+
than breaking.
|
|
626
724
|
|
|
627
|
-
Five variants — `neon-arc`, `pie`, `progress-ring`, `gradient-border`,
|
|
628
|
-
registered custom property via `@property`
|
|
629
|
-
|
|
725
|
+
Five variants — `neon-arc`, `pie`, `progress-ring`, `gradient-border`,
|
|
726
|
+
`color-cycle` — animate a registered custom property via `@property`
|
|
727
|
+
(Firefox 128+). Every use passes a fallback, so below that they render a
|
|
728
|
+
sensible static frame instead of disappearing.
|
|
630
729
|
|
|
631
730
|
---
|
|
632
731
|
|
|
633
|
-
##
|
|
732
|
+
## Contributing
|
|
634
733
|
|
|
635
734
|
```bash
|
|
636
|
-
|
|
637
|
-
npm run
|
|
638
|
-
|
|
735
|
+
# Live showcase with search and filters
|
|
736
|
+
npm run dev
|
|
737
|
+
|
|
738
|
+
# Typecheck, then build dist/
|
|
739
|
+
npm run build
|
|
740
|
+
|
|
741
|
+
# Build the static showcase
|
|
742
|
+
npm run build:demo
|
|
639
743
|
```
|
|
640
744
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
745
|
+
`build` emits ESM + CJS + `.d.ts` + CSS into `dist/`. `build:demo` writes the
|
|
746
|
+
static showcase to `dist-demo/`, which is what gets deployed to
|
|
747
|
+
[modern-loaders.netlify.app](https://modern-loaders.netlify.app/).
|
|
748
|
+
|
|
749
|
+
Adding a variant takes two edits: a `.ldr--<id>` block in `src/styles/`, and a
|
|
750
|
+
row in [`src/variants.ts`](./src/variants.ts). The component, the types, the
|
|
751
|
+
README catalogue and the showcase all read from that one manifest — `cells` is
|
|
752
|
+
how many `<span>` children the CSS expects.
|
|
644
753
|
|
|
645
754
|
Two rules keep the motion composable inside a variant: put a whole radial chain
|
|
646
|
-
(`rotate(…) translateY(…)`) in a single `transform` so the offset happens in the
|
|
647
|
-
and reach for the standalone `translate` / `rotate` / `scale`
|
|
648
|
-
animates `transform` — they compose instead
|
|
755
|
+
(`rotate(…) translateY(…)`) in a single `transform` so the offset happens in the
|
|
756
|
+
rotated frame, and reach for the standalone `translate` / `rotate` / `scale`
|
|
757
|
+
properties when an element already animates `transform` — they compose instead
|
|
758
|
+
of overwriting it.
|
|
649
759
|
|
|
650
760
|
---
|
|
651
761
|
|
package/package.json
CHANGED