@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.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/src/atoms/AtomicAvatar.README.md +284 -397
  3. package/src/atoms/AtomicBadge.README.md +123 -358
  4. package/src/atoms/AtomicCard.README.md +358 -247
  5. package/src/atoms/AtomicDatePicker.README.md +127 -332
  6. package/src/atoms/AtomicFab.README.md +194 -352
  7. package/src/atoms/AtomicIcon.README.md +241 -274
  8. package/src/atoms/AtomicProgress.README.md +100 -338
  9. package/src/atoms/AtomicSpinner.README.md +304 -337
  10. package/src/atoms/AtomicText.README.md +153 -389
  11. package/src/atoms/AtomicTextArea.README.md +267 -268
  12. package/src/atoms/EmptyState.README.md +247 -292
  13. package/src/atoms/GlassView/README.md +313 -444
  14. package/src/atoms/button/README.md +186 -297
  15. package/src/atoms/button/STRATEGY.md +252 -0
  16. package/src/atoms/chip/README.md +242 -290
  17. package/src/atoms/input/README.md +296 -290
  18. package/src/atoms/picker/README.md +278 -309
  19. package/src/atoms/skeleton/AtomicSkeleton.README.md +394 -252
  20. package/src/exports/theme.ts +0 -1
  21. package/src/molecules/BaseModal/README.md +356 -0
  22. package/src/molecules/BaseModal.README.md +324 -200
  23. package/src/molecules/ConfirmationModal.README.md +349 -302
  24. package/src/molecules/Divider/README.md +293 -376
  25. package/src/molecules/FormField.README.md +321 -534
  26. package/src/molecules/GlowingCard/GlowingCard.tsx +1 -1
  27. package/src/molecules/GlowingCard/README.md +230 -372
  28. package/src/molecules/IconContainer.tsx +1 -1
  29. package/src/molecules/List/README.md +281 -488
  30. package/src/molecules/ListItem.README.md +320 -315
  31. package/src/molecules/SearchBar/README.md +332 -430
  32. package/src/molecules/StepHeader/README.md +311 -411
  33. package/src/molecules/StepProgress/README.md +281 -448
  34. package/src/molecules/alerts/README.md +272 -355
  35. package/src/molecules/avatar/README.md +295 -356
  36. package/src/molecules/bottom-sheet/README.md +303 -340
  37. package/src/molecules/calendar/README.md +301 -265
  38. package/src/molecules/countdown/README.md +347 -456
  39. package/src/molecules/emoji/README.md +281 -514
  40. package/src/molecules/listitem/README.md +307 -399
  41. package/src/molecules/media-card/MediaCard.tsx +31 -34
  42. package/src/molecules/media-card/README.md +217 -319
  43. package/src/molecules/navigation/README.md +263 -284
  44. package/src/molecules/splash/README.md +76 -92
  45. package/src/molecules/swipe-actions/README.md +376 -588
@@ -1,636 +1,423 @@
1
1
  # FormField
2
2
 
3
- FormField is a molecule component that combines a label, input field, and validation messages into a complete form input unit. It wraps `AtomicInput` with `AtomicText` for labels and error/helper messages.
3
+ A molecule component that combines label, input field, and validation messages into a complete form input unit.
4
4
 
5
- ## Features
5
+ ## Import & Usage
6
6
 
7
- - 📝 **Complete Form Input**: Label, input, and messages in one component
8
- - **Validation**: Error and helper text support
9
- - 🔴 **Required Indicator**: Visual required field marker
10
- - 🎨 **Theme-Aware**: Design token integration
11
- - ♿ **Accessible**: Full accessibility support
12
- - 🎯 **Simple API**: Easy to use with minimal props
13
-
14
- ## Installation
15
-
16
- ```tsx
17
- import { FormField } from 'react-native-design-system';
7
+ ```typescript
8
+ import { FormField } from 'react-native-design-system/src/molecules/FormField';
18
9
  ```
19
10
 
20
- ## Basic Usage
11
+ **Location:** `src/molecules/FormField.tsx`
21
12
 
22
- ```tsx
23
- import React, { useState } from 'react';
24
- import { View } from 'react-native';
25
- import { FormField } from 'react-native-design-system';
26
-
27
- export const BasicExample = () => {
28
- const [email, setEmail] = useState('');
29
-
30
- return (
31
- <View style={{ padding: 16 }}>
32
- <FormField
33
- label="Email"
34
- value={email}
35
- onChangeText={setEmail}
36
- placeholder="Enter your email"
37
- />
38
- </View>
39
- );
40
- };
41
- ```
42
-
43
- ## Basic Input
13
+ ## Basic Usage
44
14
 
45
15
  ```tsx
46
- <FormField
47
- label="Username"
48
- value={username}
49
- onChangeText={setUsername}
50
- placeholder="Enter username"
51
- />
52
- ```
16
+ const [email, setEmail] = useState('');
53
17
 
54
- ## With Error
55
-
56
- ```tsx
57
18
  <FormField
58
19
  label="Email"
59
20
  value={email}
60
21
  onChangeText={setEmail}
61
22
  placeholder="Enter your email"
62
- error="Please enter a valid email address"
63
23
  />
64
24
  ```
65
25
 
66
- ## Required Field
26
+ ## Strategy
67
27
 
68
- ```tsx
69
- <FormField
70
- label="Password"
71
- value={password}
72
- onChangeText={setPassword}
73
- placeholder="Enter password"
74
- secureTextEntry
75
- required
76
- />
77
- ```
28
+ **Purpose**: Provide a consistent, accessible form input unit with integrated labeling, validation, and helper text.
78
29
 
79
- ## Helper Text
30
+ **When to Use**:
31
+ - All form inputs requiring labels
32
+ - Data entry forms (login, registration, settings)
33
+ - Multi-field forms
34
+ - Input fields with validation requirements
35
+ - Fields needing helper text or error messages
80
36
 
81
- ```tsx
82
- <FormField
83
- label="Username"
84
- value={username}
85
- onChangeText={setUsername}
86
- placeholder="Choose a username"
87
- helperText="Must be at least 3 characters long"
88
- />
89
- ```
37
+ **When NOT to Use**:
38
+ - For standalone inputs without labels (use AtomicInput instead)
39
+ - For search-only inputs (use SearchBar instead)
40
+ - For simple text display (use AtomicText instead)
41
+
42
+ ## Rules
43
+
44
+ ### Required
45
+
46
+ 1. **MUST** have a `label` prop for accessibility
47
+ 2. **ALWAYS** provide `value` and `onChangeText` for controlled inputs
48
+ 3. **MUST** show clear error messages when validation fails
49
+ 4. **SHOULD** provide helper text for format requirements
50
+ 5. **ALWAYS** mark required fields visually with `required` prop
51
+ 6. **MUST** clear errors when user starts typing
52
+ 7. **SHOULD** use appropriate `keyboardType` for the input type
53
+
54
+ ### Error Handling
55
+
56
+ 1. **MUST** provide specific, actionable error messages
57
+ 2. **SHOULD** show errors only after validation (not on focus)
58
+ 3. **MUST** clear error when user corrects the input
59
+ 4. **NEVER** show generic errors like "Invalid input"
60
+
61
+ ### Validation
62
+
63
+ 1. **Validate on blur**: Validate when user leaves the field
64
+ 2. **Clear on type**: Clear error when user starts typing
65
+ 3. **Show inline errors**: Display errors below the input
66
+ 4. **Required fields**: Always validate required fields
90
67
 
91
- ## Custom Required Indicator
68
+ ### Helper Text
69
+
70
+ 1. **Use for guidance**: Explain format or requirements
71
+ 2. **Keep concise**: One short sentence
72
+ 3. **Don't state obvious**: Avoid "Enter your name"
73
+ 4. **Provide examples**: Show format when helpful
74
+
75
+ ## Forbidden
76
+
77
+ ❌ **NEVER** do these:
92
78
 
93
79
  ```tsx
80
+ // ❌ No label
94
81
  <FormField
95
- label="Email"
96
82
  value={email}
97
83
  onChangeText={setEmail}
98
- placeholder="your@email.com"
99
- required
100
- requiredIndicator=" (required)"
84
+ placeholder="Email" // ❌ Placeholder is not a label
101
85
  />
102
- ```
103
86
 
104
- ## With Icons
87
+ // Generic error message
88
+ <FormField
89
+ label="Email"
90
+ error="Invalid" // ❌ Not actionable
91
+ />
105
92
 
106
- ```tsx
93
+ // ❌ Error persists after correction
107
94
  <FormField
108
95
  label="Email"
109
96
  value={email}
97
+ error={emailError} // ❌ Error still shows when typing
110
98
  onChangeText={setEmail}
111
- placeholder="your@email.com"
112
- leftIcon="mail-outline"
113
- rightIcon="checkmark-circle-outline"
114
99
  />
115
- ```
116
100
 
117
- ## Example Usages
101
+ // Required but not visually marked
102
+ <FormField
103
+ label="Email" // ❌ Missing required prop
104
+ required={false} // Actually required
105
+ />
106
+
107
+ // ❌ Unhelpful helper text
108
+ <FormField
109
+ label="Email"
110
+ helperText="Enter your email here" // ❌ Obvious
111
+ />
118
112
 
119
- ### Login Form
113
+ // Wrong keyboard type
114
+ <FormField
115
+ label="Email"
116
+ keyboardType="default" // ❌ Should be email-address
117
+ />
120
118
 
121
- ```tsx
122
- export const LoginForm = () => {
123
- const [email, setEmail] = useState('');
124
- const [password, setPassword] = useState('');
125
- const [errors, setErrors] = useState({});
126
-
127
- const validate = () => {
128
- const newErrors = {};
129
-
130
- if (!email) {
131
- newErrors.email = 'Email is required';
132
- } else if (!isValidEmail(email)) {
133
- newErrors.email = 'Please enter a valid email';
134
- }
135
-
136
- if (!password) {
137
- newErrors.password = 'Password is required';
138
- } else if (password.length < 6) {
139
- newErrors.password = 'Password must be at least 6 characters';
140
- }
141
-
142
- setErrors(newErrors);
143
- return Object.keys(newErrors).length === 0;
144
- };
145
-
146
- const handleSubmit = () => {
147
- if (validate()) {
148
- login({ email, password });
149
- }
150
- };
151
-
152
- return (
153
- <View style={{ padding: 16 }}>
154
- <FormField
155
- label="Email"
156
- value={email}
157
- onChangeText={setEmail}
158
- placeholder="your@email.com"
159
- keyboardType="email-address"
160
- autoCapitalize="none"
161
- error={errors.email}
162
- required
163
- />
164
-
165
- <FormField
166
- label="Password"
167
- value={password}
168
- onChangeText={setPassword}
169
- placeholder="Enter password"
170
- secureTextEntry
171
- error={errors.password}
172
- required
173
- />
174
-
175
- <Button title="Login" onPress={handleSubmit} />
176
- </View>
177
- );
119
+ // ❌ Not clearing errors
120
+ const handleChange = (text) => {
121
+ setEmail(text);
122
+ // Error not cleared
178
123
  };
179
124
  ```
180
125
 
181
- ### Registration Form
126
+ ## Best Practices
127
+
128
+ ### Error Handling
182
129
 
130
+ ✅ **DO**:
183
131
  ```tsx
184
- export const RegistrationForm = () => {
185
- const [formData, setFormData] = useState({
186
- firstName: '',
187
- lastName: '',
188
- email: '',
189
- password: '',
190
- confirmPassword: '',
191
- });
192
-
193
- const [errors, setErrors] = useState({});
194
-
195
- const handleChange = (field, value) => {
196
- setFormData({ ...formData, [field]: value });
197
- // Clear error when user starts typing
198
- if (errors[field]) {
199
- setErrors({ ...errors, [field]: null });
200
- }
201
- };
202
-
203
- const validate = () => {
204
- const newErrors = {};
205
-
206
- if (!formData.firstName) newErrors.firstName = 'First name is required';
207
- if (!formData.lastName) newErrors.lastName = 'Last name is required';
208
- if (!formData.email) newErrors.email = 'Email is required';
209
- if (!formData.password) newErrors.password = 'Password is required';
210
- if (formData.password !== formData.confirmPassword) {
211
- newErrors.confirmPassword = 'Passwords do not match';
212
- }
213
-
214
- setErrors(newErrors);
215
- return Object.keys(newErrors).length === 0;
216
- };
217
-
218
- return (
219
- <ScrollView style={{ padding: 16 }}>
220
- <FormField
221
- label="First Name"
222
- value={formData.firstName}
223
- onChangeText={(value) => handleChange('firstName', value)}
224
- placeholder="John"
225
- error={errors.firstName}
226
- required
227
- />
228
-
229
- <FormField
230
- label="Last Name"
231
- value={formData.lastName}
232
- onChangeText={(value) => handleChange('lastName', value)}
233
- placeholder="Doe"
234
- error={errors.lastName}
235
- required
236
- />
237
-
238
- <FormField
239
- label="Email"
240
- value={formData.email}
241
- onChangeText={(value) => handleChange('email', value)}
242
- placeholder="john.doe@example.com"
243
- keyboardType="email-address"
244
- autoCapitalize="none"
245
- error={errors.email}
246
- required
247
- />
248
-
249
- <FormField
250
- label="Password"
251
- value={formData.password}
252
- onChangeText={(value) => handleChange('password', value)}
253
- placeholder="Create a password"
254
- secureTextEntry
255
- error={errors.password}
256
- helperText="Must be at least 8 characters"
257
- required
258
- />
259
-
260
- <FormField
261
- label="Confirm Password"
262
- value={formData.confirmPassword}
263
- onChangeText={(value) => handleChange('confirmPassword', value)}
264
- placeholder="Confirm your password"
265
- secureTextEntry
266
- error={errors.confirmPassword}
267
- required
268
- />
269
-
270
- <Button title="Create Account" onPress={validate} />
271
- </ScrollView>
272
- );
132
+ const [email, setEmail] = useState('');
133
+ const [emailError, setEmailError] = useState('');
134
+
135
+ const validateEmail = (email) => {
136
+ if (!email) return 'Email is required';
137
+ if (!isValidEmail(email)) return 'Please enter a valid email address';
138
+ return '';
273
139
  };
274
- ```
275
140
 
276
- ### Profile Settings
141
+ const handleChange = (text) => {
142
+ setEmail(text);
143
+ if (emailError) setEmailError(''); // Clear error on type
144
+ };
277
145
 
278
- ```tsx
279
- export const ProfileSettings = () => {
280
- const [profile, setProfile] = useState({
281
- displayName: '',
282
- username: '',
283
- bio: '',
284
- location: '',
285
- website: '',
286
- });
287
-
288
- return (
289
- <ScrollView style={{ padding: 16 }}>
290
- <FormField
291
- label="Display Name"
292
- value={profile.displayName}
293
- onChangeText={(value) => setProfile({ ...profile, displayName: value })}
294
- placeholder="John Doe"
295
- helperText="This is how you'll appear on your profile"
296
- />
297
-
298
- <FormField
299
- label="Username"
300
- value={profile.username}
301
- onChangeText={(value) => setProfile({ ...profile, username: value })}
302
- placeholder="johndoe"
303
- helperText="https://example.com/username"
304
- leftIcon="at-outline"
305
- />
306
-
307
- <FormField
308
- label="Bio"
309
- value={profile.bio}
310
- onChangeText={(value) => setProfile({ ...profile, bio: value })}
311
- placeholder="Tell us about yourself"
312
- multiline
313
- numberOfLines={4}
314
- helperText="Maximum 150 characters"
315
- />
316
-
317
- <FormField
318
- label="Location"
319
- value={profile.location}
320
- onChangeText={(value) => setProfile({ ...profile, location: value })}
321
- placeholder="New York, NY"
322
- leftIcon="location-outline"
323
- />
324
-
325
- <FormField
326
- label="Website"
327
- value={profile.website}
328
- onChangeText={(value) => setProfile({ ...profile, website: value })}
329
- placeholder="https://yourwebsite.com"
330
- keyboardType="url"
331
- autoCapitalize="none"
332
- leftIcon="link-outline"
333
- />
334
-
335
- <Button title="Save Changes" onPress={handleSave} />
336
- </ScrollView>
337
- );
146
+ const handleBlur = () => {
147
+ const error = validateEmail(email);
148
+ setEmailError(error);
338
149
  };
339
- ```
340
150
 
341
- ### Address Form
151
+ <FormField
152
+ label="Email"
153
+ value={email}
154
+ onChangeText={handleChange}
155
+ onBlur={handleBlur}
156
+ error={emailError}
157
+ keyboardType="email-address"
158
+ autoCapitalize="none"
159
+ required
160
+ />
161
+ ```
342
162
 
163
+ ❌ **DON'T**:
343
164
  ```tsx
344
- export const AddressForm = () => {
345
- const [address, setAddress] = useState({
346
- street: '',
347
- apartment: '',
348
- city: '',
349
- state: '',
350
- zipCode: '',
351
- country: '',
352
- });
353
-
354
- return (
355
- <View style={{ padding: 16 }}>
356
- <FormField
357
- label="Street Address"
358
- value={address.street}
359
- onChangeText={(value) => setAddress({ ...address, street: value })}
360
- placeholder="123 Main St"
361
- required
362
- />
363
-
364
- <FormField
365
- label="Apartment/Suite (optional)"
366
- value={address.apartment}
367
- onChangeText={(value) => setAddress({ ...address, apartment: value })}
368
- placeholder="Apt 4B"
369
- />
370
-
371
- <FormField
372
- label="City"
373
- value={address.city}
374
- onChangeText={(value) => setAddress({ ...address, city: value })}
375
- placeholder="New York"
376
- required
377
- />
378
-
379
- <View style={{ flexDirection: 'row', gap: 8 }}>
380
- <View style={{ flex: 1 }}>
381
- <FormField
382
- label="State"
383
- value={address.state}
384
- onChangeText={(value) => setAddress({ ...address, state: value })}
385
- placeholder="NY"
386
- required
387
- />
388
- </View>
389
-
390
- <View style={{ flex: 1 }}>
391
- <FormField
392
- label="ZIP Code"
393
- value={address.zipCode}
394
- onChangeText={(value) => setAddress({ ...address, zipCode: value })}
395
- placeholder="10001"
396
- keyboardType="number-pad"
397
- required
398
- />
399
- </View>
400
- </View>
401
-
402
- <FormField
403
- label="Country"
404
- value={address.country}
405
- onChangeText={(value) => setAddress({ ...address, country: value })}
406
- placeholder="United States"
407
- required
408
- />
409
- </View>
410
- );
165
+ // Generic error
166
+ <FormField
167
+ label="Email"
168
+ error="Invalid input" // Not specific
169
+ />
170
+
171
+ // ❌ Error persists
172
+ const handleChange = (text) => {
173
+ setEmail(text);
174
+ // Error still shows
411
175
  };
412
176
  ```
413
177
 
414
- ### Credit Card Form
178
+ ### Helper Text
415
179
 
180
+ ✅ **DO**:
416
181
  ```tsx
417
- export const CreditCardForm = () => {
418
- const [card, setCard] = useState({
419
- cardNumber: '',
420
- cardHolder: '',
421
- expiryDate: '',
422
- cvv: '',
423
- });
424
-
425
- const formatCardNumber = (text) => {
426
- return text.replace(/\s/g, '').replace(/(.{4})/g, '$1 ').trim();
427
- };
428
-
429
- const formatExpiry = (text) => {
430
- if (text.length === 2 && !text.includes('/')) {
431
- return text + '/';
432
- }
433
- return text;
434
- };
435
-
436
- return (
437
- <View style={{ padding: 16 }}>
438
- <FormField
439
- label="Card Number"
440
- value={card.cardNumber}
441
- onChangeText={(value) => setCard({ ...card, cardNumber: formatCardNumber(value) })}
442
- placeholder="1234 5678 9012 3456"
443
- keyboardType="number-pad"
444
- maxLength={19}
445
- leftIcon="card-outline"
446
- required
447
- />
448
-
449
- <FormField
450
- label="Cardholder Name"
451
- value={card.cardHolder}
452
- onChangeText={(value) => setCard({ ...card, cardHolder: value })}
453
- placeholder="JOHN DOE"
454
- autoCapitalize="characters"
455
- required
456
- />
457
-
458
- <View style={{ flexDirection: 'row', gap: 8 }}>
459
- <View style={{ flex: 1 }}>
460
- <FormField
461
- label="Expiry Date"
462
- value={card.expiryDate}
463
- onChangeText={(value) => setCard({ ...card, expiryDate: formatExpiry(value) })}
464
- placeholder="MM/YY"
465
- keyboardType="number-pad"
466
- maxLength={5}
467
- required
468
- />
469
- </View>
470
-
471
- <View style={{ flex: 1 }}>
472
- <FormField
473
- label="CVV"
474
- value={card.cvv}
475
- onChangeText={(value) => setCard({ ...card, cvv: value })}
476
- placeholder="123"
477
- keyboardType="number-pad"
478
- maxLength={4}
479
- secureTextEntry
480
- helperText="3 or 4 digits on back of card"
481
- required
482
- />
483
- </View>
484
- </View>
485
- </View>
486
- );
487
- };
182
+ <FormField
183
+ label="Password"
184
+ helperText="Must be at least 8 characters with 1 number"
185
+ secureTextEntry
186
+ />
488
187
  ```
489
188
 
490
- ### Search Form
491
-
189
+ **DON'T**:
492
190
  ```tsx
493
- export const SearchForm = () => {
494
- const [searchTerm, setSearchTerm] = useState('');
495
- const [filters, setFilters] = useState({
496
- category: '',
497
- minPrice: '',
498
- maxPrice: '',
499
- });
500
-
501
- return (
502
- <View style={{ padding: 16 }}>
503
- <FormField
504
- label="Search"
505
- value={searchTerm}
506
- onChangeText={setSearchTerm}
507
- placeholder="What are you looking for?"
508
- leftIcon="search-outline"
509
- />
510
-
511
- <FormField
512
- label="Category"
513
- value={filters.category}
514
- onChangeText={(value) => setFilters({ ...filters, category: value })}
515
- placeholder="Select a category"
516
- rightIcon="chevron-down-outline"
517
- />
518
-
519
- <View style={{ flexDirection: 'row', gap: 8 }}>
520
- <View style={{ flex: 1 }}>
521
- <FormField
522
- label="Min Price"
523
- value={filters.minPrice}
524
- onChangeText={(value) => setFilters({ ...filters, minPrice: value })}
525
- placeholder="$0"
526
- keyboardType="number-pad"
527
- />
528
- </View>
529
-
530
- <View style={{ flex: 1 }}>
531
- <FormField
532
- label="Max Price"
533
- value={filters.maxPrice}
534
- onChangeText={(value) => setFilters({ ...filters, maxPrice: value })}
535
- placeholder="$1000"
536
- keyboardType="number-pad"
537
- />
538
- </View>
539
- </View>
540
-
541
- <Button title="Search" onPress={handleSearch} />
542
- </View>
543
- );
544
- };
191
+ <FormField
192
+ label="Password"
193
+ helperText="Enter your password here" // Obvious
194
+ />
545
195
  ```
546
196
 
547
- ## Props
548
-
549
- ### FormFieldProps
550
-
551
- Extends `Omit<AtomicInputProps, 'state' | 'label'>`
552
-
553
- | Prop | Type | Default | Description |
554
- |------|------|---------|-------------|
555
- | `label` | `string` | - | Field label |
556
- | `error` | `string` | - | Error message |
557
- | `helperText` | `string` | - | Helper text |
558
- | `required` | `boolean` | `false` | Show required indicator |
559
- | `containerStyle` | `ViewStyle` | - | Container style |
560
- | `style` | `ViewStyle` | - | Alias for containerStyle |
561
- | `requiredIndicator` | `string` | `' *'` | Required indicator text |
562
-
563
- Plus all AtomicInput props:
564
- - `value`, `onChangeText`, `placeholder`, `secureTextEntry`, `keyboardType`, etc.
565
-
566
- ## Best Practices
567
-
568
- ### 1. Error Handling
197
+ ### Required Fields
569
198
 
199
+ ✅ **DO**:
570
200
  ```tsx
571
- // ✅ Good: Clear specific errors
572
201
  <FormField
573
- error="Email must be in format: user@example.com"
202
+ label="Email"
203
+ required
204
+ error={emailError}
574
205
  />
206
+ ```
575
207
 
576
- // Bad: Vague errors
208
+ **DON'T**:
209
+ ```tsx
210
+ // ❌ No visual required indicator
577
211
  <FormField
578
- error="Invalid"
212
+ label="Email"
213
+ error={emailError || '* Required'}
579
214
  />
580
215
  ```
581
216
 
582
- ### 2. Helper Text
583
-
217
+ ## AI Coding Guidelines
218
+
219
+ ### For AI Agents
220
+
221
+ When generating FormField components, follow these rules:
222
+
223
+ 1. **Always import from correct path**:
224
+ ```typescript
225
+ import { FormField } from 'react-native-design-system/src/molecules/FormField';
226
+ ```
227
+
228
+ 2. **Always provide a label**:
229
+ ```tsx
230
+ // ✅ Good
231
+ <FormField
232
+ label="Email"
233
+ value={email}
234
+ onChangeText={setEmail}
235
+ />
236
+
237
+ // ❌ Bad - no label
238
+ <FormField
239
+ value={email}
240
+ onChangeText={setEmail}
241
+ placeholder="Email" // Placeholder is not a label
242
+ />
243
+ ```
244
+
245
+ 3. **Always handle errors properly**:
246
+ ```tsx
247
+ // ✅ Good - clear errors on type
248
+ const handleChange = (text) => {
249
+ setValue(text);
250
+ if (error) setError('');
251
+ };
252
+
253
+ // ❌ Bad - error persists
254
+ const handleChange = (text) => {
255
+ setValue(text);
256
+ // Error still shows
257
+ };
258
+ ```
259
+
260
+ 4. **Always use specific error messages**:
261
+ ```tsx
262
+ // ✅ Good - specific errors
263
+ const validateEmail = (email) => {
264
+ if (!email) return 'Email is required';
265
+ if (!isValidEmail(email)) return 'Please enter a valid email address';
266
+ if (!isCompanyEmail(email)) return 'Please use your company email';
267
+ return '';
268
+ };
269
+
270
+ // ❌ Bad - generic error
271
+ const validate = (value) => {
272
+ if (!value) return 'Invalid';
273
+ };
274
+ ```
275
+
276
+ 5. **Always use appropriate keyboard type**:
277
+ ```tsx
278
+ // ✅ Good - correct keyboard types
279
+ <FormField
280
+ label="Email"
281
+ keyboardType="email-address"
282
+ autoCapitalize="none"
283
+ />
284
+ <FormField
285
+ label="ZIP Code"
286
+ keyboardType="number-pad"
287
+ />
288
+ <FormField
289
+ label="Website"
290
+ keyboardType="url"
291
+ />
292
+
293
+ // ❌ Bad - always default
294
+ <FormField
295
+ label="Email"
296
+ keyboardType="default"
297
+ />
298
+ ```
299
+
300
+ ### Common Patterns
301
+
302
+ #### Basic Form Field
584
303
  ```tsx
585
- // ✅ Good: Helpful guidance
586
304
  <FormField
587
- helperText="Must be at least 8 characters with 1 number"
305
+ label="Email"
306
+ value={email}
307
+ onChangeText={setEmail}
308
+ placeholder="your@email.com"
309
+ keyboardType="email-address"
310
+ autoCapitalize="none"
311
+ required
588
312
  />
313
+ ```
314
+
315
+ #### Field with Error Handling
316
+ ```tsx
317
+ const [email, setEmail] = useState('');
318
+ const [error, setError] = useState('');
319
+
320
+ const handleChange = (text) => {
321
+ setEmail(text);
322
+ if (error) setError('');
323
+ };
324
+
325
+ const handleBlur = () => {
326
+ if (!email) setError('Email is required');
327
+ else if (!isValidEmail(email)) setError('Please enter a valid email');
328
+ };
589
329
 
590
- // ❌ Bad: Obvious info
591
330
  <FormField
592
- helperText="Enter text here"
331
+ label="Email"
332
+ value={email}
333
+ onChangeText={handleChange}
334
+ onBlur={handleBlur}
335
+ error={error}
336
+ required
593
337
  />
594
338
  ```
595
339
 
596
- ### 3. Required Fields
340
+ #### Field with Helper Text
341
+ ```tsx
342
+ <FormField
343
+ label="Password"
344
+ value={password}
345
+ onChangeText={setPassword}
346
+ placeholder="Enter password"
347
+ secureTextEntry
348
+ helperText="Must be at least 8 characters with 1 number"
349
+ required
350
+ />
351
+ ```
597
352
 
353
+ #### Field with Icons
598
354
  ```tsx
599
- // ✅ Good: Use sparingly
600
355
  <FormField
601
356
  label="Email"
602
- required
357
+ value={email}
358
+ onChangeText={setEmail}
359
+ placeholder="your@email.com"
360
+ leftIcon="mail-outline"
361
+ keyboardType="email-address"
603
362
  />
363
+ ```
604
364
 
605
- // Bad: Overuse
365
+ #### Multiline Field
366
+ ```tsx
606
367
  <FormField
607
- label="Optional Field"
608
- required
368
+ label="Bio"
369
+ value={bio}
370
+ onChangeText={setBio}
371
+ placeholder="Tell us about yourself"
372
+ multiline
373
+ numberOfLines={4}
374
+ helperText="Maximum 150 characters"
609
375
  />
610
376
  ```
611
377
 
612
- ## Accessibility
378
+ ## Props Reference
379
+
380
+ | Prop | Type | Required | Default | Description |
381
+ |------|------|----------|---------|-------------|
382
+ | `label` | `string` | Yes | - | Field label |
383
+ | `value` | `string` | Yes | - | Input value |
384
+ | `onChangeText` | `(text: string) => void` | Yes | - | Change callback |
385
+ | `error` | `string` | No | - | Error message |
386
+ | `helperText` | `string` | No | - | Helper text |
387
+ | `required` | `boolean` | No | `false` | Show required indicator |
388
+ | `placeholder` | `string` | No | - | Placeholder text |
389
+ | `secureTextEntry` | `boolean` | No | `false` | Password field |
390
+ | `keyboardType` | `KeyboardType` | No | `'default'` | Keyboard type |
391
+ | `autoCapitalize` | `'none' \| 'sentences' \| 'words' \| 'characters'` | No | - | Auto capitalize |
392
+ | `multiline` | `boolean` | No | `false` | Multiline input |
393
+ | `numberOfLines` | `number` | No | - | Number of lines |
394
+ | `leftIcon` | `string` | No | - | Left icon name |
395
+ | `rightIcon` | `string` | No | - | Right icon name |
396
+ | `onBlur` | `() => void` | No | - | Blur callback |
397
+ | `onFocus` | `() => void` | No | - | Focus callback |
613
398
 
614
- FormField provides full accessibility support:
399
+ ## Accessibility
615
400
 
616
- - ✅ Screen reader labels
617
- - ✅ Error announcements
618
- - ✅ Required field indicators
619
- - ✅ Helper text
620
- - ✅ Auto-focus handling
401
+ - ✅ Screen reader announces label and current value
402
+ - ✅ Error messages are announced to screen readers
403
+ - ✅ Required fields are indicated visually
404
+ - ✅ Helper text provides additional context
405
+ - ✅ Proper label-input association
406
+ - ✅ Touch target size maintained (min 44x44pt)
621
407
 
622
408
  ## Performance Tips
623
409
 
624
- 1. **Controlled Inputs**: Always use controlled inputs with state
625
- 2. **Validation Debounce**: Debounce validation for better UX
410
+ 1. **Controlled inputs**: Always use controlled inputs with state
411
+ 2. **Validation debounce**: Debounce validation for better UX
626
412
  3. **Memoization**: Memo validation functions
413
+ 4. **Clear errors**: Clear errors immediately on input change
627
414
 
628
415
  ## Related Components
629
416
 
630
417
  - [`AtomicInput`](../atoms/input/README.md) - Base input component
631
418
  - [`AtomicText`](../atoms/AtomicText/README.md) - Text component
632
419
  - [`Button`](../atoms/button/README.md) - Button component
633
- - [`AlertInline`](../alerts/README.md) - Inline alert component
420
+ - [`BaseModal`](./BaseModal/README.md) - Modal for forms
634
421
 
635
422
  ## License
636
423