@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,522 +1,355 @@
|
|
|
1
1
|
# StepProgress
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A simple progress indicator for multi-step workflows that visualizes current step with a horizontal progress bar.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Import & Usage
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
```typescript
|
|
8
|
+
import { StepProgress } from 'react-native-design-system/src/molecules/StepProgress';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Location:** `src/molecules/StepProgress/StepProgress.tsx`
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Basic Usage
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
|
-
|
|
16
|
+
<StepProgress
|
|
17
|
+
currentStep={2}
|
|
18
|
+
totalSteps={4}
|
|
19
|
+
/>
|
|
17
20
|
```
|
|
18
21
|
|
|
19
|
-
##
|
|
22
|
+
## Strategy
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
**Purpose**: Provide clear visual indication of progress in multi-step workflows.
|
|
25
|
+
|
|
26
|
+
**When to Use**:
|
|
27
|
+
- Multi-step forms (3-7 steps)
|
|
28
|
+
- Onboarding flows
|
|
29
|
+
- Checkout wizards
|
|
30
|
+
- Questionnaires
|
|
31
|
+
- Task completion tracking
|
|
32
|
+
- Profile completion flows
|
|
33
|
+
|
|
34
|
+
**When NOT to Use**:
|
|
35
|
+
- For continuous progress (use ProgressBar instead)
|
|
36
|
+
- For single-step forms
|
|
37
|
+
- For too many steps (>7)
|
|
38
|
+
- For non-sequential tasks
|
|
39
|
+
|
|
40
|
+
## Rules
|
|
41
|
+
|
|
42
|
+
### Required
|
|
43
|
+
|
|
44
|
+
1. **MUST** provide `currentStep` and `totalSteps`
|
|
45
|
+
2. **MUST** keep totalSteps between 3 and 7
|
|
46
|
+
3. **ALWAYS** update currentStep dynamically
|
|
47
|
+
4. **SHOULD** display step count to users
|
|
48
|
+
5. **MUST** use 1-based indexing (currentStep starts at 1)
|
|
49
|
+
6. **NEVER** show progress for single-step flows
|
|
50
|
+
7. **ALWAYS** validate currentStep <= totalSteps
|
|
51
|
+
|
|
52
|
+
### Step Management
|
|
53
|
+
|
|
54
|
+
1. **currentStep**: 1-based index (starts at 1)
|
|
55
|
+
2. **totalSteps**: Ideal 3-5, max 7
|
|
56
|
+
3. **Update**: Increment/decrement based on navigation
|
|
57
|
+
4. **Validation**: Ensure currentStep never exceeds totalSteps
|
|
58
|
+
|
|
59
|
+
### Visual Guidelines
|
|
60
|
+
|
|
61
|
+
1. **Position**: Above content, clearly visible
|
|
62
|
+
2. **Size**: Full width of container
|
|
63
|
+
3. **Color**: Theme primary color
|
|
64
|
+
4. **Animation**: Smooth transitions between steps
|
|
40
65
|
|
|
41
|
-
|
|
66
|
+
### User Feedback
|
|
67
|
+
|
|
68
|
+
1. **Show step number**: "Step 2 of 4"
|
|
69
|
+
2. **Show percentage**: "50% complete"
|
|
70
|
+
3. **Update immediately**: On step change
|
|
71
|
+
4. **Indicate completion**: Special state when finished
|
|
72
|
+
|
|
73
|
+
## Forbidden
|
|
74
|
+
|
|
75
|
+
❌ **NEVER** do these:
|
|
42
76
|
|
|
43
77
|
```tsx
|
|
44
|
-
|
|
78
|
+
// ❌ Too many steps
|
|
45
79
|
<StepProgress
|
|
46
|
-
currentStep={
|
|
47
|
-
totalSteps={
|
|
80
|
+
currentStep={5}
|
|
81
|
+
totalSteps={20} // ❌ Too many
|
|
48
82
|
/>
|
|
49
83
|
|
|
50
|
-
|
|
84
|
+
// ❌ Too few steps
|
|
51
85
|
<StepProgress
|
|
52
86
|
currentStep={1}
|
|
53
|
-
totalSteps={
|
|
87
|
+
totalSteps={2} // ❌ Too few for progress indicator
|
|
54
88
|
/>
|
|
55
|
-
```
|
|
56
89
|
|
|
57
|
-
|
|
90
|
+
// ❌ Hardcoded currentStep
|
|
91
|
+
<StepProgress
|
|
92
|
+
currentStep={2} // ❌ Not dynamic
|
|
93
|
+
totalSteps={4}
|
|
94
|
+
/>
|
|
58
95
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return (
|
|
65
|
-
<View>
|
|
66
|
-
<StepProgress
|
|
67
|
-
currentStep={step}
|
|
68
|
-
totalSteps={totalSteps}
|
|
69
|
-
/>
|
|
70
|
-
|
|
71
|
-
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 16 }}>
|
|
72
|
-
<Button
|
|
73
|
-
title="Geri"
|
|
74
|
-
disabled={step === 1}
|
|
75
|
-
onPress={() => setStep(step - 1)}
|
|
76
|
-
/>
|
|
77
|
-
<Button
|
|
78
|
-
title="İleri"
|
|
79
|
-
disabled={step === totalSteps}
|
|
80
|
-
onPress={() => setStep(step + 1)}
|
|
81
|
-
/>
|
|
82
|
-
</View>
|
|
83
|
-
</View>
|
|
84
|
-
);
|
|
85
|
-
};
|
|
86
|
-
```
|
|
96
|
+
// ❌ Wrong indexing (0-based)
|
|
97
|
+
<StepProgress
|
|
98
|
+
currentStep={1} // ❌ Should be 2 for second step
|
|
99
|
+
totalSteps={4}
|
|
100
|
+
/>
|
|
87
101
|
|
|
88
|
-
|
|
102
|
+
// ❌ currentStep exceeds totalSteps
|
|
103
|
+
<StepProgress
|
|
104
|
+
currentStep={5} // ❌ Exceeds totalSteps
|
|
105
|
+
totalSteps={4}
|
|
106
|
+
/>
|
|
89
107
|
|
|
90
|
-
|
|
108
|
+
// ❌ Negative or zero steps
|
|
109
|
+
<StepProgress
|
|
110
|
+
currentStep={0} // ❌ Should be 1-based
|
|
111
|
+
totalSteps={4}
|
|
112
|
+
/>
|
|
91
113
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
{ id: 2, title: 'Profil' },
|
|
98
|
-
{ id: 3, title: 'İlgi Alanları' },
|
|
99
|
-
{ id: 4, title: 'Bitir' },
|
|
100
|
-
];
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<ScreenLayout>
|
|
104
|
-
<StepProgress
|
|
105
|
-
currentStep={currentStep}
|
|
106
|
-
totalSteps={steps.length}
|
|
107
|
-
/>
|
|
108
|
-
|
|
109
|
-
<View style={{ flex: 1, justifyContent: 'center' }}>
|
|
110
|
-
<AtomicText type="headlineLarge" style={{ textAlign: 'center' }}>
|
|
111
|
-
{steps[currentStep - 1].title}
|
|
112
|
-
</AtomicText>
|
|
113
|
-
</View>
|
|
114
|
-
|
|
115
|
-
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
116
|
-
<Button
|
|
117
|
-
title="Geri"
|
|
118
|
-
disabled={currentStep === 1}
|
|
119
|
-
onPress={() => setCurrentStep(currentStep - 1)}
|
|
120
|
-
/>
|
|
121
|
-
<Button
|
|
122
|
-
title={currentStep === steps.length ? 'Bitir' : 'İleri'}
|
|
123
|
-
onPress={() => {
|
|
124
|
-
if (currentStep < steps.length) {
|
|
125
|
-
setCurrentStep(currentStep + 1);
|
|
126
|
-
} else {
|
|
127
|
-
// Finish
|
|
128
|
-
}
|
|
129
|
-
}}
|
|
130
|
-
/>
|
|
131
|
-
</View>
|
|
132
|
-
</ScreenLayout>
|
|
133
|
-
);
|
|
134
|
-
};
|
|
114
|
+
// ❌ Missing progress display
|
|
115
|
+
<View>
|
|
116
|
+
<StepProgress currentStep={2} totalSteps={4} />
|
|
117
|
+
{/* ❌ No indication of which step */}
|
|
118
|
+
</View>
|
|
135
119
|
```
|
|
136
120
|
|
|
137
|
-
|
|
121
|
+
## Best Practices
|
|
122
|
+
|
|
123
|
+
### Dynamic Step Management
|
|
138
124
|
|
|
125
|
+
✅ **DO**:
|
|
139
126
|
```tsx
|
|
140
|
-
|
|
141
|
-
const [checkoutStep, setCheckoutStep] = useState(1);
|
|
142
|
-
const checkoutSteps = ['Sepet', 'Teslimat', 'Ödeme', 'Onay'];
|
|
143
|
-
|
|
144
|
-
return (
|
|
145
|
-
<View>
|
|
146
|
-
<StepProgress
|
|
147
|
-
currentStep={checkoutStep}
|
|
148
|
-
totalSteps={checkoutSteps.length}
|
|
149
|
-
/>
|
|
150
|
-
|
|
151
|
-
<View style={{ marginTop: 16 }}>
|
|
152
|
-
<AtomicText type="titleMedium" style={{ textAlign: 'center', marginBottom: 8 }}>
|
|
153
|
-
{checkoutSteps[checkoutStep - 1]}
|
|
154
|
-
</AtomicText>
|
|
155
|
-
</View>
|
|
156
|
-
|
|
157
|
-
{/* Step content */}
|
|
158
|
-
</View>
|
|
159
|
-
);
|
|
160
|
-
};
|
|
161
|
-
```
|
|
127
|
+
const [step, setStep] = useState(1);
|
|
162
128
|
|
|
163
|
-
|
|
129
|
+
<View>
|
|
130
|
+
<StepProgress
|
|
131
|
+
currentStep={step}
|
|
132
|
+
totalSteps={4}
|
|
133
|
+
/>
|
|
134
|
+
<AtomicText>Step {step} of 4</AtomicText>
|
|
135
|
+
<Button
|
|
136
|
+
title="Next"
|
|
137
|
+
onPress={() => setStep(Math.min(step + 1, 4))}
|
|
138
|
+
/>
|
|
139
|
+
</View>
|
|
140
|
+
```
|
|
164
141
|
|
|
142
|
+
❌ **DON'T**:
|
|
165
143
|
```tsx
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
'Soru 3',
|
|
172
|
-
'Soru 4',
|
|
173
|
-
'Soru 5',
|
|
174
|
-
];
|
|
175
|
-
|
|
176
|
-
const progress = questionIndex + 1;
|
|
177
|
-
|
|
178
|
-
return (
|
|
179
|
-
<View>
|
|
180
|
-
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 }}>
|
|
181
|
-
<AtomicText type="labelLarge">Soru {progress}/{questions.length}</AtomicText>
|
|
182
|
-
<AtomicText type="labelLarge" color="primary">
|
|
183
|
-
%{Math.round((progress / questions.length) * 100)}
|
|
184
|
-
</AtomicText>
|
|
185
|
-
</View>
|
|
186
|
-
|
|
187
|
-
<StepProgress
|
|
188
|
-
currentStep={progress}
|
|
189
|
-
totalSteps={questions.length}
|
|
190
|
-
/>
|
|
191
|
-
|
|
192
|
-
<View style={{ marginTop: 24 }}>
|
|
193
|
-
<AtomicText type="headlineMedium">{questions[questionIndex]}</AtomicText>
|
|
194
|
-
</View>
|
|
195
|
-
|
|
196
|
-
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 32 }}>
|
|
197
|
-
<Button
|
|
198
|
-
title="Önceki"
|
|
199
|
-
disabled={questionIndex === 0}
|
|
200
|
-
onPress={() => setQuestionIndex(questionIndex - 1)}
|
|
201
|
-
/>
|
|
202
|
-
<Button
|
|
203
|
-
title={questionIndex === questions.length - 1 ? 'Bitir' : 'Sonraki'}
|
|
204
|
-
onPress={() => {
|
|
205
|
-
if (questionIndex < questions.length - 1) {
|
|
206
|
-
setQuestionIndex(questionIndex + 1);
|
|
207
|
-
} else {
|
|
208
|
-
// Submit quiz
|
|
209
|
-
}
|
|
210
|
-
}}
|
|
211
|
-
/>
|
|
212
|
-
</View>
|
|
213
|
-
</View>
|
|
214
|
-
);
|
|
215
|
-
};
|
|
144
|
+
// ❌ Hardcoded
|
|
145
|
+
<StepProgress
|
|
146
|
+
currentStep={2}
|
|
147
|
+
totalSteps={4}
|
|
148
|
+
/>
|
|
216
149
|
```
|
|
217
150
|
|
|
218
|
-
###
|
|
151
|
+
### Number of Steps
|
|
219
152
|
|
|
153
|
+
✅ **DO**:
|
|
220
154
|
```tsx
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const formSteps = ['Kişisel', 'İletişim', 'Adres', 'Onay'];
|
|
224
|
-
|
|
225
|
-
return (
|
|
226
|
-
<AtomicCard variant="outlined">
|
|
227
|
-
<View style={{ padding: 16 }}>
|
|
228
|
-
<StepProgress
|
|
229
|
-
currentStep={formStep}
|
|
230
|
-
totalSteps={formSteps.length}
|
|
231
|
-
/>
|
|
232
|
-
|
|
233
|
-
<View style={{ marginTop: 24 }}>
|
|
234
|
-
{formStep === 1 && (
|
|
235
|
-
<View>
|
|
236
|
-
<AtomicText type="titleLarge">Kişisel Bilgiler</AtomicText>
|
|
237
|
-
<FormField label="Ad" />
|
|
238
|
-
<FormField label="Soyad" />
|
|
239
|
-
</View>
|
|
240
|
-
)}
|
|
241
|
-
|
|
242
|
-
{formStep === 2 && (
|
|
243
|
-
<View>
|
|
244
|
-
<AtomicText type="titleLarge">İletişim Bilgileri</AtomicText>
|
|
245
|
-
<FormField label="E-posta" />
|
|
246
|
-
<FormField label="Telefon" />
|
|
247
|
-
</View>
|
|
248
|
-
)}
|
|
249
|
-
|
|
250
|
-
{formStep === 3 && (
|
|
251
|
-
<View>
|
|
252
|
-
<AtomicText type="titleLarge">Adres</AtomicText>
|
|
253
|
-
<FormField label="Şehir" />
|
|
254
|
-
<FormField label="Ülke" />
|
|
255
|
-
</View>
|
|
256
|
-
)}
|
|
257
|
-
|
|
258
|
-
{formStep === 4 && (
|
|
259
|
-
<View>
|
|
260
|
-
<AtomicText type="titleLarge">Onayla</AtomicText>
|
|
261
|
-
<AtomicText>Bilgilerinizi kontrol edin</AtomicText>
|
|
262
|
-
</View>
|
|
263
|
-
)}
|
|
264
|
-
</View>
|
|
265
|
-
|
|
266
|
-
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 24 }}>
|
|
267
|
-
<Button
|
|
268
|
-
title="Geri"
|
|
269
|
-
variant="ghost"
|
|
270
|
-
disabled={formStep === 1}
|
|
271
|
-
onPress={() => setFormStep(formStep - 1)}
|
|
272
|
-
/>
|
|
273
|
-
<Button
|
|
274
|
-
title={formStep === formSteps.length ? 'Gönder' : 'İleri'}
|
|
275
|
-
onPress={() => {
|
|
276
|
-
if (formStep < formSteps.length) {
|
|
277
|
-
setFormStep(formStep + 1);
|
|
278
|
-
} else {
|
|
279
|
-
// Submit form
|
|
280
|
-
}
|
|
281
|
-
}}
|
|
282
|
-
/>
|
|
283
|
-
</View>
|
|
284
|
-
</View>
|
|
285
|
-
</AtomicCard>
|
|
286
|
-
);
|
|
287
|
-
};
|
|
155
|
+
// ✅ Good: 3-5 steps
|
|
156
|
+
<StepProgress currentStep={2} totalSteps={4} />
|
|
288
157
|
```
|
|
289
158
|
|
|
290
|
-
|
|
291
|
-
|
|
159
|
+
❌ **DON'T**:
|
|
292
160
|
```tsx
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (completedTasks < totalTasks) {
|
|
299
|
-
setCompletedTasks(completedTasks + 1);
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
const progressPercentage = Math.round((completedTasks / totalTasks) * 100);
|
|
304
|
-
|
|
305
|
-
return (
|
|
306
|
-
<AtomicCard variant="elevated">
|
|
307
|
-
<View style={{ padding: 16 }}>
|
|
308
|
-
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 }}>
|
|
309
|
-
<AtomicText type="titleMedium">Günlük Görevler</AtomicText>
|
|
310
|
-
<AtomicText type="labelLarge" color="primary">
|
|
311
|
-
%{progressPercentage}
|
|
312
|
-
</AtomicText>
|
|
313
|
-
</View>
|
|
314
|
-
|
|
315
|
-
<StepProgress
|
|
316
|
-
currentStep={completedTasks}
|
|
317
|
-
totalTasks={totalTasks}
|
|
318
|
-
/>
|
|
319
|
-
|
|
320
|
-
<View style={{ marginTop: 16 }}>
|
|
321
|
-
<AtomicText type="bodyMedium" color="secondary">
|
|
322
|
-
{completedTasks}/{totalTasks} görev tamamlandı
|
|
323
|
-
</AtomicText>
|
|
324
|
-
</View>
|
|
325
|
-
|
|
326
|
-
{completedTasks < totalTasks && (
|
|
327
|
-
<Button
|
|
328
|
-
title="Görevi Tamamla"
|
|
329
|
-
onPress={toggleTask}
|
|
330
|
-
style={{ marginTop: 16 }}
|
|
331
|
-
/>
|
|
332
|
-
)}
|
|
333
|
-
|
|
334
|
-
{completedTasks === totalTasks && (
|
|
335
|
-
<View style={{ marginTop: 16, alignItems: 'center' }}>
|
|
336
|
-
<AtomicIcon name="checkmark-circle" size="xl" color="success" />
|
|
337
|
-
<AtomicText type="titleMedium" color="success" style={{ marginTop: 8 }}>
|
|
338
|
-
Tüm görevler tamamlandı!
|
|
339
|
-
</AtomicText>
|
|
340
|
-
</View>
|
|
341
|
-
)}
|
|
342
|
-
</View>
|
|
343
|
-
</AtomicCard>
|
|
344
|
-
);
|
|
345
|
-
};
|
|
161
|
+
// ❌ Bad: Too many
|
|
162
|
+
<StepProgress currentStep={5} totalSteps={15} />
|
|
163
|
+
|
|
164
|
+
// ❌ Bad: Too few
|
|
165
|
+
<StepProgress currentStep={1} totalSteps={2} />
|
|
346
166
|
```
|
|
347
167
|
|
|
348
|
-
###
|
|
168
|
+
### User Feedback
|
|
349
169
|
|
|
170
|
+
✅ **DO**:
|
|
350
171
|
```tsx
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
return (
|
|
362
|
-
<View>
|
|
363
|
-
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 }}>
|
|
364
|
-
<AtomicText type="titleMedium">Dosya Yükleme</AtomicText>
|
|
365
|
-
<AtomicText type="labelLarge">
|
|
366
|
-
{uploadedFiles}/{totalFiles}
|
|
367
|
-
</AtomicText>
|
|
368
|
-
</View>
|
|
369
|
-
|
|
370
|
-
<StepProgress
|
|
371
|
-
currentStep={uploadedFiles}
|
|
372
|
-
totalSteps={totalFiles}
|
|
373
|
-
/>
|
|
374
|
-
|
|
375
|
-
{uploadedFiles < totalFiles && (
|
|
376
|
-
<Button
|
|
377
|
-
title="Dosya Yükle"
|
|
378
|
-
onPress={uploadFile}
|
|
379
|
-
style={{ marginTop: 16 }}
|
|
380
|
-
/>
|
|
381
|
-
)}
|
|
382
|
-
|
|
383
|
-
{uploadedFiles === totalFiles && (
|
|
384
|
-
<AtomicText type="bodyMedium" color="success" style={{ marginTop: 16 }}>
|
|
385
|
-
Tüm dosyalar yüklendi ✓
|
|
386
|
-
</AtomicText>
|
|
387
|
-
)}
|
|
388
|
-
</View>
|
|
389
|
-
);
|
|
390
|
-
};
|
|
172
|
+
<View>
|
|
173
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
174
|
+
<AtomicText>Question {currentStep}/{totalSteps}</AtomicText>
|
|
175
|
+
<AtomicText>%{Math.round((currentStep / totalSteps) * 100)}</AtomicText>
|
|
176
|
+
</View>
|
|
177
|
+
<StepProgress currentStep={currentStep} totalSteps={totalSteps} />
|
|
178
|
+
</View>
|
|
391
179
|
```
|
|
392
180
|
|
|
393
|
-
###
|
|
181
|
+
### Step Validation
|
|
394
182
|
|
|
183
|
+
✅ **DO**:
|
|
395
184
|
```tsx
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
];
|
|
407
|
-
|
|
408
|
-
return (
|
|
409
|
-
<View style={{ padding: 16 }}>
|
|
410
|
-
<AtomicText type="headlineMedium" style={{ marginBottom: 8 }}>
|
|
411
|
-
Profilinizi Tamamlayın
|
|
412
|
-
</AtomicText>
|
|
413
|
-
|
|
414
|
-
<StepProgress
|
|
415
|
-
currentStep={completedSections}
|
|
416
|
-
totalSteps={totalSections}
|
|
417
|
-
/>
|
|
418
|
-
|
|
419
|
-
<View style={{ marginTop: 16 }}>
|
|
420
|
-
<AtomicText type="bodyMedium" color="secondary">
|
|
421
|
-
{completedSections}/{totalSections} bölüm tamamlandı
|
|
422
|
-
</AtomicText>
|
|
423
|
-
</View>
|
|
424
|
-
|
|
425
|
-
<View style={{ marginTop: 16 }}>
|
|
426
|
-
{sections.map((section) => (
|
|
427
|
-
<View
|
|
428
|
-
key={section.id}
|
|
429
|
-
style={{
|
|
430
|
-
flexDirection: 'row',
|
|
431
|
-
alignItems: 'center',
|
|
432
|
-
paddingVertical: 8,
|
|
433
|
-
borderBottomWidth: 1,
|
|
434
|
-
borderBottomColor: '#e0e0e0',
|
|
435
|
-
}}
|
|
436
|
-
>
|
|
437
|
-
<AtomicIcon
|
|
438
|
-
name={section.completed ? 'checkmark-circle' : 'ellipse-outline'}
|
|
439
|
-
size="md"
|
|
440
|
-
color={section.completed ? 'success' : 'secondary'}
|
|
441
|
-
/>
|
|
442
|
-
<AtomicText style={{ marginLeft: 12 }}>
|
|
443
|
-
{section.name}
|
|
444
|
-
</AtomicText>
|
|
445
|
-
</View>
|
|
446
|
-
))}
|
|
447
|
-
</View>
|
|
448
|
-
</View>
|
|
449
|
-
);
|
|
185
|
+
const goToNextStep = () => {
|
|
186
|
+
if (currentStep < totalSteps) {
|
|
187
|
+
setCurrentStep(currentStep + 1);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const goToPrevStep = () => {
|
|
192
|
+
if (currentStep > 1) {
|
|
193
|
+
setCurrentStep(currentStep - 1);
|
|
194
|
+
}
|
|
450
195
|
};
|
|
451
196
|
```
|
|
452
197
|
|
|
453
|
-
##
|
|
198
|
+
## AI Coding Guidelines
|
|
454
199
|
|
|
455
|
-
###
|
|
200
|
+
### For AI Agents
|
|
456
201
|
|
|
457
|
-
|
|
458
|
-
|------|-----|------------|----------|
|
|
459
|
-
| `currentStep` | `number` | - **(Zorunlu)** | Mevcut adım |
|
|
460
|
-
| `totalSteps` | `number` | - **(Zorunlu)** | Toplam adım sayısı |
|
|
461
|
-
| `style` | `ViewStyle` | - | Özel stil |
|
|
202
|
+
When generating StepProgress components, follow these rules:
|
|
462
203
|
|
|
463
|
-
|
|
204
|
+
1. **Always import from correct path**:
|
|
205
|
+
```typescript
|
|
206
|
+
import { StepProgress } from 'react-native-design-system/src/molecules/StepProgress';
|
|
207
|
+
```
|
|
464
208
|
|
|
465
|
-
|
|
209
|
+
2. **Always use dynamic state management**:
|
|
210
|
+
```tsx
|
|
211
|
+
// ✅ Good - dynamic state
|
|
212
|
+
const [step, setStep] = useState(1);
|
|
213
|
+
<StepProgress currentStep={step} totalSteps={4} />
|
|
466
214
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
215
|
+
// ❌ Bad - hardcoded
|
|
216
|
+
<StepProgress currentStep={2} totalSteps={4} />
|
|
217
|
+
```
|
|
470
218
|
|
|
471
|
-
|
|
472
|
-
|
|
219
|
+
3. **Always validate step count**:
|
|
220
|
+
```tsx
|
|
221
|
+
// ✅ Good - appropriate number of steps
|
|
222
|
+
<StepProgress currentStep={2} totalSteps={4} />
|
|
473
223
|
|
|
474
|
-
//
|
|
475
|
-
<StepProgress currentStep={5} totalSteps={20} />
|
|
476
|
-
```
|
|
224
|
+
// ❌ Bad - too many steps
|
|
225
|
+
<StepProgress currentStep={5} totalSteps={20} />
|
|
226
|
+
```
|
|
477
227
|
|
|
478
|
-
|
|
228
|
+
4. **Always provide user feedback**:
|
|
229
|
+
```tsx
|
|
230
|
+
// ✅ Good - show step number
|
|
231
|
+
<View>
|
|
232
|
+
<AtomicText>Step {step} of {totalSteps}</AtomicText>
|
|
233
|
+
<StepProgress currentStep={step} totalSteps={totalSteps} />
|
|
234
|
+
</View>
|
|
479
235
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
<StepProgress currentStep={step} totalSteps={5} />
|
|
236
|
+
// ❌ Bad - no feedback
|
|
237
|
+
<StepProgress currentStep={step} totalSteps={totalSteps} />
|
|
238
|
+
```
|
|
484
239
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
240
|
+
5. **Always use 1-based indexing**:
|
|
241
|
+
```tsx
|
|
242
|
+
// ✅ Good - 1-based
|
|
243
|
+
const [step, setStep] = useState(1); // Starts at 1
|
|
244
|
+
|
|
245
|
+
// ❌ Bad - 0-based
|
|
246
|
+
const [step, setStep] = useState(0); // Starts at 0
|
|
247
|
+
```
|
|
488
248
|
|
|
489
|
-
###
|
|
249
|
+
### Common Patterns
|
|
250
|
+
|
|
251
|
+
#### Onboarding Progress
|
|
252
|
+
```tsx
|
|
253
|
+
const [currentStep, setCurrentStep] = useState(1);
|
|
254
|
+
const steps = ['Welcome', 'Profile', 'Interests', 'Finish'];
|
|
255
|
+
|
|
256
|
+
<View>
|
|
257
|
+
<StepProgress
|
|
258
|
+
currentStep={currentStep}
|
|
259
|
+
totalSteps={steps.length}
|
|
260
|
+
/>
|
|
261
|
+
<AtomicText type="titleMedium" style={{ textAlign: 'center', marginTop: 8 }}>
|
|
262
|
+
{steps[currentStep - 1]}
|
|
263
|
+
</AtomicText>
|
|
264
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 16 }}>
|
|
265
|
+
<Button
|
|
266
|
+
title="Back"
|
|
267
|
+
disabled={currentStep === 1}
|
|
268
|
+
onPress={() => setCurrentStep(currentStep - 1)}
|
|
269
|
+
/>
|
|
270
|
+
<Button
|
|
271
|
+
title={currentStep === steps.length ? 'Finish' : 'Next'}
|
|
272
|
+
onPress={() => setCurrentStep(Math.min(currentStep + 1, steps.length))}
|
|
273
|
+
/>
|
|
274
|
+
</View>
|
|
275
|
+
</View>
|
|
276
|
+
```
|
|
490
277
|
|
|
278
|
+
#### Quiz Progress
|
|
491
279
|
```tsx
|
|
492
|
-
|
|
493
|
-
|
|
280
|
+
const [questionIndex, setQuestionIndex] = useState(0);
|
|
281
|
+
const questions = ['Q1', 'Q2', 'Q3', 'Q4', 'Q5'];
|
|
282
|
+
|
|
283
|
+
<View>
|
|
284
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 }}>
|
|
285
|
+
<AtomicText type="labelLarge">
|
|
286
|
+
Question {questionIndex + 1}/{questions.length}
|
|
287
|
+
</AtomicText>
|
|
288
|
+
<AtomicText type="labelLarge" color="primary">
|
|
289
|
+
%{Math.round(((questionIndex + 1) / questions.length) * 100)}
|
|
290
|
+
</AtomicText>
|
|
291
|
+
</View>
|
|
292
|
+
<StepProgress
|
|
293
|
+
currentStep={questionIndex + 1}
|
|
294
|
+
totalSteps={questions.length}
|
|
295
|
+
/>
|
|
296
|
+
<AtomicText type="headlineMedium" style={{ marginTop: 24 }}>
|
|
297
|
+
{questions[questionIndex]}
|
|
298
|
+
</AtomicText>
|
|
299
|
+
</View>
|
|
300
|
+
```
|
|
494
301
|
|
|
495
|
-
|
|
496
|
-
|
|
302
|
+
#### Task Completion
|
|
303
|
+
```tsx
|
|
304
|
+
const [completedTasks, setCompletedTasks] = useState(0);
|
|
305
|
+
const totalTasks = 10;
|
|
306
|
+
|
|
307
|
+
<View>
|
|
308
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 }}>
|
|
309
|
+
<AtomicText type="titleMedium">Daily Tasks</AtomicText>
|
|
310
|
+
<AtomicText type="labelLarge" color="primary">
|
|
311
|
+
%{Math.round((completedTasks / totalTasks) * 100)}
|
|
312
|
+
</AtomicText>
|
|
313
|
+
</View>
|
|
314
|
+
<StepProgress
|
|
315
|
+
currentStep={completedTasks}
|
|
316
|
+
totalSteps={totalTasks}
|
|
317
|
+
/>
|
|
318
|
+
<AtomicText type="bodyMedium" color="secondary" style={{ marginTop: 8 }}>
|
|
319
|
+
{completedTasks}/{totalTasks} tasks completed
|
|
320
|
+
</AtomicText>
|
|
321
|
+
</View>
|
|
497
322
|
```
|
|
498
323
|
|
|
499
|
-
##
|
|
324
|
+
## Props Reference
|
|
325
|
+
|
|
326
|
+
| Prop | Type | Required | Default | Description |
|
|
327
|
+
|------|------|----------|---------|-------------|
|
|
328
|
+
| `currentStep` | `number` | **Yes** | - | Current step (1-based) |
|
|
329
|
+
| `totalSteps` | `number` | **Yes** | - | Total number of steps (3-7 recommended) |
|
|
330
|
+
| `style` | `ViewStyle` | No | - | Custom container style |
|
|
500
331
|
|
|
501
|
-
|
|
332
|
+
## Accessibility
|
|
502
333
|
|
|
503
|
-
- ✅ Screen reader
|
|
504
|
-
- ✅ Semantic role
|
|
505
|
-
- ✅
|
|
506
|
-
- ✅
|
|
334
|
+
- ✅ Screen reader announces progress
|
|
335
|
+
- ✅ Semantic progress role
|
|
336
|
+
- ✅ Visual contrast maintained
|
|
337
|
+
- ✅ Progress percentage available
|
|
338
|
+
- ✅ Step count announced
|
|
507
339
|
|
|
508
|
-
##
|
|
340
|
+
## Performance Tips
|
|
509
341
|
|
|
510
|
-
1. **Memoization**:
|
|
511
|
-
2. **Minimal
|
|
512
|
-
3. **Stable
|
|
342
|
+
1. **Memoization**: Memo component to prevent re-renders
|
|
343
|
+
2. **Minimal props**: Only 2 required props
|
|
344
|
+
3. **Stable references**: Use stable state values
|
|
345
|
+
4. **Optimize updates**: Only update when step changes
|
|
513
346
|
|
|
514
|
-
##
|
|
347
|
+
## Related Components
|
|
515
348
|
|
|
516
|
-
- [`StepHeader`](../StepHeader/README.md) -
|
|
517
|
-
- [`Divider`](../Divider/README.md) -
|
|
518
|
-
- [`AtomicText`](../../atoms/AtomicText/README.md) -
|
|
349
|
+
- [`StepHeader`](../StepHeader/README.md) - Step header component
|
|
350
|
+
- [`Divider`](../Divider/README.md) - Divider component
|
|
351
|
+
- [`AtomicText`](../../atoms/AtomicText/README.md) - Text component
|
|
519
352
|
|
|
520
|
-
##
|
|
353
|
+
## License
|
|
521
354
|
|
|
522
355
|
MIT
|