@umituz/react-native-design-system 2.6.94 → 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/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/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 -80
- package/src/molecules/swipe-actions/README.md +376 -588
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# BaseModal
|
|
2
|
+
|
|
3
|
+
A generic fullscreen modal component for React Native with responsive design, providing a consistent base for all modal types.
|
|
4
|
+
|
|
5
|
+
## Import & Usage
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { BaseModal } from 'react-native-design-system/src/molecules/BaseModal';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Location:** `src/molecules/BaseModal/BaseModal.tsx`
|
|
12
|
+
|
|
13
|
+
## Basic Usage
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
<BaseModal visible={isVisible} onClose={handleClose}>
|
|
17
|
+
<YourModalContent />
|
|
18
|
+
</BaseModal>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Strategy
|
|
22
|
+
|
|
23
|
+
**Purpose**: Provide a consistent, accessible, and performant modal system for the application.
|
|
24
|
+
|
|
25
|
+
**When to Use**:
|
|
26
|
+
- Form modals (login, registration, edit)
|
|
27
|
+
- Confirmation dialogs
|
|
28
|
+
- Information displays
|
|
29
|
+
- Settings panels
|
|
30
|
+
- Multi-step wizards
|
|
31
|
+
|
|
32
|
+
**When NOT to Use**:
|
|
33
|
+
- For simple alerts (use Alert/toast instead)
|
|
34
|
+
- For slide-up panels (use BottomSheet instead)
|
|
35
|
+
- For dropdowns (use Dropdown/Popover instead)
|
|
36
|
+
- For side panels (use Drawer instead)
|
|
37
|
+
|
|
38
|
+
## Rules
|
|
39
|
+
|
|
40
|
+
### Required
|
|
41
|
+
|
|
42
|
+
1. **MUST** have a close mechanism (onClose required)
|
|
43
|
+
2. **ALWAYS** provide a visible close button or back-drop dismiss
|
|
44
|
+
3. **MUST** handle escape key (desktop) and back button (mobile)
|
|
45
|
+
4. **NEVER** nest modals inside modals
|
|
46
|
+
5. **SHOULD** have title for accessibility
|
|
47
|
+
6. **MUST** trap focus within modal (accessibility)
|
|
48
|
+
|
|
49
|
+
### Dismiss Behavior
|
|
50
|
+
|
|
51
|
+
1. **Default**: Backdrop dismiss enabled
|
|
52
|
+
2. **Critical actions**: Disable backdrop dismiss, require explicit action
|
|
53
|
+
3. **Always provide close button** (don't rely only on backdrop)
|
|
54
|
+
|
|
55
|
+
### Modal Size
|
|
56
|
+
|
|
57
|
+
1. **Responsive**: Auto-adjusts to device size
|
|
58
|
+
2. **Mobile**: Full width with margin
|
|
59
|
+
3. **Tablet**: Fixed width (600px recommended)
|
|
60
|
+
4. **Desktop**: Fixed width centered (max 800px)
|
|
61
|
+
|
|
62
|
+
### Content Guidelines
|
|
63
|
+
|
|
64
|
+
1. **Scrollable content**: Use ScrollView for long content
|
|
65
|
+
2. **Actions at bottom**: Place buttons at bottom (right-aligned or full-width)
|
|
66
|
+
3. **Title at top**: Clear title with optional close button
|
|
67
|
+
|
|
68
|
+
## Forbidden
|
|
69
|
+
|
|
70
|
+
❌ **NEVER** do these:
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
// ❌ No close mechanism
|
|
74
|
+
<BaseModal visible={true}>
|
|
75
|
+
<Content />
|
|
76
|
+
</BaseModal>
|
|
77
|
+
|
|
78
|
+
// ❌ Nested modals
|
|
79
|
+
<BaseModal visible={true}>
|
|
80
|
+
<Content />
|
|
81
|
+
<BaseModal visible={true}>
|
|
82
|
+
<NestedModal />
|
|
83
|
+
</BaseModal>
|
|
84
|
+
</BaseModal>
|
|
85
|
+
|
|
86
|
+
// ❌ No backdrop dismiss for non-critical
|
|
87
|
+
<BaseModal
|
|
88
|
+
visible={true}
|
|
89
|
+
dismissOnBackdrop={false}
|
|
90
|
+
>
|
|
91
|
+
<InfoContent /> {/* ❌ Not critical */}
|
|
92
|
+
</BaseModal>
|
|
93
|
+
|
|
94
|
+
// ❌ No title (accessibility issue)
|
|
95
|
+
<BaseModal visible={true} onClose={onClose}>
|
|
96
|
+
<Content /> {/* ❌ Missing title */}
|
|
97
|
+
</BaseModal>
|
|
98
|
+
|
|
99
|
+
// ❌ Full-screen hardcoded
|
|
100
|
+
<BaseModal
|
|
101
|
+
visible={true}
|
|
102
|
+
contentStyle={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
|
|
103
|
+
>
|
|
104
|
+
<Content />
|
|
105
|
+
</BaseModal>
|
|
106
|
+
|
|
107
|
+
// ❌ Manual z-index wars
|
|
108
|
+
<BaseModal visible={true} style={{ zIndex: 9999 }}>
|
|
109
|
+
<Content />
|
|
110
|
+
</BaseModal>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Best Practices
|
|
114
|
+
|
|
115
|
+
### Confirmation Modal
|
|
116
|
+
|
|
117
|
+
✅ **DO**:
|
|
118
|
+
```tsx
|
|
119
|
+
<BaseModal
|
|
120
|
+
visible={showConfirmation}
|
|
121
|
+
onClose={() => setShowConfirmation(false)}
|
|
122
|
+
dismissOnBackdrop={false}
|
|
123
|
+
>
|
|
124
|
+
<View style={{ padding: 24 }}>
|
|
125
|
+
<AtomicText type="titleLarge" style={{ marginBottom: 16 }}>
|
|
126
|
+
Confirm Action
|
|
127
|
+
</AtomicText>
|
|
128
|
+
<AtomicText style={{ marginBottom: 24 }}>
|
|
129
|
+
Are you sure you want to proceed?
|
|
130
|
+
</AtomicText>
|
|
131
|
+
<View style={{ flexDirection: 'row', justifyContent: 'flex-end', gap: 12 }}>
|
|
132
|
+
<Button title="Cancel" variant="ghost" onPress={() => setShowConfirmation(false)} />
|
|
133
|
+
<Button title="Confirm" onPress={handleConfirm} />
|
|
134
|
+
</View>
|
|
135
|
+
</View>
|
|
136
|
+
</BaseModal>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
❌ **DON'T**:
|
|
140
|
+
```tsx
|
|
141
|
+
// ❌ No clear confirmation
|
|
142
|
+
<BaseModal visible={showConfirmation} onClose={onClose}>
|
|
143
|
+
<Button title="OK" onPress={onClose} />
|
|
144
|
+
</BaseModal>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Form Modal
|
|
148
|
+
|
|
149
|
+
✅ **DO**:
|
|
150
|
+
```tsx
|
|
151
|
+
<BaseModal visible={showForm} onClose={handleClose}>
|
|
152
|
+
<ScrollView style={{ padding: 24 }}>
|
|
153
|
+
<AtomicText type="titleLarge" style={{ marginBottom: 24 }}>
|
|
154
|
+
Create Item
|
|
155
|
+
</AtomicText>
|
|
156
|
+
<FormField label="Name" value={name} onChangeText={setName} />
|
|
157
|
+
<FormField label="Email" value={email} onChangeText={setEmail} />
|
|
158
|
+
</ScrollView>
|
|
159
|
+
<View style={{ padding: 16, borderTopWidth: 1, borderColor: '#e0e0e0' }}>
|
|
160
|
+
<Button title="Cancel" variant="ghost" onPress={handleClose} style={{ marginRight: 8 }} />
|
|
161
|
+
<Button title="Save" onPress={handleSave} />
|
|
162
|
+
</View>
|
|
163
|
+
</BaseModal>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Loading Modal
|
|
167
|
+
|
|
168
|
+
✅ **DO**:
|
|
169
|
+
```tsx
|
|
170
|
+
<BaseModal
|
|
171
|
+
visible={isLoading}
|
|
172
|
+
onClose={() => {}}
|
|
173
|
+
dismissOnBackdrop={false}
|
|
174
|
+
contentStyle={{ backgroundColor: 'transparent', borderColor: 'transparent' }}
|
|
175
|
+
>
|
|
176
|
+
<View style={{ backgroundColor: '#fff', padding: 32, borderRadius: 16, alignItems: 'center' }}>
|
|
177
|
+
<AtomicSpinner size="lg" />
|
|
178
|
+
<AtomicText style={{ marginTop: 16 }}>Please wait...</AtomicText>
|
|
179
|
+
</View>
|
|
180
|
+
</BaseModal>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## AI Coding Guidelines
|
|
184
|
+
|
|
185
|
+
### For AI Agents
|
|
186
|
+
|
|
187
|
+
When generating BaseModal components, follow these rules:
|
|
188
|
+
|
|
189
|
+
1. **Always import from correct path**:
|
|
190
|
+
```typescript
|
|
191
|
+
import { BaseModal } from 'react-native-design-system/src/molecules/BaseModal';
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
2. **Always provide close mechanism**:
|
|
195
|
+
```tsx
|
|
196
|
+
<BaseModal
|
|
197
|
+
visible={visible}
|
|
198
|
+
onClose={具体的关闭函数}
|
|
199
|
+
dismissOnBackdrop={根据操作重要性决定}
|
|
200
|
+
>
|
|
201
|
+
{content}
|
|
202
|
+
</BaseModal>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
3. **Always handle state properly**:
|
|
206
|
+
```tsx
|
|
207
|
+
const [visible, setVisible] = useState(false);
|
|
208
|
+
|
|
209
|
+
const open = () => setVisible(true);
|
|
210
|
+
const close = () => setVisible(false);
|
|
211
|
+
|
|
212
|
+
<BaseModal visible={visible} onClose={close}>
|
|
213
|
+
{content}
|
|
214
|
+
</BaseModal>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
4. **Always consider content length**:
|
|
218
|
+
```tsx
|
|
219
|
+
// ✅ Good - ScrollView for long content
|
|
220
|
+
<BaseModal visible={visible} onClose={close}>
|
|
221
|
+
<ScrollView style={{ padding: 24 }}>
|
|
222
|
+
{longContent}
|
|
223
|
+
</ScrollView>
|
|
224
|
+
</BaseModal>
|
|
225
|
+
|
|
226
|
+
// ✅ Good - View for short content
|
|
227
|
+
<BaseModal visible={visible} onClose={close}>
|
|
228
|
+
<View style={{ padding: 24 }}>
|
|
229
|
+
{shortContent}
|
|
230
|
+
</View>
|
|
231
|
+
</BaseModal>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
5. **Always use dismissOnBackdrop appropriately**:
|
|
235
|
+
```tsx
|
|
236
|
+
// ✅ Good - non-critical modal
|
|
237
|
+
<BaseModal
|
|
238
|
+
visible={showInfo}
|
|
239
|
+
onClose={close}
|
|
240
|
+
dismissOnBackdrop={true}
|
|
241
|
+
>
|
|
242
|
+
<InfoContent />
|
|
243
|
+
</BaseModal>
|
|
244
|
+
|
|
245
|
+
// ✅ Good - critical action (prevent accidental dismiss)
|
|
246
|
+
<BaseModal
|
|
247
|
+
visible={showConfirmation}
|
|
248
|
+
onClose={close}
|
|
249
|
+
dismissOnBackdrop={false}
|
|
250
|
+
>
|
|
251
|
+
<ConfirmationContent />
|
|
252
|
+
</BaseModal>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Common Patterns
|
|
256
|
+
|
|
257
|
+
#### Form Modal
|
|
258
|
+
```tsx
|
|
259
|
+
<BaseModal visible={visible} onClose={handleClose}>
|
|
260
|
+
<ScrollView style={{ padding: 24 }}>
|
|
261
|
+
<AtomicText type="headlineLarge">Edit Profile</AtomicText>
|
|
262
|
+
<FormField label="Name" value={name} onChangeText={setName} />
|
|
263
|
+
<FormField label="Email" value={email} onChangeText={setEmail} />
|
|
264
|
+
</ScrollView>
|
|
265
|
+
<View style={{ flexDirection: 'row', justifyContent: 'flex-end', padding: 16, gap: 12 }}>
|
|
266
|
+
<Button title="Cancel" variant="ghost" onPress={handleClose} />
|
|
267
|
+
<Button title="Save" onPress={handleSave} />
|
|
268
|
+
</View>
|
|
269
|
+
</BaseModal>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### Confirmation Modal
|
|
273
|
+
```tsx
|
|
274
|
+
<BaseModal
|
|
275
|
+
visible={showConfirm}
|
|
276
|
+
onClose={() => setShowConfirm(false)}
|
|
277
|
+
dismissOnBackdrop={false}
|
|
278
|
+
>
|
|
279
|
+
<View style={{ padding: 24, alignItems: 'center' }}>
|
|
280
|
+
<AtomicIcon name="warning" size="xl" color="warning" />
|
|
281
|
+
<AtomicText type="titleLarge" style={{ marginTop: 16 }}>
|
|
282
|
+
Confirm Delete
|
|
283
|
+
</AtomicText>
|
|
284
|
+
<AtomicText style={{ marginTop: 8, textAlign: 'center' }}>
|
|
285
|
+
This action cannot be undone
|
|
286
|
+
</AtomicText>
|
|
287
|
+
<View style={{ flexDirection: 'row', marginTop: 24, gap: 12 }}>
|
|
288
|
+
<Button title="Cancel" variant="ghost" onPress={() => setShowConfirm(false)} />
|
|
289
|
+
<Button title="Delete" variant="destructive" onPress={handleDelete} />
|
|
290
|
+
</View>
|
|
291
|
+
</View>
|
|
292
|
+
</BaseModal>
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### Success Modal
|
|
296
|
+
```tsx
|
|
297
|
+
<BaseModal
|
|
298
|
+
visible={showSuccess}
|
|
299
|
+
onClose={() => setShowSuccess(false)}
|
|
300
|
+
dismissOnBackdrop={true}
|
|
301
|
+
>
|
|
302
|
+
<View style={{ padding: 32, alignItems: 'center' }}>
|
|
303
|
+
<View style={{
|
|
304
|
+
width: 80, height: 80, borderRadius: 40,
|
|
305
|
+
backgroundColor: '#10b981', justifyContent: 'center', alignItems: 'center'
|
|
306
|
+
}}>
|
|
307
|
+
<AtomicIcon name="checkmark" size="xl" customColor="#fff" />
|
|
308
|
+
</View>
|
|
309
|
+
<AtomicText type="titleLarge" style={{ marginTop: 24 }}>
|
|
310
|
+
Success!
|
|
311
|
+
</AtomicText>
|
|
312
|
+
<AtomicText style={{ marginTop: 12, textAlign: 'center', color: '#666' }}>
|
|
313
|
+
Operation completed successfully
|
|
314
|
+
</AtomicText>
|
|
315
|
+
<Button title="Continue" onPress={() => setShowSuccess(false)} style={{ marginTop: 32 }} />
|
|
316
|
+
</View>
|
|
317
|
+
</BaseModal>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Props Reference
|
|
321
|
+
|
|
322
|
+
| Prop | Type | Required | Default | Description |
|
|
323
|
+
|------|------|----------|---------|-------------|
|
|
324
|
+
| `visible` | `boolean` | **Yes** | - | Modal visibility |
|
|
325
|
+
| `onClose` | `() => void` | **Yes** | - | Close callback |
|
|
326
|
+
| `children` | `ReactNode` | **Yes** | - | Modal content |
|
|
327
|
+
| `dismissOnBackdrop` | `boolean` | No | `true` | Close on backdrop tap |
|
|
328
|
+
| `contentStyle` | `ViewStyle` | No | - | Custom content style |
|
|
329
|
+
| `testID` | `string` | No | `'base-modal'` | Test ID for testing |
|
|
330
|
+
|
|
331
|
+
## Accessibility
|
|
332
|
+
|
|
333
|
+
- ✅ Screen reader announces modal title and content
|
|
334
|
+
- ✅ Focus trap within modal
|
|
335
|
+
- ✅ Keyboard navigation (Escape to close)
|
|
336
|
+
- ✅ Semantic roles and labels
|
|
337
|
+
- ✅ Focus management (return focus to trigger)
|
|
338
|
+
- ✅ Back button handling on mobile
|
|
339
|
+
|
|
340
|
+
## Performance Tips
|
|
341
|
+
|
|
342
|
+
1. **Lazy loading**: Load modal content only when visible
|
|
343
|
+
2. **Memoization**: Memo modal content
|
|
344
|
+
3. **Conditional rendering**: Don't render when not visible
|
|
345
|
+
4. **Cleanup**: Clean up resources and subscriptions on close
|
|
346
|
+
|
|
347
|
+
## Related Components
|
|
348
|
+
|
|
349
|
+
- [`ConfirmationModal`](./confirmation-modal/README.md) - Pre-styled confirmation modal
|
|
350
|
+
- [`BottomSheet`](./bottom-sheet/README.md) - Bottom sheet modal
|
|
351
|
+
- [`FormField`](./FormField/README.md) - Form field component
|
|
352
|
+
- [`Button`](../../atoms/button/README.md) - Button component
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
MIT
|