shimmer-trace 1.1.1 → 1.1.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 +112 -110
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
[](https://www.typescriptlang.org)
|
|
11
11
|
[](./LICENSE)
|
|
12
12
|
|
|
13
|
+
**[🚀 Live Demo](https://jeetvora331.github.io/shimmer-trace/)**
|
|
14
|
+
|
|
13
15
|
<p align="center">
|
|
14
16
|
<img src="https://raw.githubusercontent.com/jeetvora331/shimmer-trace/main/assets/demo.gif" alt="shimmer-trace demo" width="720" />
|
|
15
17
|
</p>
|
|
@@ -73,13 +75,13 @@ pnpm add shimmer-trace
|
|
|
73
75
|
import { Shimmer } from "shimmer-trace";
|
|
74
76
|
|
|
75
77
|
function ProfilePage() {
|
|
76
|
-
|
|
78
|
+
const [loading, setLoading] = useState(true);
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
return (
|
|
81
|
+
<Shimmer loading={loading}>
|
|
82
|
+
<UserCard />
|
|
83
|
+
</Shimmer>
|
|
84
|
+
);
|
|
83
85
|
}
|
|
84
86
|
```
|
|
85
87
|
|
|
@@ -95,18 +97,18 @@ The core component. Wrap anything with it.
|
|
|
95
97
|
|
|
96
98
|
```tsx
|
|
97
99
|
<Shimmer
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
100
|
+
loading={boolean} // required — controls shimmer on/off
|
|
101
|
+
animation="wave" // 'wave' | 'pulse' | 'shine' | 'glow' | 'gradient'
|
|
102
|
+
baseColor="#e0e0e0" // skeleton base color
|
|
103
|
+
highlightColor="#f5f5f5" // shimmer highlight color
|
|
104
|
+
speed={1.5} // animation duration in seconds
|
|
105
|
+
borderRadius="4px" // override auto-detected border-radius
|
|
106
|
+
dummyLength={10} // list mode: number of skeleton items
|
|
107
|
+
stopPropagation={false} // force this Shimmer to be a master
|
|
108
|
+
className="my-class" // applied to the container div
|
|
109
|
+
style={{ display: "flex" }} // merged into container styles
|
|
108
110
|
>
|
|
109
|
-
|
|
111
|
+
{children}
|
|
110
112
|
</Shimmer>
|
|
111
113
|
```
|
|
112
114
|
|
|
@@ -136,20 +138,20 @@ Wrap any component — shimmer-trace handles the rest.
|
|
|
136
138
|
import { Shimmer } from "shimmer-trace";
|
|
137
139
|
|
|
138
140
|
function App() {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
141
|
+
const [loading, setLoading] = useState(true);
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<Shimmer loading={loading}>
|
|
145
|
+
<div className="profile-card">
|
|
146
|
+
<img src={user.avatar} alt="Avatar" />
|
|
147
|
+
<div>
|
|
148
|
+
<h3>{user.name}</h3>
|
|
149
|
+
<span>{user.role}</span>
|
|
150
|
+
<p>{user.bio}</p>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</Shimmer>
|
|
154
|
+
);
|
|
153
155
|
}
|
|
154
156
|
```
|
|
155
157
|
|
|
@@ -159,15 +161,15 @@ Works out of the box with inputs, labels, and buttons.
|
|
|
159
161
|
|
|
160
162
|
```tsx
|
|
161
163
|
<Shimmer loading={loading}>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
<form>
|
|
165
|
+
<label>Email</label>
|
|
166
|
+
<input type="email" placeholder="you@example.com" />
|
|
165
167
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
<label>Message</label>
|
|
169
|
+
<textarea placeholder="Your message..." />
|
|
168
170
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
+
<button type="submit">Send</button>
|
|
172
|
+
</form>
|
|
171
173
|
</Shimmer>
|
|
172
174
|
```
|
|
173
175
|
|
|
@@ -177,16 +179,16 @@ Loading a list from an API? `dummyLength` clones your list item template to show
|
|
|
177
179
|
|
|
178
180
|
```tsx
|
|
179
181
|
<Shimmer loading={loading} dummyLength={10}>
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
182
|
+
{posts.map((post) => (
|
|
183
|
+
<div className="post-row" key={post.id}>
|
|
184
|
+
<img src={post.thumbnail} alt="" />
|
|
185
|
+
<div>
|
|
186
|
+
<h4>{post.title}</h4>
|
|
187
|
+
<span>{post.author}</span>
|
|
188
|
+
</div>
|
|
189
|
+
<span className="badge">{post.category}</span>
|
|
190
|
+
</div>
|
|
191
|
+
))}
|
|
190
192
|
</Shimmer>
|
|
191
193
|
```
|
|
192
194
|
|
|
@@ -202,9 +204,9 @@ One `<Shimmer>` wraps multiple cards. One overlay. One perfectly synchronized wa
|
|
|
202
204
|
|
|
203
205
|
```tsx
|
|
204
206
|
<Shimmer loading={loading} style={{ display: "flex", gap: "1rem" }}>
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
207
|
+
<StatCard value="4,821" label="Total Users" />
|
|
208
|
+
<StatCard value="98.4%" label="Uptime" />
|
|
209
|
+
<StatCard value="142ms" label="Avg Latency" />
|
|
208
210
|
</Shimmer>
|
|
209
211
|
```
|
|
210
212
|
|
|
@@ -214,7 +216,7 @@ No separate shimmers per card. One master overlay covers them all — the wave s
|
|
|
214
216
|
|
|
215
217
|
```tsx
|
|
216
218
|
<Shimmer loading={loading} baseColor="#1e1e3a" highlightColor="#2d2d52">
|
|
217
|
-
|
|
219
|
+
<DashboardWidget />
|
|
218
220
|
</Shimmer>
|
|
219
221
|
```
|
|
220
222
|
|
|
@@ -229,19 +231,19 @@ import { createShimmer } from "shimmer-trace";
|
|
|
229
231
|
|
|
230
232
|
// Create a pre-configured Shimmer component
|
|
231
233
|
const DarkShimmer = createShimmer({
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
baseColor: "#1e1e3a",
|
|
235
|
+
highlightColor: "#2d2d52",
|
|
236
|
+
animation: "wave",
|
|
237
|
+
speed: 1.2,
|
|
236
238
|
});
|
|
237
239
|
|
|
238
240
|
// Use it like a regular component — just add `loading`
|
|
239
241
|
function App() {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
242
|
+
return (
|
|
243
|
+
<DarkShimmer loading={loading}>
|
|
244
|
+
<UserCard />
|
|
245
|
+
</DarkShimmer>
|
|
246
|
+
);
|
|
245
247
|
}
|
|
246
248
|
```
|
|
247
249
|
|
|
@@ -263,26 +265,26 @@ Pass the same component without data as `template`. Zero shimmer-awareness neede
|
|
|
263
265
|
|
|
264
266
|
```tsx
|
|
265
267
|
function UserCard({ user }) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
268
|
+
return (
|
|
269
|
+
<div className="card">
|
|
270
|
+
<img src={user.avatar} alt="" />
|
|
271
|
+
<h3>{user.name}</h3>
|
|
272
|
+
<p>{user.bio}</p>
|
|
273
|
+
</div>
|
|
274
|
+
);
|
|
273
275
|
}
|
|
274
276
|
|
|
275
277
|
// Same shape, no data — used as skeleton template
|
|
276
278
|
const UserCardSkeleton = () => (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
279
|
+
<div className="card">
|
|
280
|
+
<img src="" alt="" />
|
|
281
|
+
<h3> </h3>
|
|
282
|
+
<p> </p>
|
|
283
|
+
</div>
|
|
282
284
|
);
|
|
283
285
|
|
|
284
286
|
<ShimmerSuspense template={<UserCardSkeleton />}>
|
|
285
|
-
|
|
287
|
+
<UserCard resource={resource} />
|
|
286
288
|
</ShimmerSuspense>;
|
|
287
289
|
```
|
|
288
290
|
|
|
@@ -294,22 +296,22 @@ No template needed. The component detects shimmer mode and renders an empty shap
|
|
|
294
296
|
import { useIsShimmering } from "shimmer-trace";
|
|
295
297
|
|
|
296
298
|
function UserCard({ resource }) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
299
|
+
const isShimmering = useIsShimmering();
|
|
300
|
+
|
|
301
|
+
// Skip data fetching in shimmer mode (avoids nested Suspense throw)
|
|
302
|
+
const user = isShimmering ? null : resource.read();
|
|
303
|
+
|
|
304
|
+
return (
|
|
305
|
+
<div className="card">
|
|
306
|
+
<img src={user?.avatar ?? ""} alt="" />
|
|
307
|
+
<h3>{user?.name ?? " "}</h3>
|
|
308
|
+
<p>{user?.bio ?? " "}</p>
|
|
309
|
+
</div>
|
|
310
|
+
);
|
|
309
311
|
}
|
|
310
312
|
|
|
311
313
|
<ShimmerSuspense>
|
|
312
|
-
|
|
314
|
+
<UserCard resource={resource} />
|
|
313
315
|
</ShimmerSuspense>;
|
|
314
316
|
```
|
|
315
317
|
|
|
@@ -317,12 +319,12 @@ function UserCard({ resource }) {
|
|
|
317
319
|
|
|
318
320
|
```tsx
|
|
319
321
|
<ShimmerSuspense
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
322
|
+
template={<UserCardSkeleton />}
|
|
323
|
+
animation="pulse"
|
|
324
|
+
baseColor="#1e1e3a"
|
|
325
|
+
highlightColor="#2d2d52"
|
|
324
326
|
>
|
|
325
|
-
|
|
327
|
+
<UserCard resource={resource} />
|
|
326
328
|
</ShimmerSuspense>
|
|
327
329
|
```
|
|
328
330
|
|
|
@@ -334,13 +336,13 @@ function UserCard({ resource }) {
|
|
|
334
336
|
|
|
335
337
|
```tsx
|
|
336
338
|
<Shimmer loading={loading}>
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
339
|
+
<PageHeader>
|
|
340
|
+
{/* This nested Shimmer contributes its rects to the parent overlay */}
|
|
341
|
+
<Shimmer loading={loading}>
|
|
342
|
+
<NavigationMenu />
|
|
343
|
+
</Shimmer>
|
|
344
|
+
</PageHeader>
|
|
345
|
+
<MainContent />
|
|
344
346
|
</Shimmer>
|
|
345
347
|
```
|
|
346
348
|
|
|
@@ -348,12 +350,12 @@ Use `stopPropagation` to force an independent shimmer:
|
|
|
348
350
|
|
|
349
351
|
```tsx
|
|
350
352
|
<Shimmer loading={outerLoading}>
|
|
351
|
-
|
|
353
|
+
<Sidebar />
|
|
352
354
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
355
|
+
{/* Independent shimmer — own overlay, own animation */}
|
|
356
|
+
<Shimmer loading={innerLoading} stopPropagation>
|
|
357
|
+
<Feed />
|
|
358
|
+
</Shimmer>
|
|
357
359
|
</Shimmer>
|
|
358
360
|
```
|
|
359
361
|
|
|
@@ -395,11 +397,11 @@ Full types exported:
|
|
|
395
397
|
|
|
396
398
|
```ts
|
|
397
399
|
import type {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
400
|
+
ShimmerProps, // Props for <Shimmer>
|
|
401
|
+
ShimmerConfig, // Config options (colors, speed, animation)
|
|
402
|
+
ShimmerRect, // Measured element rectangle
|
|
403
|
+
AnimationType, // 'wave' | 'pulse' | 'breathe'
|
|
404
|
+
ShimmerSuspenseProps,
|
|
403
405
|
} from "shimmer-trace";
|
|
404
406
|
```
|
|
405
407
|
|
|
@@ -421,4 +423,4 @@ import type {
|
|
|
421
423
|
|
|
422
424
|
## License
|
|
423
425
|
|
|
424
|
-
|
|
426
|
+
MIT — [Jeet Vora](https://github.com/jeetvora331)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shimmer-trace",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "High-performance React skeleton loaders that automatically trace your UI dimensions. Synchronized animations, zero CLS, and one-line implementation.",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"bugs": {
|
|
48
48
|
"url": "https://github.com/jeetvora331/shimmer-trace/issues"
|
|
49
49
|
},
|
|
50
|
-
"homepage": "https://github.
|
|
50
|
+
"homepage": "https://jeetvora331.github.io/shimmer-trace/",
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"react": ">=18.0.0",
|
|
53
53
|
"react-dom": ">=18.0.0"
|
|
@@ -59,6 +59,6 @@
|
|
|
59
59
|
"react-dom": "^19.1.0",
|
|
60
60
|
"esbuild": "^0.25.0",
|
|
61
61
|
"tsup": "^8.5.0",
|
|
62
|
-
"typescript": "^
|
|
62
|
+
"typescript": "^6.0.0"
|
|
63
63
|
}
|
|
64
64
|
}
|