@delightui/components 0.1.105 → 0.1.107
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/README.md +104 -1
- package/dist/cjs/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/cjs/components/molecules/Modal/index.d.ts +2 -0
- package/dist/cjs/components/molecules/index.d.ts +2 -0
- package/dist/cjs/library.css +19 -6
- package/dist/cjs/library.js +3 -3
- package/dist/cjs/library.js.map +1 -1
- package/dist/esm/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/esm/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/esm/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/esm/components/molecules/Modal/index.d.ts +2 -0
- package/dist/esm/components/molecules/index.d.ts +2 -0
- package/dist/esm/library.css +19 -6
- package/dist/esm/library.js +3 -3
- package/dist/esm/library.js.map +1 -1
- package/dist/index.d.ts +108 -2
- package/docs/README.md +264 -0
- package/docs/components/atoms/ActionImage.md +119 -0
- package/docs/components/atoms/Button.md +197 -0
- package/docs/components/atoms/Checkbox.md +299 -0
- package/docs/components/atoms/CheckboxItem.md +314 -0
- package/docs/components/atoms/Chip.md +380 -0
- package/docs/components/atoms/CustomToggle.md +270 -0
- package/docs/components/atoms/Icon.md +365 -0
- package/docs/components/atoms/IconButton.md +407 -0
- package/docs/components/atoms/Image.md +448 -0
- package/docs/components/atoms/Input.md +430 -0
- package/docs/components/atoms/ListItem.md +502 -0
- package/docs/components/atoms/Password.md +472 -0
- package/docs/components/atoms/RadioButton.md +614 -0
- package/docs/components/atoms/RadioButtonItem.md +588 -0
- package/docs/components/atoms/ResponsiveComponent.md +612 -0
- package/docs/components/atoms/SelectListItem.md +609 -0
- package/docs/components/atoms/Slider.md +605 -0
- package/docs/components/atoms/Spinner.md +605 -0
- package/docs/components/atoms/Text.md +463 -0
- package/docs/components/atoms/TextArea.md +670 -0
- package/docs/components/atoms/ToastNotification.md +668 -0
- package/docs/components/atoms/Toggle.md +737 -0
- package/docs/components/atoms/ToggleButton.md +751 -0
- package/docs/components/atoms/Tooltip.md +391 -0
- package/docs/components/molecules/Accordion.md +440 -0
- package/docs/components/molecules/AccordionGroup.md +547 -0
- package/docs/components/molecules/ActionCard.md +546 -0
- package/docs/components/molecules/Breadcrumb.md +403 -0
- package/docs/components/molecules/Breadcrumbs.md +485 -0
- package/docs/components/molecules/ButtonGroup.md +383 -0
- package/docs/components/molecules/Card.md +298 -0
- package/docs/components/molecules/ChipInput.md +646 -0
- package/docs/components/molecules/ContextMenu.md +768 -0
- package/docs/components/molecules/CustomTimeSelector.md +116 -0
- package/docs/components/molecules/DatePicker.md +516 -0
- package/docs/components/molecules/DateTimeSelector.md +166 -0
- package/docs/components/molecules/FormField.md +312 -0
- package/docs/components/molecules/Grid.md +577 -0
- package/docs/components/molecules/GridItem.md +834 -0
- package/docs/components/molecules/GridList.md +244 -0
- package/docs/components/molecules/List.md +485 -0
- package/docs/components/molecules/Modal.md +470 -0
- package/docs/components/molecules/ModalFooter.md +702 -0
- package/docs/components/molecules/ModalHeader.md +756 -0
- package/docs/components/molecules/ModalProvider.md +205 -0
- package/docs/components/molecules/Nav.md +530 -0
- package/docs/components/molecules/NavItem.md +572 -0
- package/docs/components/molecules/NavLink.md +499 -0
- package/docs/components/molecules/Option.md +521 -0
- package/docs/components/molecules/Pagination.md +592 -0
- package/docs/components/molecules/PaginationNumberField.md +722 -0
- package/docs/components/molecules/Popover.md +516 -0
- package/docs/components/molecules/ProgressBar.md +624 -0
- package/docs/components/molecules/RadioGroup.md +831 -0
- package/docs/components/molecules/RepeaterList.md +185 -0
- package/docs/components/molecules/Select.md +402 -0
- package/docs/components/molecules/SortableTrigger.md +82 -0
- package/docs/components/molecules/useModal.md +379 -0
- package/docs/components/organisms/Dropzone.md +346 -0
- package/docs/components/organisms/DropzoneClear.md +135 -0
- package/docs/components/organisms/DropzoneContent.md +216 -0
- package/docs/components/organisms/DropzoneFilename.md +191 -0
- package/docs/components/organisms/DropzoneSupportedFormats.md +184 -0
- package/docs/components/organisms/DropzoneTrigger.md +209 -0
- package/docs/components/organisms/Form.md +533 -0
- package/docs/components/organisms/SlideOutPanel.md +662 -0
- package/docs/components/organisms/TabContent.md +902 -0
- package/docs/components/organisms/TabItem.md +1091 -0
- package/docs/components/organisms/Table.md +611 -0
- package/docs/components/organisms/TableBody.md +679 -0
- package/docs/components/organisms/TableCell.md +482 -0
- package/docs/components/organisms/TableHeader.md +513 -0
- package/docs/components/organisms/TableHeaderCell.md +661 -0
- package/docs/components/organisms/TableRow.md +715 -0
- package/docs/components/organisms/Tabs.md +1330 -0
- package/docs/components/utils/ConditionalView.md +568 -0
- package/docs/components/utils/RenderStateView.md +726 -0
- package/docs/components/utils/WrapTextNodes.md +614 -0
- 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
|
+
```
|