@delightui/components 0.1.104 → 0.1.106

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 (120) hide show
  1. package/README.md +104 -1
  2. package/dist/cjs/components/molecules/Modal/DemoModal.d.ts +8 -0
  3. package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
  4. package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
  5. package/dist/cjs/components/molecules/Modal/ModalContext/index.d.ts +3 -0
  6. package/dist/cjs/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
  7. package/dist/cjs/components/molecules/Modal/index.d.ts +2 -0
  8. package/dist/cjs/components/molecules/Popover/Popover.presenter.d.ts +26 -0
  9. package/dist/cjs/components/molecules/Select/Option/Option.types.d.ts +6 -0
  10. package/dist/cjs/components/molecules/Select/Select.Context.d.ts +1 -1
  11. package/dist/cjs/components/molecules/Select/Select.d.ts +5 -5
  12. package/dist/cjs/components/molecules/Select/Select.presenter.d.ts +1 -0
  13. package/dist/cjs/components/molecules/Select/Select.types.d.ts +5 -0
  14. package/dist/cjs/components/molecules/Select/index.d.ts +2 -9
  15. package/dist/cjs/components/molecules/index.d.ts +2 -0
  16. package/dist/cjs/components/utils/accessibilityUtils.d.ts +41 -0
  17. package/dist/cjs/components/utils/index.d.ts +2 -0
  18. package/dist/cjs/library.css +13 -0
  19. package/dist/cjs/library.js +2 -2
  20. package/dist/cjs/library.js.map +1 -1
  21. package/dist/esm/components/molecules/Modal/DemoModal.d.ts +8 -0
  22. package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
  23. package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
  24. package/dist/esm/components/molecules/Modal/ModalContext/index.d.ts +3 -0
  25. package/dist/esm/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
  26. package/dist/esm/components/molecules/Modal/index.d.ts +2 -0
  27. package/dist/esm/components/molecules/Popover/Popover.presenter.d.ts +26 -0
  28. package/dist/esm/components/molecules/Select/Option/Option.types.d.ts +6 -0
  29. package/dist/esm/components/molecules/Select/Select.Context.d.ts +1 -1
  30. package/dist/esm/components/molecules/Select/Select.d.ts +5 -5
  31. package/dist/esm/components/molecules/Select/Select.presenter.d.ts +1 -0
  32. package/dist/esm/components/molecules/Select/Select.types.d.ts +5 -0
  33. package/dist/esm/components/molecules/Select/index.d.ts +2 -9
  34. package/dist/esm/components/molecules/index.d.ts +2 -0
  35. package/dist/esm/components/utils/accessibilityUtils.d.ts +41 -0
  36. package/dist/esm/components/utils/index.d.ts +2 -0
  37. package/dist/esm/library.css +13 -0
  38. package/dist/esm/library.js +3 -3
  39. package/dist/esm/library.js.map +1 -1
  40. package/dist/index.d.ts +156 -12
  41. package/docs/README.md +264 -0
  42. package/docs/components/atoms/ActionImage.md +119 -0
  43. package/docs/components/atoms/Button.md +197 -0
  44. package/docs/components/atoms/Checkbox.md +299 -0
  45. package/docs/components/atoms/CheckboxItem.md +314 -0
  46. package/docs/components/atoms/Chip.md +380 -0
  47. package/docs/components/atoms/CustomToggle.md +270 -0
  48. package/docs/components/atoms/Icon.md +365 -0
  49. package/docs/components/atoms/IconButton.md +407 -0
  50. package/docs/components/atoms/Image.md +448 -0
  51. package/docs/components/atoms/Input.md +430 -0
  52. package/docs/components/atoms/ListItem.md +502 -0
  53. package/docs/components/atoms/Password.md +472 -0
  54. package/docs/components/atoms/RadioButton.md +614 -0
  55. package/docs/components/atoms/RadioButtonItem.md +588 -0
  56. package/docs/components/atoms/ResponsiveComponent.md +612 -0
  57. package/docs/components/atoms/SelectListItem.md +609 -0
  58. package/docs/components/atoms/Slider.md +605 -0
  59. package/docs/components/atoms/Spinner.md +605 -0
  60. package/docs/components/atoms/Text.md +463 -0
  61. package/docs/components/atoms/TextArea.md +670 -0
  62. package/docs/components/atoms/ToastNotification.md +668 -0
  63. package/docs/components/atoms/Toggle.md +737 -0
  64. package/docs/components/atoms/ToggleButton.md +751 -0
  65. package/docs/components/atoms/Tooltip.md +391 -0
  66. package/docs/components/molecules/Accordion.md +440 -0
  67. package/docs/components/molecules/AccordionGroup.md +547 -0
  68. package/docs/components/molecules/ActionCard.md +546 -0
  69. package/docs/components/molecules/Breadcrumb.md +403 -0
  70. package/docs/components/molecules/Breadcrumbs.md +485 -0
  71. package/docs/components/molecules/ButtonGroup.md +383 -0
  72. package/docs/components/molecules/Card.md +298 -0
  73. package/docs/components/molecules/ChipInput.md +646 -0
  74. package/docs/components/molecules/ContextMenu.md +768 -0
  75. package/docs/components/molecules/CustomTimeSelector.md +116 -0
  76. package/docs/components/molecules/DatePicker.md +516 -0
  77. package/docs/components/molecules/DateTimeSelector.md +166 -0
  78. package/docs/components/molecules/FormField.md +312 -0
  79. package/docs/components/molecules/Grid.md +577 -0
  80. package/docs/components/molecules/GridItem.md +834 -0
  81. package/docs/components/molecules/GridList.md +244 -0
  82. package/docs/components/molecules/List.md +485 -0
  83. package/docs/components/molecules/Modal.md +470 -0
  84. package/docs/components/molecules/ModalFooter.md +702 -0
  85. package/docs/components/molecules/ModalHeader.md +756 -0
  86. package/docs/components/molecules/ModalProvider.md +205 -0
  87. package/docs/components/molecules/Nav.md +530 -0
  88. package/docs/components/molecules/NavItem.md +572 -0
  89. package/docs/components/molecules/NavLink.md +499 -0
  90. package/docs/components/molecules/Option.md +521 -0
  91. package/docs/components/molecules/Pagination.md +592 -0
  92. package/docs/components/molecules/PaginationNumberField.md +722 -0
  93. package/docs/components/molecules/Popover.md +516 -0
  94. package/docs/components/molecules/ProgressBar.md +624 -0
  95. package/docs/components/molecules/RadioGroup.md +831 -0
  96. package/docs/components/molecules/RepeaterList.md +185 -0
  97. package/docs/components/molecules/Select.md +402 -0
  98. package/docs/components/molecules/SortableTrigger.md +82 -0
  99. package/docs/components/molecules/useModal.md +379 -0
  100. package/docs/components/organisms/Dropzone.md +346 -0
  101. package/docs/components/organisms/DropzoneClear.md +135 -0
  102. package/docs/components/organisms/DropzoneContent.md +216 -0
  103. package/docs/components/organisms/DropzoneFilename.md +191 -0
  104. package/docs/components/organisms/DropzoneSupportedFormats.md +184 -0
  105. package/docs/components/organisms/DropzoneTrigger.md +209 -0
  106. package/docs/components/organisms/Form.md +533 -0
  107. package/docs/components/organisms/SlideOutPanel.md +662 -0
  108. package/docs/components/organisms/TabContent.md +902 -0
  109. package/docs/components/organisms/TabItem.md +1091 -0
  110. package/docs/components/organisms/Table.md +611 -0
  111. package/docs/components/organisms/TableBody.md +679 -0
  112. package/docs/components/organisms/TableCell.md +482 -0
  113. package/docs/components/organisms/TableHeader.md +513 -0
  114. package/docs/components/organisms/TableHeaderCell.md +661 -0
  115. package/docs/components/organisms/TableRow.md +715 -0
  116. package/docs/components/organisms/Tabs.md +1330 -0
  117. package/docs/components/utils/ConditionalView.md +568 -0
  118. package/docs/components/utils/RenderStateView.md +726 -0
  119. package/docs/components/utils/WrapTextNodes.md +614 -0
  120. package/package.json +3 -2
@@ -0,0 +1,624 @@
1
+ # ProgressBar
2
+
3
+ ## Description
4
+
5
+ A progress indicator component that visually represents the completion status of a task or process. Provides customizable value ranges, label display options, and styling controls for creating loading indicators, form progress, file uploads, and multi-step workflow progress visualization.
6
+
7
+ ## Aliases
8
+
9
+ - ProgressBar
10
+ - ProgressIndicator
11
+ - LoadingBar
12
+ - ProgressMeter
13
+ - StatusBar
14
+ - Gauge
15
+
16
+ ## Props Breakdown
17
+
18
+ **Extends:** Standalone interface (no HTML element inheritance)
19
+
20
+ | Prop | Type | Default | Required | Description |
21
+ |------|------|---------|----------|-------------|
22
+ | `value` | `number` | - | Yes | Current progress value |
23
+ | `min` | `number` | `0` | No | Minimum value of the progress bar |
24
+ | `max` | `number` | `100` | No | Maximum value of the progress bar |
25
+ | `showLabel` | `'Percentage' \| 'Text'` | - | No | Determines if and how the label is displayed |
26
+ | `label` | `ReactNode` | - | No | Custom label displayed when showLabel is 'Text' |
27
+ | `className` | `string` | - | No | Additional CSS class names |
28
+
29
+ ## Examples
30
+
31
+ ### Basic Usage
32
+ ```tsx
33
+ import { ProgressBar } from '@delightui/components';
34
+
35
+ function BasicExample() {
36
+ const [progress, setProgress] = useState(0);
37
+
38
+ useEffect(() => {
39
+ const timer = setInterval(() => {
40
+ setProgress(prev => {
41
+ if (prev >= 100) return 0;
42
+ return prev + 10;
43
+ });
44
+ }, 500);
45
+
46
+ return () => clearInterval(timer);
47
+ }, []);
48
+
49
+ return (
50
+ <div className="progress-demo">
51
+ <ProgressBar value={progress} />
52
+ </div>
53
+ );
54
+ }
55
+ ```
56
+
57
+ ### Progress with Percentage Label
58
+ ```tsx
59
+ function PercentageLabelExample() {
60
+ const [uploadProgress, setUploadProgress] = useState(0);
61
+
62
+ const simulateUpload = () => {
63
+ setUploadProgress(0);
64
+ const timer = setInterval(() => {
65
+ setUploadProgress(prev => {
66
+ if (prev >= 100) {
67
+ clearInterval(timer);
68
+ return 100;
69
+ }
70
+ return prev + Math.random() * 15;
71
+ });
72
+ }, 200);
73
+ };
74
+
75
+ return (
76
+ <div className="upload-progress">
77
+ <Text type="Heading6">File Upload Progress</Text>
78
+
79
+ <ProgressBar
80
+ value={uploadProgress}
81
+ showLabel="Percentage"
82
+ />
83
+
84
+ <div className="upload-actions">
85
+ <Button onClick={simulateUpload}>
86
+ Start Upload
87
+ </Button>
88
+
89
+ {uploadProgress === 100 && (
90
+ <Text type="BodySmall" className="success">
91
+ Upload Complete!
92
+ </Text>
93
+ )}
94
+ </div>
95
+ </div>
96
+ );
97
+ }
98
+ ```
99
+
100
+ ### Custom Text Label
101
+ ```tsx
102
+ function CustomLabelExample() {
103
+ const [taskProgress, setTaskProgress] = useState(3);
104
+ const totalTasks = 8;
105
+
106
+ const nextTask = () => {
107
+ if (taskProgress < totalTasks) {
108
+ setTaskProgress(prev => prev + 1);
109
+ }
110
+ };
111
+
112
+ const resetTasks = () => {
113
+ setTaskProgress(0);
114
+ };
115
+
116
+ const progressValue = (taskProgress / totalTasks) * 100;
117
+
118
+ return (
119
+ <div className="task-progress">
120
+ <Text type="Heading6">Project Tasks</Text>
121
+
122
+ <ProgressBar
123
+ value={progressValue}
124
+ showLabel="Text"
125
+ label={`${taskProgress} of ${totalTasks} tasks completed`}
126
+ />
127
+
128
+ <div className="task-actions">
129
+ <Button
130
+ onClick={nextTask}
131
+ disabled={taskProgress >= totalTasks}
132
+ >
133
+ Complete Task
134
+ </Button>
135
+ <Button type="Outlined" onClick={resetTasks}>
136
+ Reset
137
+ </Button>
138
+ </div>
139
+
140
+ {taskProgress === totalTasks && (
141
+ <div className="completion-message">
142
+ <Icon icon="CheckCircle" className="success-icon" />
143
+ <Text>All tasks completed!</Text>
144
+ </div>
145
+ )}
146
+ </div>
147
+ );
148
+ }
149
+ ```
150
+
151
+ ### Custom Range Progress
152
+ ```tsx
153
+ function CustomRangeExample() {
154
+ const [score, setScore] = useState(750);
155
+ const minScore = 300;
156
+ const maxScore = 850;
157
+
158
+ const increaseScore = () => {
159
+ setScore(prev => Math.min(prev + 50, maxScore));
160
+ };
161
+
162
+ const decreaseScore = () => {
163
+ setScore(prev => Math.max(prev - 50, minScore));
164
+ };
165
+
166
+ const getScoreRating = (score) => {
167
+ if (score < 500) return { rating: 'Poor', color: 'red' };
168
+ if (score < 650) return { rating: 'Fair', color: 'orange' };
169
+ if (score < 750) return { rating: 'Good', color: 'blue' };
170
+ return { rating: 'Excellent', color: 'green' };
171
+ };
172
+
173
+ const { rating, color } = getScoreRating(score);
174
+
175
+ return (
176
+ <div className="credit-score">
177
+ <Text type="Heading6">Credit Score</Text>
178
+
179
+ <div className="score-display">
180
+ <Text type="Heading3">{score}</Text>
181
+ <Text type="BodySmall" style={{ color }}>
182
+ {rating}
183
+ </Text>
184
+ </div>
185
+
186
+ <ProgressBar
187
+ value={score}
188
+ min={minScore}
189
+ max={maxScore}
190
+ showLabel="Text"
191
+ label={`Score: ${score} / ${maxScore}`}
192
+ className={`score-${color}`}
193
+ />
194
+
195
+ <div className="score-range">
196
+ <Text type="Caption">Poor</Text>
197
+ <Text type="Caption">Fair</Text>
198
+ <Text type="Caption">Good</Text>
199
+ <Text type="Caption">Excellent</Text>
200
+ </div>
201
+
202
+ <div className="score-actions">
203
+ <Button
204
+ type="Outlined"
205
+ onClick={decreaseScore}
206
+ disabled={score <= minScore}
207
+ >
208
+ Decrease
209
+ </Button>
210
+ <Button
211
+ onClick={increaseScore}
212
+ disabled={score >= maxScore}
213
+ >
214
+ Increase
215
+ </Button>
216
+ </div>
217
+ </div>
218
+ );
219
+ }
220
+ ```
221
+
222
+ ### Multi-step Form Progress
223
+ ```tsx
224
+ function FormProgressExample() {
225
+ const [currentStep, setCurrentStep] = useState(1);
226
+ const totalSteps = 4;
227
+
228
+ const steps = [
229
+ { id: 1, name: 'Personal Info', completed: false },
230
+ { id: 2, name: 'Contact Details', completed: false },
231
+ { id: 3, name: 'Preferences', completed: false },
232
+ { id: 4, name: 'Review', completed: false }
233
+ ];
234
+
235
+ const [stepStates, setStepStates] = useState(steps);
236
+
237
+ const nextStep = () => {
238
+ if (currentStep < totalSteps) {
239
+ setStepStates(prev =>
240
+ prev.map(step =>
241
+ step.id === currentStep ? { ...step, completed: true } : step
242
+ )
243
+ );
244
+ setCurrentStep(prev => prev + 1);
245
+ }
246
+ };
247
+
248
+ const prevStep = () => {
249
+ if (currentStep > 1) {
250
+ setCurrentStep(prev => prev - 1);
251
+ }
252
+ };
253
+
254
+ const progressValue = ((currentStep - 1) / (totalSteps - 1)) * 100;
255
+ const completedSteps = stepStates.filter(step => step.completed).length;
256
+
257
+ return (
258
+ <div className="form-wizard">
259
+ <Text type="Heading5">Account Setup</Text>
260
+
261
+ <div className="progress-section">
262
+ <ProgressBar
263
+ value={progressValue}
264
+ showLabel="Text"
265
+ label={`Step ${currentStep} of ${totalSteps}`}
266
+ />
267
+
268
+ <div className="step-indicators">
269
+ {stepStates.map(step => (
270
+ <div
271
+ key={step.id}
272
+ className={`step-indicator ${
273
+ step.id === currentStep ? 'current' :
274
+ step.completed ? 'completed' : 'pending'
275
+ }`}
276
+ >
277
+ {step.completed ? (
278
+ <Icon icon="Check" />
279
+ ) : (
280
+ <Text type="Caption">{step.id}</Text>
281
+ )}
282
+ <Text type="BodySmall">{step.name}</Text>
283
+ </div>
284
+ ))}
285
+ </div>
286
+ </div>
287
+
288
+ <div className="form-content">
289
+ <Text type="Heading6">
290
+ {stepStates.find(s => s.id === currentStep)?.name}
291
+ </Text>
292
+ <Text>Form content for step {currentStep} goes here...</Text>
293
+ </div>
294
+
295
+ <div className="form-navigation">
296
+ <Button
297
+ type="Outlined"
298
+ onClick={prevStep}
299
+ disabled={currentStep === 1}
300
+ >
301
+ Previous
302
+ </Button>
303
+
304
+ <div className="step-info">
305
+ <Text type="BodySmall">
306
+ {completedSteps} of {totalSteps} steps completed
307
+ </Text>
308
+ </div>
309
+
310
+ <Button
311
+ onClick={nextStep}
312
+ disabled={currentStep === totalSteps}
313
+ >
314
+ {currentStep === totalSteps ? 'Finish' : 'Next'}
315
+ </Button>
316
+ </div>
317
+ </div>
318
+ );
319
+ }
320
+ ```
321
+
322
+ ### Animated Loading States
323
+ ```tsx
324
+ function LoadingStatesExample() {
325
+ const [loadingState, setLoadingState] = useState('idle');
326
+ const [progress, setProgress] = useState(0);
327
+
328
+ const loadingStates = {
329
+ idle: { label: 'Ready to start', value: 0 },
330
+ connecting: { label: 'Connecting to server...', value: 25 },
331
+ downloading: { label: 'Downloading data...', value: 50 },
332
+ processing: { label: 'Processing files...', value: 75 },
333
+ complete: { label: 'Complete!', value: 100 }
334
+ };
335
+
336
+ const startLoading = async () => {
337
+ const states = Object.keys(loadingStates);
338
+
339
+ for (let i = 1; i < states.length; i++) {
340
+ setLoadingState(states[i]);
341
+ setProgress(loadingStates[states[i]].value);
342
+
343
+ // Simulate loading time
344
+ await new Promise(resolve => setTimeout(resolve, 1000));
345
+ }
346
+
347
+ // Reset after completion
348
+ setTimeout(() => {
349
+ setLoadingState('idle');
350
+ setProgress(0);
351
+ }, 2000);
352
+ };
353
+
354
+ const currentState = loadingStates[loadingState];
355
+
356
+ return (
357
+ <div className="loading-demo">
358
+ <Text type="Heading6">Loading Simulation</Text>
359
+
360
+ <div className="loading-progress">
361
+ <ProgressBar
362
+ value={progress}
363
+ showLabel="Text"
364
+ label={currentState.label}
365
+ className={`loading-${loadingState}`}
366
+ />
367
+
368
+ <div className="loading-status">
369
+ {loadingState !== 'idle' && loadingState !== 'complete' && (
370
+ <Spinner size="Small" />
371
+ )}
372
+
373
+ {loadingState === 'complete' && (
374
+ <Icon icon="CheckCircle" className="success-icon" />
375
+ )}
376
+ </div>
377
+ </div>
378
+
379
+ <Button
380
+ onClick={startLoading}
381
+ disabled={loadingState !== 'idle' && loadingState !== 'complete'}
382
+ >
383
+ {loadingState === 'idle' ? 'Start Loading' : 'Loading...'}
384
+ </Button>
385
+ </div>
386
+ );
387
+ }
388
+ ```
389
+
390
+ ### Skill Level Indicator
391
+ ```tsx
392
+ function SkillIndicatorExample() {
393
+ const skills = [
394
+ { name: 'JavaScript', level: 90 },
395
+ { name: 'React', level: 85 },
396
+ { name: 'TypeScript', level: 75 },
397
+ { name: 'Node.js', level: 70 },
398
+ { name: 'Python', level: 60 }
399
+ ];
400
+
401
+ const getSkillLevel = (level) => {
402
+ if (level >= 90) return 'Expert';
403
+ if (level >= 75) return 'Advanced';
404
+ if (level >= 60) return 'Intermediate';
405
+ if (level >= 40) return 'Beginner';
406
+ return 'Learning';
407
+ };
408
+
409
+ return (
410
+ <div className="skills-chart">
411
+ <Text type="Heading6">Technical Skills</Text>
412
+
413
+ <div className="skills-list">
414
+ {skills.map((skill, index) => (
415
+ <div key={skill.name} className="skill-item">
416
+ <div className="skill-header">
417
+ <Text type="BodyMedium">{skill.name}</Text>
418
+ <Text type="BodySmall" className="skill-level">
419
+ {getSkillLevel(skill.level)}
420
+ </Text>
421
+ </div>
422
+
423
+ <ProgressBar
424
+ value={skill.level}
425
+ showLabel="Percentage"
426
+ className={`skill-progress skill-${Math.floor(skill.level / 20)}`}
427
+ />
428
+ </div>
429
+ ))}
430
+ </div>
431
+
432
+ <div className="skills-legend">
433
+ <div className="legend-item">
434
+ <div className="legend-color expert" />
435
+ <Text type="Caption">Expert (90%+)</Text>
436
+ </div>
437
+ <div className="legend-item">
438
+ <div className="legend-color advanced" />
439
+ <Text type="Caption">Advanced (75-89%)</Text>
440
+ </div>
441
+ <div className="legend-item">
442
+ <div className="legend-color intermediate" />
443
+ <Text type="Caption">Intermediate (60-74%)</Text>
444
+ </div>
445
+ </div>
446
+ </div>
447
+ );
448
+ }
449
+ ```
450
+
451
+ ### Storage Usage Indicator
452
+ ```tsx
453
+ function StorageUsageExample() {
454
+ const [storageData, setStorageData] = useState({
455
+ used: 45.6,
456
+ total: 100,
457
+ breakdown: {
458
+ documents: 15.2,
459
+ images: 18.4,
460
+ videos: 8.3,
461
+ other: 3.7
462
+ }
463
+ });
464
+
465
+ const usagePercent = (storageData.used / storageData.total) * 100;
466
+ const freeSpace = storageData.total - storageData.used;
467
+
468
+ const getUsageStatus = (percent) => {
469
+ if (percent >= 90) return { status: 'Critical', color: 'red' };
470
+ if (percent >= 75) return { status: 'High', color: 'orange' };
471
+ if (percent >= 50) return { status: 'Medium', color: 'blue' };
472
+ return { status: 'Low', color: 'green' };
473
+ };
474
+
475
+ const { status, color } = getUsageStatus(usagePercent);
476
+
477
+ return (
478
+ <div className="storage-usage">
479
+ <Text type="Heading6">Cloud Storage</Text>
480
+
481
+ <div className="storage-overview">
482
+ <div className="storage-stats">
483
+ <Text type="Heading4">{storageData.used} GB</Text>
484
+ <Text type="BodySmall">of {storageData.total} GB used</Text>
485
+ </div>
486
+
487
+ <div className="storage-status">
488
+ <Chip
489
+ size="Small"
490
+ style={color === 'green' ? 'Success' :
491
+ color === 'blue' ? 'Primary' :
492
+ color === 'orange' ? 'Warning' : 'Danger'}
493
+ >
494
+ {status} Usage
495
+ </Chip>
496
+ </div>
497
+ </div>
498
+
499
+ <ProgressBar
500
+ value={usagePercent}
501
+ showLabel="Text"
502
+ label={`${freeSpace.toFixed(1)} GB free space remaining`}
503
+ className={`storage-progress ${color}`}
504
+ />
505
+
506
+ <div className="storage-breakdown">
507
+ <Text type="BodyMedium">Storage Breakdown</Text>
508
+
509
+ {Object.entries(storageData.breakdown).map(([type, size]) => (
510
+ <div key={type} className="breakdown-item">
511
+ <div className="breakdown-info">
512
+ <Text type="BodySmall">{type.charAt(0).toUpperCase() + type.slice(1)}</Text>
513
+ <Text type="BodySmall">{size} GB</Text>
514
+ </div>
515
+
516
+ <ProgressBar
517
+ value={(size / storageData.total) * 100}
518
+ className={`breakdown-progress ${type}`}
519
+ />
520
+ </div>
521
+ ))}
522
+ </div>
523
+
524
+ <div className="storage-actions">
525
+ <Button type="Outlined" size="Small">
526
+ Manage Storage
527
+ </Button>
528
+ <Button size="Small">
529
+ Upgrade Plan
530
+ </Button>
531
+ </div>
532
+ </div>
533
+ );
534
+ }
535
+ ```
536
+
537
+ ### Fitness Goals Progress
538
+ ```tsx
539
+ function FitnessProgressExample() {
540
+ const [fitnessGoals, setFitnessGoals] = useState({
541
+ steps: { current: 8234, target: 10000, unit: 'steps' },
542
+ calories: { current: 1850, target: 2200, unit: 'cal' },
543
+ water: { current: 6, target: 8, unit: 'glasses' },
544
+ sleep: { current: 7.5, target: 8, unit: 'hours' }
545
+ });
546
+
547
+ const updateGoal = (goalType, increment) => {
548
+ setFitnessGoals(prev => ({
549
+ ...prev,
550
+ [goalType]: {
551
+ ...prev[goalType],
552
+ current: Math.max(0, prev[goalType].current + increment)
553
+ }
554
+ }));
555
+ };
556
+
557
+ return (
558
+ <div className="fitness-dashboard">
559
+ <Text type="Heading6">Today's Goals</Text>
560
+
561
+ <div className="goals-grid">
562
+ {Object.entries(fitnessGoals).map(([goalType, goal]) => {
563
+ const percentage = Math.min((goal.current / goal.target) * 100, 100);
564
+ const isCompleted = goal.current >= goal.target;
565
+
566
+ return (
567
+ <div key={goalType} className="goal-card">
568
+ <div className="goal-header">
569
+ <Text type="BodyMedium">
570
+ {goalType.charAt(0).toUpperCase() + goalType.slice(1)}
571
+ </Text>
572
+ {isCompleted && (
573
+ <Icon icon="CheckCircle" className="completed-icon" />
574
+ )}
575
+ </div>
576
+
577
+ <div className="goal-stats">
578
+ <Text type="Heading5">
579
+ {goal.current.toLocaleString()}
580
+ </Text>
581
+ <Text type="BodySmall">
582
+ / {goal.target.toLocaleString()} {goal.unit}
583
+ </Text>
584
+ </div>
585
+
586
+ <ProgressBar
587
+ value={percentage}
588
+ showLabel="Percentage"
589
+ className={`goal-progress ${isCompleted ? 'completed' : ''}`}
590
+ />
591
+
592
+ <div className="goal-actions">
593
+ <Button
594
+ size="Small"
595
+ type="Ghost"
596
+ onClick={() => updateGoal(goalType, -100)}
597
+ >
598
+ -
599
+ </Button>
600
+ <Button
601
+ size="Small"
602
+ type="Ghost"
603
+ onClick={() => updateGoal(goalType, 100)}
604
+ >
605
+ +
606
+ </Button>
607
+ </div>
608
+ </div>
609
+ );
610
+ })}
611
+ </div>
612
+
613
+ <div className="daily-summary">
614
+ <Text type="BodyMedium">Daily Summary</Text>
615
+ <Text type="BodySmall">
616
+ {Object.values(fitnessGoals).filter(goal =>
617
+ goal.current >= goal.target
618
+ ).length} of {Object.keys(fitnessGoals).length} goals completed
619
+ </Text>
620
+ </div>
621
+ </div>
622
+ );
623
+ }
624
+ ```