@umituz/react-native-design-system 2.6.93 → 2.6.95
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/package.json +1 -1
- package/src/atoms/AtomicAvatar.README.md +284 -397
- package/src/atoms/AtomicBadge.README.md +123 -358
- package/src/atoms/AtomicCard.README.md +358 -247
- package/src/atoms/AtomicDatePicker.README.md +127 -332
- package/src/atoms/AtomicFab.README.md +194 -352
- package/src/atoms/AtomicIcon.README.md +241 -274
- package/src/atoms/AtomicProgress.README.md +100 -338
- package/src/atoms/AtomicSpinner.README.md +304 -337
- package/src/atoms/AtomicText.README.md +153 -389
- package/src/atoms/AtomicTextArea.README.md +267 -268
- package/src/atoms/EmptyState.README.md +247 -292
- package/src/atoms/GlassView/README.md +313 -444
- package/src/atoms/button/README.md +186 -297
- package/src/atoms/button/STRATEGY.md +252 -0
- package/src/atoms/chip/README.md +242 -290
- package/src/atoms/input/README.md +296 -290
- package/src/atoms/picker/README.md +278 -309
- package/src/atoms/skeleton/AtomicSkeleton.README.md +394 -252
- package/src/exports/theme.ts +0 -1
- package/src/molecules/BaseModal/README.md +356 -0
- package/src/molecules/BaseModal.README.md +324 -200
- package/src/molecules/ConfirmationModal.README.md +349 -302
- package/src/molecules/Divider/README.md +293 -376
- package/src/molecules/FormField.README.md +321 -534
- package/src/molecules/GlowingCard/GlowingCard.tsx +1 -1
- package/src/molecules/GlowingCard/README.md +230 -372
- package/src/molecules/IconContainer.tsx +1 -1
- package/src/molecules/List/README.md +281 -488
- package/src/molecules/ListItem.README.md +320 -315
- package/src/molecules/SearchBar/README.md +332 -430
- package/src/molecules/StepHeader/README.md +311 -411
- package/src/molecules/StepProgress/README.md +281 -448
- package/src/molecules/alerts/README.md +272 -355
- package/src/molecules/avatar/README.md +295 -356
- package/src/molecules/bottom-sheet/README.md +303 -340
- package/src/molecules/calendar/README.md +301 -265
- package/src/molecules/countdown/README.md +347 -456
- package/src/molecules/emoji/README.md +281 -514
- package/src/molecules/listitem/README.md +307 -399
- package/src/molecules/media-card/MediaCard.tsx +31 -34
- package/src/molecules/media-card/README.md +217 -319
- package/src/molecules/navigation/README.md +263 -284
- package/src/molecules/splash/README.md +76 -92
- package/src/molecules/swipe-actions/README.md +376 -588
|
@@ -1,339 +1,481 @@
|
|
|
1
1
|
# AtomicSkeleton
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A placeholder component shown while content is loading. Displays different patterns including lists, cards, avatars, and text.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Import & Usage
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
```typescript
|
|
8
|
+
import { AtomicSkeleton } from 'react-native-design-system/src/atoms/skeleton/AtomicSkeleton';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Location:** `src/atoms/skeleton/AtomicSkeleton.tsx`
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Basic Usage
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
|
-
|
|
16
|
+
<AtomicSkeleton pattern="list" count={3} />
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## Strategy
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
import React from 'react';
|
|
23
|
-
import { View } from 'react-native';
|
|
24
|
-
import { AtomicSkeleton } from 'react-native-design-system';
|
|
25
|
-
|
|
26
|
-
export const BasicExample = () => {
|
|
27
|
-
return (
|
|
28
|
-
<View style={{ padding: 16 }}>
|
|
29
|
-
<AtomicSkeleton pattern="list" count={3} />
|
|
30
|
-
</View>
|
|
31
|
-
);
|
|
32
|
-
};
|
|
33
|
-
```
|
|
21
|
+
**Purpose**: Improve perceived performance by showing placeholder content while actual data loads.
|
|
34
22
|
|
|
35
|
-
|
|
23
|
+
**When to Use**:
|
|
24
|
+
- During initial page load
|
|
25
|
+
- For list items loading (feed, search results)
|
|
26
|
+
- For card-based content loading (products, profiles)
|
|
27
|
+
- For image loading states
|
|
28
|
+
- When content structure is predictable
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
**When NOT to Use**:
|
|
31
|
+
- For quick operations (< 500ms) - use spinner instead
|
|
32
|
+
- When content structure is unknown/variable
|
|
33
|
+
- For error states (use EmptyState instead)
|
|
34
|
+
- For static content that doesn't load
|
|
35
|
+
- As a decorative element
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
<AtomicSkeleton pattern="list" count={5} />
|
|
43
|
-
```
|
|
37
|
+
## Rules
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
### Required
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
1. **MUST** match skeleton pattern to actual content structure
|
|
42
|
+
2. **ALWAYS** remove skeleton when data arrives
|
|
43
|
+
3. **SHOULD** use appropriate count for expected content
|
|
44
|
+
4. **MUST** be hidden from screen readers (loading placeholder only)
|
|
45
|
+
5. **ALWAYS** use semantic patterns (list, card, avatar) when applicable
|
|
46
|
+
6. **SHOULD** keep skeleton duration reasonable (< 3 seconds preferred)
|
|
47
|
+
7. **MUST** not skeleton for very quick loads (< 300ms)
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
<AtomicSkeleton pattern="card" count={3} />
|
|
53
|
-
```
|
|
49
|
+
### Pattern Selection
|
|
54
50
|
|
|
55
|
-
|
|
51
|
+
1. **List**: For list items, feed items, search results
|
|
52
|
+
2. **Card**: For product cards, info cards
|
|
53
|
+
3. **Avatar**: For user avatars, profile pictures
|
|
54
|
+
4. **Text**: For paragraphs, descriptions
|
|
55
|
+
5. **Custom**: For unique layouts (define shapes)
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
<AtomicSkeleton pattern="avatar" count={5} />
|
|
59
|
-
```
|
|
57
|
+
### Count Guidelines
|
|
60
58
|
|
|
61
|
-
|
|
59
|
+
1. **Lists**: Use 3-5 skeletons for initial load
|
|
60
|
+
2. **Cards**: Use 2-6 skeletons depending on grid
|
|
61
|
+
3. **Avatars**: Use 5-10 for user lists
|
|
62
|
+
4. **Text**: Use 1-3 lines per section
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
### Custom Skeletons
|
|
65
|
+
|
|
66
|
+
1. **MUST** match actual content dimensions
|
|
67
|
+
2. **SHOULD** follow content spacing
|
|
68
|
+
3. **MUST** use appropriate borderRadius for shapes
|
|
69
|
+
4. **SHOULD** keep total elements reasonable (< 10 per skeleton)
|
|
66
70
|
|
|
67
|
-
##
|
|
71
|
+
## Forbidden
|
|
72
|
+
|
|
73
|
+
❌ **NEVER** do these:
|
|
68
74
|
|
|
69
75
|
```tsx
|
|
76
|
+
// ❌ Skeleton never removed
|
|
77
|
+
{loading && <AtomicSkeleton />} {/* ❌ Always shows */}
|
|
78
|
+
{/* Even when data arrives */}
|
|
79
|
+
|
|
80
|
+
// ❌ Wrong pattern for content
|
|
81
|
+
<AtomicSkeleton pattern="avatar" /> {/* ❌ Content is text */}
|
|
82
|
+
// Actual content: <AtomicText>Long description</AtomicText>
|
|
83
|
+
|
|
84
|
+
// ❌ Too many skeletons
|
|
85
|
+
<AtomicSkeleton pattern="list" count={20} /> {/* ❌ Too many */}
|
|
86
|
+
|
|
87
|
+
// ❌ Skeleton for quick load
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
setLoading(true);
|
|
90
|
+
fetchData(); {/* ❌ Takes 200ms, shouldn't skeleton */}
|
|
91
|
+
setLoading(false);
|
|
92
|
+
}, []);
|
|
93
|
+
|
|
94
|
+
// ❌ Not matching content structure
|
|
95
|
+
<AtomicSkeleton pattern="list" />
|
|
96
|
+
// Actual content:
|
|
97
|
+
<View style={{ flexDirection: 'row' }}>
|
|
98
|
+
<Image />
|
|
99
|
+
<View>
|
|
100
|
+
<Text>Title</Text>
|
|
101
|
+
<Text>Description</Text>
|
|
102
|
+
</View>
|
|
103
|
+
</View>
|
|
104
|
+
|
|
105
|
+
// ❌ Custom skeleton wrong dimensions
|
|
106
|
+
<AtomicSkeleton
|
|
107
|
+
pattern="custom"
|
|
108
|
+
custom={[{ width: 100, height: 100 }]} {/* ❌ Too large */}
|
|
109
|
+
/>
|
|
110
|
+
// Actual: <Image style={{ width: 50, height: 50 }} />
|
|
111
|
+
|
|
112
|
+
// ❌ Complex custom skeleton
|
|
70
113
|
<AtomicSkeleton
|
|
71
114
|
pattern="custom"
|
|
72
115
|
custom={[
|
|
73
|
-
|
|
74
|
-
{ width: '
|
|
75
|
-
{ width: '
|
|
116
|
+
/* ❌ 20+ elements, too complex */
|
|
117
|
+
{ width: '100%', height: 200 },
|
|
118
|
+
{ width: '80%', height: 20 },
|
|
119
|
+
// ... 18 more
|
|
76
120
|
]}
|
|
77
121
|
/>
|
|
78
122
|
```
|
|
79
123
|
|
|
80
|
-
##
|
|
124
|
+
## Best Practices
|
|
81
125
|
|
|
82
|
-
###
|
|
126
|
+
### Pattern Selection
|
|
83
127
|
|
|
128
|
+
✅ **DO**:
|
|
84
129
|
```tsx
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
130
|
+
// ✅ Match pattern to content
|
|
131
|
+
{loading ? (
|
|
132
|
+
<AtomicSkeleton pattern="list" count={3} />
|
|
133
|
+
) : (
|
|
134
|
+
<FlatList
|
|
135
|
+
data={items}
|
|
136
|
+
renderItem={({ item }) => <ListItem item={item} />}
|
|
137
|
+
/>
|
|
138
|
+
)}
|
|
139
|
+
|
|
140
|
+
// ✅ Card pattern for cards
|
|
141
|
+
{loading ? (
|
|
142
|
+
<View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
|
|
143
|
+
<AtomicSkeleton pattern="card" count={6} />
|
|
144
|
+
</View>
|
|
145
|
+
) : (
|
|
146
|
+
<ProductGrid products={products} />
|
|
147
|
+
)}
|
|
92
148
|
```
|
|
93
149
|
|
|
94
|
-
|
|
95
|
-
|
|
150
|
+
❌ **DON'T**:
|
|
96
151
|
```tsx
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
152
|
+
// ❌ Wrong pattern
|
|
153
|
+
{loading ? (
|
|
154
|
+
<AtomicSkeleton pattern="avatar" /> {/* Wrong! */}
|
|
155
|
+
) : (
|
|
156
|
+
<FlatList data={items} renderItem={({ item }) => <Text>{item.title}</Text>} />
|
|
157
|
+
)}
|
|
158
|
+
|
|
159
|
+
// ❌ Generic pattern when specific exists
|
|
160
|
+
<AtomicSkeleton
|
|
161
|
+
pattern="custom"
|
|
162
|
+
custom={[{ width: '100%', height: 60 }]} {/* Should use "list" */}
|
|
163
|
+
/>
|
|
106
164
|
```
|
|
107
165
|
|
|
108
|
-
###
|
|
166
|
+
### Appropriate Count
|
|
109
167
|
|
|
168
|
+
✅ **DO**:
|
|
110
169
|
```tsx
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
170
|
+
// ✅ Reasonable count
|
|
171
|
+
<AtomicSkeleton pattern="list" count={3} />
|
|
172
|
+
<AtomicSkeleton pattern="card" count={4} />
|
|
173
|
+
<AtomicSkeleton pattern="avatar" count={8} />
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
❌ **DON'T**:
|
|
177
|
+
```tsx
|
|
178
|
+
// ❌ Too many skeletons
|
|
179
|
+
<AtomicSkeleton pattern="list" count={15} />
|
|
180
|
+
<AtomicSkeleton pattern="card" count={12} />
|
|
181
|
+
|
|
182
|
+
// ❌ Too few skeletons
|
|
183
|
+
<AtomicSkeleton pattern="list" count={1} /> {/* Shows too little */}
|
|
125
184
|
```
|
|
126
185
|
|
|
127
|
-
###
|
|
186
|
+
### Removing Skeleton
|
|
128
187
|
|
|
188
|
+
✅ **DO**:
|
|
129
189
|
```tsx
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
190
|
+
// ✅ Proper loading state
|
|
191
|
+
const [loading, setLoading] = useState(true);
|
|
192
|
+
const [data, setData] = useState([]);
|
|
193
|
+
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
const loadData = async () => {
|
|
196
|
+
setLoading(true);
|
|
197
|
+
try {
|
|
198
|
+
const result = await fetchData();
|
|
199
|
+
setData(result);
|
|
200
|
+
} finally {
|
|
201
|
+
setLoading(false); // ✅ Always completes
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
loadData();
|
|
205
|
+
}, []);
|
|
206
|
+
|
|
207
|
+
{loading ? (
|
|
208
|
+
<AtomicSkeleton pattern="list" count={3} />
|
|
209
|
+
) : (
|
|
210
|
+
<DataList data={data} />
|
|
211
|
+
)}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
❌ **DON'T**:
|
|
215
|
+
```tsx
|
|
216
|
+
// ❌ Skeleton never removed
|
|
217
|
+
const [loading, setLoading] = useState(false);
|
|
218
|
+
|
|
219
|
+
{loading && <AtomicSkeleton />} {/* Never shows actual content */}
|
|
220
|
+
|
|
221
|
+
// ❌ Skeleton shows with data
|
|
222
|
+
<View>
|
|
223
|
+
{loading && <AtomicSkeleton />}
|
|
224
|
+
<DataList data={data} /> {/* Shows together! */}
|
|
225
|
+
</View>
|
|
147
226
|
```
|
|
148
227
|
|
|
149
|
-
###
|
|
228
|
+
### Custom Skeletons
|
|
150
229
|
|
|
230
|
+
✅ **DO**:
|
|
151
231
|
```tsx
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
<View style={{ width: '100%', height: 16, borderRadius: 4, marginBottom: 8, backgroundColor: '#e0e0e0' }} />
|
|
166
|
-
<View style={{ width: '80%', height: 16, borderRadius: 4, backgroundColor: '#f0f0f0' }} />
|
|
167
|
-
</View>
|
|
168
|
-
))}
|
|
169
|
-
</View>
|
|
170
|
-
);
|
|
171
|
-
};
|
|
232
|
+
// ✅ Match content structure
|
|
233
|
+
const skeletonCustom = [
|
|
234
|
+
{ width: '100%', height: 200, borderRadius: 12 }, // Image
|
|
235
|
+
{ width: '80%', height: 24, borderRadius: 4, marginBottom: 12 }, // Title
|
|
236
|
+
{ width: '100%', height: 16, borderRadius: 4, marginBottom: 8 }, // Line 1
|
|
237
|
+
{ width: '60%', height: 16, borderRadius: 4 }, // Line 2
|
|
238
|
+
];
|
|
239
|
+
|
|
240
|
+
{loading ? (
|
|
241
|
+
<AtomicSkeleton pattern="custom" custom={skeletonCustom} />
|
|
242
|
+
) : (
|
|
243
|
+
<ProductDetail product={product} />
|
|
244
|
+
)}
|
|
172
245
|
```
|
|
173
246
|
|
|
174
|
-
|
|
247
|
+
❌ **DON'T**:
|
|
248
|
+
```tsx
|
|
249
|
+
// ❌ Wrong dimensions
|
|
250
|
+
<AtomicSkeleton
|
|
251
|
+
pattern="custom"
|
|
252
|
+
custom={[{ width: 50, height: 50 }]} {/* Way too small */}
|
|
253
|
+
/>
|
|
175
254
|
|
|
255
|
+
// ❌ Too complex
|
|
256
|
+
<AtomicSkeleton
|
|
257
|
+
pattern="custom"
|
|
258
|
+
custom={Array.from({ length: 20 }).map(() => ({ /* ... */ }))} {/* Too many */}
|
|
259
|
+
/>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Duration Considerations
|
|
263
|
+
|
|
264
|
+
✅ **DO**:
|
|
176
265
|
```tsx
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
);
|
|
201
|
-
};
|
|
266
|
+
// ✅ Show skeleton only if loading takes time
|
|
267
|
+
const [showSkeleton, setShowSkeleton] = useState(false);
|
|
268
|
+
const [loading, setLoading] = useState(true);
|
|
269
|
+
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
const timer = setTimeout(() => setShowSkeleton(true), 300);
|
|
272
|
+
// Only show skeleton if loading takes > 300ms
|
|
273
|
+
|
|
274
|
+
const loadData = async () => {
|
|
275
|
+
const result = await fetchData();
|
|
276
|
+
setLoading(false);
|
|
277
|
+
setShowSkeleton(false);
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
loadData();
|
|
281
|
+
return () => clearTimeout(timer);
|
|
282
|
+
}, []);
|
|
283
|
+
|
|
284
|
+
{showSkeleton && loading ? (
|
|
285
|
+
<AtomicSkeleton pattern="list" count={3} />
|
|
286
|
+
) : loading ? null : (
|
|
287
|
+
<DataList data={data} />
|
|
288
|
+
)}
|
|
202
289
|
```
|
|
203
290
|
|
|
204
|
-
|
|
291
|
+
❌ **DON'T**:
|
|
292
|
+
```tsx
|
|
293
|
+
// ❌ Skeleton flashes for quick loads
|
|
294
|
+
{loading && <AtomicSkeleton />} {/* Flashes for 200ms loads */}
|
|
295
|
+
```
|
|
205
296
|
|
|
297
|
+
## AI Coding Guidelines
|
|
298
|
+
|
|
299
|
+
### For AI Agents
|
|
300
|
+
|
|
301
|
+
When generating AtomicSkeleton components, follow these rules:
|
|
302
|
+
|
|
303
|
+
1. **Always match pattern to content**:
|
|
304
|
+
```tsx
|
|
305
|
+
// ✅ Good - pattern matches content
|
|
306
|
+
{loading ? (
|
|
307
|
+
<AtomicSkeleton pattern="list" count={3} />
|
|
308
|
+
) : (
|
|
309
|
+
<FlatList data={items} renderItem={({ item }) => <ListItem />} />
|
|
310
|
+
)}
|
|
311
|
+
|
|
312
|
+
// ❌ Bad - pattern doesn't match
|
|
313
|
+
{loading ? (
|
|
314
|
+
<AtomicSkeleton pattern="card" />
|
|
315
|
+
) : (
|
|
316
|
+
<FlatList data={items} renderItem={({ item }) => <Text>{item.title}</Text>} />
|
|
317
|
+
)}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
2. **Always remove skeleton when data arrives**:
|
|
321
|
+
```tsx
|
|
322
|
+
// ✅ Good - proper conditional
|
|
323
|
+
{loading ? (
|
|
324
|
+
<AtomicSkeleton pattern="list" count={3} />
|
|
325
|
+
) : (
|
|
326
|
+
<DataContent data={data} />
|
|
327
|
+
)}
|
|
328
|
+
|
|
329
|
+
// ❌ Bad - skeleton with content
|
|
330
|
+
<View>
|
|
331
|
+
{loading && <AtomicSkeleton />}
|
|
332
|
+
<DataContent data={data} />
|
|
333
|
+
</View>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
3. **Always use reasonable count**:
|
|
337
|
+
```tsx
|
|
338
|
+
// ✅ Good - appropriate count
|
|
339
|
+
<AtomicSkeleton pattern="list" count={3} />
|
|
340
|
+
<AtomicSkeleton pattern="card" count={4} />
|
|
341
|
+
|
|
342
|
+
// ❌ Bad - too many or too few
|
|
343
|
+
<AtomicSkeleton pattern="list" count={15} />
|
|
344
|
+
<AtomicSkeleton pattern="list" count={1} />
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
4. **Always match custom skeleton dimensions**:
|
|
348
|
+
```tsx
|
|
349
|
+
// ✅ Good - dimensions match content
|
|
350
|
+
<AtomicSkeleton
|
|
351
|
+
pattern="custom"
|
|
352
|
+
custom={[
|
|
353
|
+
{ width: 100, height: 100, borderRadius: 50 }, // Avatar
|
|
354
|
+
{ width: 150, height: 20, borderRadius: 4 }, // Name
|
|
355
|
+
]}
|
|
356
|
+
/>
|
|
357
|
+
|
|
358
|
+
// ❌ Bad - wrong dimensions
|
|
359
|
+
<AtomicSkeleton
|
|
360
|
+
pattern="custom"
|
|
361
|
+
custom={[
|
|
362
|
+
{ width: 50, height: 50 }, // Way too small
|
|
363
|
+
{ width: 300, height: 50 }, // Too large
|
|
364
|
+
]}
|
|
365
|
+
/>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
5. **Always avoid skeleton for quick loads**:
|
|
369
|
+
```tsx
|
|
370
|
+
// ✅ Good - delay skeleton
|
|
371
|
+
const [showSkeleton, setShowSkeleton] = useState(false);
|
|
372
|
+
useEffect(() => {
|
|
373
|
+
const timer = setTimeout(() => setShowSkeleton(true), 300);
|
|
374
|
+
return () => clearTimeout(timer);
|
|
375
|
+
}, []);
|
|
376
|
+
|
|
377
|
+
// ❌ Bad - skeleton flashes
|
|
378
|
+
{loading && <AtomicSkeleton />} {/* Even for 200ms loads */}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Common Patterns
|
|
382
|
+
|
|
383
|
+
#### List Loading
|
|
206
384
|
```tsx
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
<View style={{ alignItems: 'center', marginTop: 24 }}>
|
|
213
|
-
<AtomicSkeleton
|
|
214
|
-
pattern="custom"
|
|
215
|
-
custom={[
|
|
216
|
-
{ width: 80, height: 16, borderRadius: 4, marginBottom: 8 },
|
|
217
|
-
{ width: 120, height: 12, borderRadius: 4 },
|
|
218
|
-
]}
|
|
219
|
-
/>
|
|
220
|
-
</View>
|
|
221
|
-
</View>
|
|
222
|
-
);
|
|
223
|
-
};
|
|
385
|
+
{loading ? (
|
|
386
|
+
<AtomicSkeleton pattern="list" count={3} />
|
|
387
|
+
) : (
|
|
388
|
+
<FlatList data={items} renderItem={({ item }) => <ListItem item={item} />} />
|
|
389
|
+
)}
|
|
224
390
|
```
|
|
225
391
|
|
|
226
|
-
|
|
392
|
+
#### Card Grid Loading
|
|
393
|
+
```tsx
|
|
394
|
+
{loading ? (
|
|
395
|
+
<View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
|
|
396
|
+
<AtomicSkeleton pattern="card" count={6} />
|
|
397
|
+
</View>
|
|
398
|
+
) : (
|
|
399
|
+
<ProductGrid products={products} />
|
|
400
|
+
)}
|
|
401
|
+
```
|
|
227
402
|
|
|
403
|
+
#### Avatar List Loading
|
|
228
404
|
```tsx
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
<View style={{ width: 100, height: 16, borderRadius: 4, marginBottom: 8, backgroundColor: '#e0e0e0' }} />
|
|
235
|
-
<View style={{ width: '100%', height: 48, borderRadius: 8, backgroundColor: '#f0f0f0' }} />
|
|
236
|
-
</View>
|
|
237
|
-
))}
|
|
238
|
-
|
|
239
|
-
<View style={{ width: 120, height: 48, borderRadius: 8, backgroundColor: '#e0e0e0' }} />
|
|
240
|
-
</View>
|
|
241
|
-
);
|
|
242
|
-
};
|
|
405
|
+
{loading ? (
|
|
406
|
+
<AtomicSkeleton pattern="avatar" count={8} />
|
|
407
|
+
) : (
|
|
408
|
+
<UserList users={users} />
|
|
409
|
+
)}
|
|
243
410
|
```
|
|
244
411
|
|
|
245
|
-
|
|
412
|
+
#### Custom Skeleton
|
|
413
|
+
```tsx
|
|
414
|
+
{loading ? (
|
|
415
|
+
<AtomicSkeleton
|
|
416
|
+
pattern="custom"
|
|
417
|
+
custom={[
|
|
418
|
+
{ width: '100%', height: 200, borderRadius: 12 },
|
|
419
|
+
{ width: '80%', height: 24, borderRadius: 4, marginBottom: 12 },
|
|
420
|
+
{ width: '100%', height: 16, borderRadius: 4 },
|
|
421
|
+
]}
|
|
422
|
+
/>
|
|
423
|
+
) : (
|
|
424
|
+
<Content />
|
|
425
|
+
)}
|
|
426
|
+
```
|
|
246
427
|
|
|
247
|
-
|
|
428
|
+
## Props Reference
|
|
248
429
|
|
|
249
|
-
| Prop |
|
|
250
|
-
|
|
251
|
-
| `pattern` | `SkeletonPattern` | `'list'` | Skeleton pattern
|
|
252
|
-
| `custom` | `SkeletonConfig[]` | - | Custom
|
|
253
|
-
| `count` | `number` | `1` |
|
|
254
|
-
| `style` | `
|
|
255
|
-
| `testID` | `string` | - | Test
|
|
430
|
+
| Prop | Type | Required | Default | Description |
|
|
431
|
+
|------|------|----------|---------|-------------|
|
|
432
|
+
| `pattern` | `SkeletonPattern` | No | `'list'` | Skeleton pattern |
|
|
433
|
+
| `custom` | `SkeletonConfig[]` | No | - | Custom configuration |
|
|
434
|
+
| `count` | `number` | No | `1` | Number of skeletons |
|
|
435
|
+
| `style` | `ViewStyle` | No | - | Custom style |
|
|
436
|
+
| `testID` | `string` | No | - | Test identifier |
|
|
256
437
|
|
|
257
438
|
### SkeletonPattern
|
|
258
439
|
|
|
259
440
|
```typescript
|
|
260
441
|
type SkeletonPattern =
|
|
261
|
-
| 'list' //
|
|
262
|
-
| 'card' //
|
|
442
|
+
| 'list' // List item
|
|
443
|
+
| 'card' // Card
|
|
263
444
|
| 'avatar' // Avatar
|
|
264
|
-
| 'text' //
|
|
265
|
-
| 'custom'; //
|
|
445
|
+
| 'text' // Text
|
|
446
|
+
| 'custom'; // Custom
|
|
266
447
|
```
|
|
267
448
|
|
|
268
449
|
### SkeletonConfig
|
|
269
450
|
|
|
270
451
|
```typescript
|
|
271
452
|
interface SkeletonConfig {
|
|
272
|
-
width: number | string;
|
|
273
|
-
height?: number;
|
|
274
|
-
borderRadius?: number;
|
|
275
|
-
marginBottom?: number;
|
|
453
|
+
width: number | string; // Width
|
|
454
|
+
height?: number; // Height
|
|
455
|
+
borderRadius?: number; // Corner radius
|
|
456
|
+
marginBottom?: number; // Bottom margin
|
|
276
457
|
}
|
|
277
458
|
```
|
|
278
459
|
|
|
279
|
-
##
|
|
280
|
-
|
|
281
|
-
### 1. Pattern Seçimi
|
|
282
|
-
|
|
283
|
-
```tsx
|
|
284
|
-
// Liste için
|
|
285
|
-
<AtomicSkeleton pattern="list" />
|
|
286
|
-
|
|
287
|
-
// Kart için
|
|
288
|
-
<AtomicSkeleton pattern="card" />
|
|
289
|
-
|
|
290
|
-
// Avatar için
|
|
291
|
-
<AtomicSkeleton pattern="avatar" />
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
### 2. Count Kullanımı
|
|
295
|
-
|
|
296
|
-
```tsx
|
|
297
|
-
// Uzun liste
|
|
298
|
-
<AtomicSkeleton pattern="list" count={10} />
|
|
299
|
-
|
|
300
|
-
// Kısa liste
|
|
301
|
-
<AtomicSkeleton pattern="list" count={3} />
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
### 3. Custom Skeleton
|
|
305
|
-
|
|
306
|
-
```tsx
|
|
307
|
-
// Özel tasarım
|
|
308
|
-
<AtomicSkeleton
|
|
309
|
-
pattern="custom"
|
|
310
|
-
custom={[
|
|
311
|
-
{ width: '100%', height: 200, borderRadius: 12 },
|
|
312
|
-
{ width: '80%', height: 20, borderRadius: 4 },
|
|
313
|
-
]}
|
|
314
|
-
/>
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
## Erişilebilirlik
|
|
318
|
-
|
|
319
|
-
AtomicSkeleton, tam erişilebilirlik desteği sunar:
|
|
460
|
+
## Accessibility
|
|
320
461
|
|
|
321
|
-
- ✅
|
|
322
|
-
- ✅ Loading state
|
|
323
|
-
- ✅ Accessibility
|
|
462
|
+
- ✅ Hidden from screen readers (loading placeholder only)
|
|
463
|
+
- ✅ Loading state announced to screen readers
|
|
464
|
+
- ✅ Accessibility properties for loading context
|
|
324
465
|
|
|
325
|
-
##
|
|
466
|
+
## Performance Tips
|
|
326
467
|
|
|
327
|
-
1. **Minimal
|
|
328
|
-
2. **Simple
|
|
329
|
-
3. **Unload**:
|
|
468
|
+
1. **Minimal count**: Use necessary number of skeletons
|
|
469
|
+
2. **Simple patterns**: Prefer built-in patterns over complex custom
|
|
470
|
+
3. **Unload promptly**: Remove skeleton as soon as data arrives
|
|
471
|
+
4. **Quick loads**: Skip skeleton for loads < 300ms
|
|
330
472
|
|
|
331
|
-
##
|
|
473
|
+
## Related Components
|
|
332
474
|
|
|
333
|
-
- [`AtomicSpinner`](../AtomicSpinner
|
|
334
|
-
- [`EmptyState`](../EmptyState
|
|
335
|
-
- [`AtomicProgress`](../AtomicProgress
|
|
475
|
+
- [`AtomicSpinner`](../AtomicSpinner.README.md) - Loading spinner
|
|
476
|
+
- [`EmptyState`](../EmptyState.README.md) - Empty state
|
|
477
|
+
- [`AtomicProgress`](../AtomicProgress.README.md) - Progress bar
|
|
336
478
|
|
|
337
|
-
##
|
|
479
|
+
## License
|
|
338
480
|
|
|
339
481
|
MIT
|