@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.
Files changed (102) 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/index.d.ts +2 -0
  9. package/dist/cjs/library.css +19 -6
  10. package/dist/cjs/library.js +3 -3
  11. package/dist/cjs/library.js.map +1 -1
  12. package/dist/esm/components/molecules/Modal/DemoModal.d.ts +8 -0
  13. package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
  14. package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
  15. package/dist/esm/components/molecules/Modal/ModalContext/index.d.ts +3 -0
  16. package/dist/esm/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
  17. package/dist/esm/components/molecules/Modal/index.d.ts +2 -0
  18. package/dist/esm/components/molecules/index.d.ts +2 -0
  19. package/dist/esm/library.css +19 -6
  20. package/dist/esm/library.js +3 -3
  21. package/dist/esm/library.js.map +1 -1
  22. package/dist/index.d.ts +108 -2
  23. package/docs/README.md +264 -0
  24. package/docs/components/atoms/ActionImage.md +119 -0
  25. package/docs/components/atoms/Button.md +197 -0
  26. package/docs/components/atoms/Checkbox.md +299 -0
  27. package/docs/components/atoms/CheckboxItem.md +314 -0
  28. package/docs/components/atoms/Chip.md +380 -0
  29. package/docs/components/atoms/CustomToggle.md +270 -0
  30. package/docs/components/atoms/Icon.md +365 -0
  31. package/docs/components/atoms/IconButton.md +407 -0
  32. package/docs/components/atoms/Image.md +448 -0
  33. package/docs/components/atoms/Input.md +430 -0
  34. package/docs/components/atoms/ListItem.md +502 -0
  35. package/docs/components/atoms/Password.md +472 -0
  36. package/docs/components/atoms/RadioButton.md +614 -0
  37. package/docs/components/atoms/RadioButtonItem.md +588 -0
  38. package/docs/components/atoms/ResponsiveComponent.md +612 -0
  39. package/docs/components/atoms/SelectListItem.md +609 -0
  40. package/docs/components/atoms/Slider.md +605 -0
  41. package/docs/components/atoms/Spinner.md +605 -0
  42. package/docs/components/atoms/Text.md +463 -0
  43. package/docs/components/atoms/TextArea.md +670 -0
  44. package/docs/components/atoms/ToastNotification.md +668 -0
  45. package/docs/components/atoms/Toggle.md +737 -0
  46. package/docs/components/atoms/ToggleButton.md +751 -0
  47. package/docs/components/atoms/Tooltip.md +391 -0
  48. package/docs/components/molecules/Accordion.md +440 -0
  49. package/docs/components/molecules/AccordionGroup.md +547 -0
  50. package/docs/components/molecules/ActionCard.md +546 -0
  51. package/docs/components/molecules/Breadcrumb.md +403 -0
  52. package/docs/components/molecules/Breadcrumbs.md +485 -0
  53. package/docs/components/molecules/ButtonGroup.md +383 -0
  54. package/docs/components/molecules/Card.md +298 -0
  55. package/docs/components/molecules/ChipInput.md +646 -0
  56. package/docs/components/molecules/ContextMenu.md +768 -0
  57. package/docs/components/molecules/CustomTimeSelector.md +116 -0
  58. package/docs/components/molecules/DatePicker.md +516 -0
  59. package/docs/components/molecules/DateTimeSelector.md +166 -0
  60. package/docs/components/molecules/FormField.md +312 -0
  61. package/docs/components/molecules/Grid.md +577 -0
  62. package/docs/components/molecules/GridItem.md +834 -0
  63. package/docs/components/molecules/GridList.md +244 -0
  64. package/docs/components/molecules/List.md +485 -0
  65. package/docs/components/molecules/Modal.md +470 -0
  66. package/docs/components/molecules/ModalFooter.md +702 -0
  67. package/docs/components/molecules/ModalHeader.md +756 -0
  68. package/docs/components/molecules/ModalProvider.md +205 -0
  69. package/docs/components/molecules/Nav.md +530 -0
  70. package/docs/components/molecules/NavItem.md +572 -0
  71. package/docs/components/molecules/NavLink.md +499 -0
  72. package/docs/components/molecules/Option.md +521 -0
  73. package/docs/components/molecules/Pagination.md +592 -0
  74. package/docs/components/molecules/PaginationNumberField.md +722 -0
  75. package/docs/components/molecules/Popover.md +516 -0
  76. package/docs/components/molecules/ProgressBar.md +624 -0
  77. package/docs/components/molecules/RadioGroup.md +831 -0
  78. package/docs/components/molecules/RepeaterList.md +185 -0
  79. package/docs/components/molecules/Select.md +402 -0
  80. package/docs/components/molecules/SortableTrigger.md +82 -0
  81. package/docs/components/molecules/useModal.md +379 -0
  82. package/docs/components/organisms/Dropzone.md +346 -0
  83. package/docs/components/organisms/DropzoneClear.md +135 -0
  84. package/docs/components/organisms/DropzoneContent.md +216 -0
  85. package/docs/components/organisms/DropzoneFilename.md +191 -0
  86. package/docs/components/organisms/DropzoneSupportedFormats.md +184 -0
  87. package/docs/components/organisms/DropzoneTrigger.md +209 -0
  88. package/docs/components/organisms/Form.md +533 -0
  89. package/docs/components/organisms/SlideOutPanel.md +662 -0
  90. package/docs/components/organisms/TabContent.md +902 -0
  91. package/docs/components/organisms/TabItem.md +1091 -0
  92. package/docs/components/organisms/Table.md +611 -0
  93. package/docs/components/organisms/TableBody.md +679 -0
  94. package/docs/components/organisms/TableCell.md +482 -0
  95. package/docs/components/organisms/TableHeader.md +513 -0
  96. package/docs/components/organisms/TableHeaderCell.md +661 -0
  97. package/docs/components/organisms/TableRow.md +715 -0
  98. package/docs/components/organisms/Tabs.md +1330 -0
  99. package/docs/components/utils/ConditionalView.md +568 -0
  100. package/docs/components/utils/RenderStateView.md +726 -0
  101. package/docs/components/utils/WrapTextNodes.md +614 -0
  102. package/package.json +3 -2
@@ -0,0 +1,751 @@
1
+ # ToggleButton
2
+
3
+ A button component that maintains a pressed/unpressed state, functioning as a toggle between two states. It combines the visual appearance of a button with the state behavior of a toggle, making it perfect for scenarios where you need a button-like interface for binary choices or mode switches.
4
+
5
+ ## Aliases
6
+
7
+ - ToggleButton
8
+ - PressButton
9
+ - StateButton
10
+
11
+ ## Props Breakdown
12
+
13
+ **Extends:** `ButtonProps` (which extends `HTMLAttributes<HTMLButtonElement>` (excluding `style`), excluding `type` and `actionType`) and `ControlledFormComponentProps<boolean>`
14
+
15
+ | Prop | Type | Default | Required | Description |
16
+ |------|------|---------|----------|-------------|
17
+ | `defaultChecked` | `boolean` | `undefined` | No | Default value for uncontrolled component |
18
+ | `children` | `ReactNode` | `undefined` | No | Content of the button |
19
+ | `className` | `string` | `undefined` | No | Additional className for the toggle |
20
+ | `initialValue` | `boolean` | `undefined` | No | The initial value for the field |
21
+ | `checked` | `boolean` | `undefined` | No | The initial value for the field |
22
+ | `value` | `boolean` | `undefined` | No | The current value of the form field |
23
+ | `onValueChange` | `(value: boolean) => void` | `undefined` | No | Callback function that is called when the field value changes |
24
+ | `disabled` | `boolean` | `false` | No | Whether the form field is disabled and cannot be interacted with |
25
+ | `required` | `boolean` | `false` | No | Whether the form field must have a value |
26
+ | `invalid` | `boolean` | `false` | No | Whether the form field's current value is invalid |
27
+ | `id` | `string` | `undefined` | No | Id for the form field |
28
+ | `appearance` | `'Default' \| 'Inverse'` | `'Default'` | No | Appearance of the button |
29
+ | `style` | `'Primary' \| 'Secondary' \| 'Destructive'` | `'Primary'` | No | Style of the button |
30
+ | `size` | `'Small' \| 'Medium' \| 'Large'` | `'Medium'` | No | Size of the button |
31
+ | `loading` | `boolean` | `false` | No | Indicates if the button is in a loading state |
32
+ | `leadingIcon` | `ReactNode` | `undefined` | No | Icon to be displayed before the button's content |
33
+ | `trailingIcon` | `ReactNode` | `undefined` | No | Icon to be displayed after the button's content |
34
+ | `onClick` | `(event?: MouseEvent<HTMLElement>) => void` | `undefined` | No | Click event handler for the button |
35
+
36
+ Plus all standard HTML button attributes (id, title, aria-*, data-*, etc.).
37
+
38
+ ## Examples
39
+
40
+ ### Basic ToggleButton
41
+
42
+ ```tsx
43
+ import { ToggleButton } from '@delightui/components';
44
+
45
+ function BasicToggleButtonExample() {
46
+ const [isPressed, setIsPressed] = useState(false);
47
+
48
+ return (
49
+ <div>
50
+ <p>Button state: {isPressed ? 'Pressed' : 'Not pressed'}</p>
51
+ <ToggleButton
52
+ value={isPressed}
53
+ onValueChange={setIsPressed}
54
+ >
55
+ Toggle Me
56
+ </ToggleButton>
57
+ </div>
58
+ );
59
+ }
60
+ ```
61
+
62
+ ### ToggleButton with Icons
63
+
64
+ ```tsx
65
+ import { ToggleButton, Icon } from '@delightui/components';
66
+
67
+ function IconToggleButtonExample() {
68
+ const [isFavorite, setIsFavorite] = useState(false);
69
+ const [isBookmarked, setIsBookmarked] = useState(false);
70
+ const [isLiked, setIsLiked] = useState(false);
71
+
72
+ return (
73
+ <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>
74
+ <ToggleButton
75
+ value={isFavorite}
76
+ onValueChange={setIsFavorite}
77
+ leadingIcon={<Icon name={isFavorite ? 'CheckFilled' : 'CheckOutlined'} />}
78
+ style={isFavorite ? 'Primary' : 'Secondary'}
79
+ >
80
+ {isFavorite ? 'Favorited' : 'Favorite'}
81
+ </ToggleButton>
82
+
83
+ <ToggleButton
84
+ value={isBookmarked}
85
+ onValueChange={setIsBookmarked}
86
+ leadingIcon={<Icon name={isBookmarked ? 'AddFilled' : 'AddOutlined'} />}
87
+ style={isBookmarked ? 'Primary' : 'Secondary'}
88
+ >
89
+ {isBookmarked ? 'Saved' : 'Save'}
90
+ </ToggleButton>
91
+
92
+ <ToggleButton
93
+ value={isLiked}
94
+ onValueChange={setIsLiked}
95
+ leadingIcon={<Icon name={isLiked ? 'CheckFilled' : 'CheckOutlined'} />}
96
+ style={isLiked ? 'Primary' : 'Secondary'}
97
+ size="Small"
98
+ >
99
+ {isLiked ? 'Liked' : 'Like'}
100
+ </ToggleButton>
101
+ </div>
102
+ );
103
+ }
104
+ ```
105
+
106
+ ### Different Sizes and Styles
107
+
108
+ ```tsx
109
+ import { ToggleButton } from '@delightui/components';
110
+
111
+ function SizedToggleButtonExample() {
112
+ const [states, setStates] = useState({
113
+ small: false,
114
+ medium: false,
115
+ large: false
116
+ });
117
+
118
+ const updateState = (key: string, value: boolean) => {
119
+ setStates(prev => ({ ...prev, [key]: value }));
120
+ };
121
+
122
+ return (
123
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
124
+ <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
125
+ <ToggleButton
126
+ value={states.small}
127
+ onValueChange={(value) => updateState('small', value)}
128
+ size="Small"
129
+ >
130
+ Small
131
+ </ToggleButton>
132
+
133
+ <ToggleButton
134
+ value={states.medium}
135
+ onValueChange={(value) => updateState('medium', value)}
136
+ size="Medium"
137
+ >
138
+ Medium
139
+ </ToggleButton>
140
+
141
+ <ToggleButton
142
+ value={states.large}
143
+ onValueChange={(value) => updateState('large', value)}
144
+ size="Large"
145
+ >
146
+ Large
147
+ </ToggleButton>
148
+ </div>
149
+
150
+ <div style={{ display: 'flex', gap: '8px' }}>
151
+ <ToggleButton
152
+ value={false}
153
+ style="Primary"
154
+ >
155
+ Primary
156
+ </ToggleButton>
157
+
158
+ <ToggleButton
159
+ value={false}
160
+ style="Secondary"
161
+ >
162
+ Secondary
163
+ </ToggleButton>
164
+
165
+ <ToggleButton
166
+ value={false}
167
+ style="Destructive"
168
+ >
169
+ Destructive
170
+ </ToggleButton>
171
+ </div>
172
+ </div>
173
+ );
174
+ }
175
+ ```
176
+
177
+ ### Toolbar with ToggleButtons
178
+
179
+ ```tsx
180
+ import { ToggleButton, Icon } from '@delightui/components';
181
+
182
+ function ToolbarExample() {
183
+ const [formatting, setFormatting] = useState({
184
+ bold: false,
185
+ italic: false,
186
+ underline: false,
187
+ alignLeft: true,
188
+ alignCenter: false,
189
+ alignRight: false
190
+ });
191
+
192
+ const updateFormatting = (key: string, value: boolean) => {
193
+ if (key.startsWith('align')) {
194
+ // Only one alignment can be active
195
+ setFormatting(prev => ({
196
+ ...prev,
197
+ alignLeft: key === 'alignLeft' ? value : false,
198
+ alignCenter: key === 'alignCenter' ? value : false,
199
+ alignRight: key === 'alignRight' ? value : false
200
+ }));
201
+ } else {
202
+ setFormatting(prev => ({ ...prev, [key]: value }));
203
+ }
204
+ };
205
+
206
+ return (
207
+ <div style={{
208
+ display: 'flex',
209
+ gap: '4px',
210
+ padding: '8px',
211
+ border: '1px solid #ccc',
212
+ borderRadius: '8px',
213
+ backgroundColor: '#f8f9fa'
214
+ }}>
215
+ {/* Text formatting */}
216
+ <ToggleButton
217
+ value={formatting.bold}
218
+ onValueChange={(value) => updateFormatting('bold', value)}
219
+ size="Small"
220
+ leadingIcon={<Icon name="AddFilled" />}
221
+ title="Bold"
222
+ />
223
+
224
+ <ToggleButton
225
+ value={formatting.italic}
226
+ onValueChange={(value) => updateFormatting('italic', value)}
227
+ size="Small"
228
+ leadingIcon={<Icon name="InfoFilled" />}
229
+ title="Italic"
230
+ />
231
+
232
+ <ToggleButton
233
+ value={formatting.underline}
234
+ onValueChange={(value) => updateFormatting('underline', value)}
235
+ size="Small"
236
+ leadingIcon={<Icon name="AddFilled" />}
237
+ title="Underline"
238
+ />
239
+
240
+ {/* Separator */}
241
+ <div style={{ width: '1px', backgroundColor: '#ccc', margin: '0 4px' }} />
242
+
243
+ {/* Alignment */}
244
+ <ToggleButton
245
+ value={formatting.alignLeft}
246
+ onValueChange={(value) => updateFormatting('alignLeft', value)}
247
+ size="Small"
248
+ leadingIcon={<Icon name="AddFilled" />}
249
+ title="Align Left"
250
+ />
251
+
252
+ <ToggleButton
253
+ value={formatting.alignCenter}
254
+ onValueChange={(value) => updateFormatting('alignCenter', value)}
255
+ size="Small"
256
+ leadingIcon={<Icon name="AddFilled" />}
257
+ title="Align Center"
258
+ />
259
+
260
+ <ToggleButton
261
+ value={formatting.alignRight}
262
+ onValueChange={(value) => updateFormatting('alignRight', value)}
263
+ size="Small"
264
+ leadingIcon={<Icon name="AddFilled" />}
265
+ title="Align Right"
266
+ />
267
+ </div>
268
+ );
269
+ }
270
+ ```
271
+
272
+ ### Filter Buttons
273
+
274
+ ```tsx
275
+ import { ToggleButton, Text } from '@delightui/components';
276
+
277
+ function FilterButtonsExample() {
278
+ const [filters, setFilters] = useState({
279
+ all: true,
280
+ active: false,
281
+ completed: false,
282
+ overdue: false
283
+ });
284
+
285
+ const [tasks] = useState([
286
+ { id: 1, title: 'Complete project', status: 'active', dueDate: '2024-04-01' },
287
+ { id: 2, title: 'Review documents', status: 'completed', dueDate: '2024-03-28' },
288
+ { id: 3, title: 'Send report', status: 'overdue', dueDate: '2024-03-20' },
289
+ { id: 4, title: 'Team meeting', status: 'active', dueDate: '2024-04-05' }
290
+ ]);
291
+
292
+ const updateFilter = (key: string, value: boolean) => {
293
+ if (key === 'all' && value) {
294
+ setFilters({ all: true, active: false, completed: false, overdue: false });
295
+ } else {
296
+ const newFilters = { ...filters, [key]: value, all: false };
297
+ if (!Object.values(newFilters).some(Boolean)) {
298
+ newFilters.all = true;
299
+ }
300
+ setFilters(newFilters);
301
+ }
302
+ };
303
+
304
+ const getFilteredTasks = () => {
305
+ if (filters.all) return tasks;
306
+ return tasks.filter(task => {
307
+ if (filters.active && task.status === 'active') return true;
308
+ if (filters.completed && task.status === 'completed') return true;
309
+ if (filters.overdue && task.status === 'overdue') return true;
310
+ return false;
311
+ });
312
+ };
313
+
314
+ const filteredTasks = getFilteredTasks();
315
+
316
+ return (
317
+ <div>
318
+ <Text weight="bold" style={{ marginBottom: '16px' }}>
319
+ Task Filters
320
+ </Text>
321
+
322
+ <div style={{ display: 'flex', gap: '8px', marginBottom: '20px', flexWrap: 'wrap' }}>
323
+ <ToggleButton
324
+ value={filters.all}
325
+ onValueChange={(value) => updateFilter('all', value)}
326
+ size="Small"
327
+ >
328
+ All ({tasks.length})
329
+ </ToggleButton>
330
+
331
+ <ToggleButton
332
+ value={filters.active}
333
+ onValueChange={(value) => updateFilter('active', value)}
334
+ size="Small"
335
+ style="Primary"
336
+ >
337
+ Active ({tasks.filter(t => t.status === 'active').length})
338
+ </ToggleButton>
339
+
340
+ <ToggleButton
341
+ value={filters.completed}
342
+ onValueChange={(value) => updateFilter('completed', value)}
343
+ size="Small"
344
+ style="Secondary"
345
+ >
346
+ Completed ({tasks.filter(t => t.status === 'completed').length})
347
+ </ToggleButton>
348
+
349
+ <ToggleButton
350
+ value={filters.overdue}
351
+ onValueChange={(value) => updateFilter('overdue', value)}
352
+ size="Small"
353
+ style="Destructive"
354
+ >
355
+ Overdue ({tasks.filter(t => t.status === 'overdue').length})
356
+ </ToggleButton>
357
+ </div>
358
+
359
+ <div>
360
+ <Text weight="medium" style={{ marginBottom: '12px' }}>
361
+ Showing {filteredTasks.length} tasks
362
+ </Text>
363
+
364
+ {filteredTasks.map(task => (
365
+ <div key={task.id} style={{
366
+ padding: '12px',
367
+ border: '1px solid #eee',
368
+ borderRadius: '4px',
369
+ marginBottom: '8px'
370
+ }}>
371
+ <Text weight="medium">{task.title}</Text>
372
+ <Text size="small" color="secondary" style={{ display: 'block', marginTop: '4px' }}>
373
+ Status: {task.status} | Due: {task.dueDate}
374
+ </Text>
375
+ </div>
376
+ ))}
377
+ </div>
378
+ </div>
379
+ );
380
+ }
381
+ ```
382
+
383
+ ### View Mode Switcher
384
+
385
+ ```tsx
386
+ import { ToggleButton, Icon } from '@delightui/components';
387
+
388
+ function ViewModeSwitcherExample() {
389
+ const [viewMode, setViewMode] = useState('list');
390
+
391
+ const viewModes = [
392
+ { id: 'list', label: 'List View', icon: 'AddFilled' },
393
+ { id: 'grid', label: 'Grid View', icon: 'AddFilled' },
394
+ { id: 'card', label: 'Card View', icon: 'AddFilled' }
395
+ ];
396
+
397
+ const sampleData = [
398
+ { id: 1, title: 'Item 1', description: 'Description for item 1' },
399
+ { id: 2, title: 'Item 2', description: 'Description for item 2' },
400
+ { id: 3, title: 'Item 3', description: 'Description for item 3' },
401
+ { id: 4, title: 'Item 4', description: 'Description for item 4' }
402
+ ];
403
+
404
+ const renderContent = () => {
405
+ switch (viewMode) {
406
+ case 'list':
407
+ return (
408
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
409
+ {sampleData.map(item => (
410
+ <div key={item.id} style={{
411
+ display: 'flex',
412
+ alignItems: 'center',
413
+ gap: '12px',
414
+ padding: '12px',
415
+ border: '1px solid #eee',
416
+ borderRadius: '4px'
417
+ }}>
418
+ <Text weight="medium">{item.title}</Text>
419
+ <Text size="small" color="secondary">{item.description}</Text>
420
+ </div>
421
+ ))}
422
+ </div>
423
+ );
424
+
425
+ case 'grid':
426
+ return (
427
+ <div style={{
428
+ display: 'grid',
429
+ gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
430
+ gap: '16px'
431
+ }}>
432
+ {sampleData.map(item => (
433
+ <div key={item.id} style={{
434
+ padding: '16px',
435
+ border: '1px solid #eee',
436
+ borderRadius: '8px',
437
+ textAlign: 'center'
438
+ }}>
439
+ <Text weight="medium" style={{ display: 'block', marginBottom: '8px' }}>
440
+ {item.title}
441
+ </Text>
442
+ <Text size="small" color="secondary">{item.description}</Text>
443
+ </div>
444
+ ))}
445
+ </div>
446
+ );
447
+
448
+ case 'card':
449
+ return (
450
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
451
+ {sampleData.map(item => (
452
+ <div key={item.id} style={{
453
+ padding: '20px',
454
+ border: '1px solid #eee',
455
+ borderRadius: '12px',
456
+ backgroundColor: '#f8f9fa'
457
+ }}>
458
+ <Text weight="bold" size="large" style={{ display: 'block', marginBottom: '12px' }}>
459
+ {item.title}
460
+ </Text>
461
+ <Text>{item.description}</Text>
462
+ </div>
463
+ ))}
464
+ </div>
465
+ );
466
+
467
+ default:
468
+ return null;
469
+ }
470
+ };
471
+
472
+ return (
473
+ <div>
474
+ <div style={{
475
+ display: 'flex',
476
+ justifyContent: 'space-between',
477
+ alignItems: 'center',
478
+ marginBottom: '20px'
479
+ }}>
480
+ <Text weight="bold">Content View</Text>
481
+
482
+ <div style={{ display: 'flex', gap: '4px' }}>
483
+ {viewModes.map(mode => (
484
+ <ToggleButton
485
+ key={mode.id}
486
+ value={viewMode === mode.id}
487
+ onValueChange={(value) => value && setViewMode(mode.id)}
488
+ size="Small"
489
+ leadingIcon={<Icon name={mode.icon} />}
490
+ title={mode.label}
491
+ />
492
+ ))}
493
+ </div>
494
+ </div>
495
+
496
+ {renderContent()}
497
+ </div>
498
+ );
499
+ }
500
+ ```
501
+
502
+ ### Settings Toggle Buttons
503
+
504
+ ```tsx
505
+ import { ToggleButton, Icon, Text } from '@delightui/components';
506
+
507
+ function SettingsToggleButtonsExample() {
508
+ const [settings, setSettings] = useState({
509
+ notifications: true,
510
+ autoSave: false,
511
+ darkMode: false,
512
+ compactView: false
513
+ });
514
+
515
+ const updateSetting = (key: string, value: boolean) => {
516
+ setSettings(prev => ({ ...prev, [key]: value }));
517
+ };
518
+
519
+ return (
520
+ <div style={{ maxWidth: '400px' }}>
521
+ <Text weight="bold" size="large" style={{ marginBottom: '20px' }}>
522
+ Quick Settings
523
+ </Text>
524
+
525
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
526
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
527
+ <div>
528
+ <Text weight="medium">Notifications</Text>
529
+ <Text size="small" color="secondary" style={{ display: 'block', marginTop: '2px' }}>
530
+ Receive push notifications
531
+ </Text>
532
+ </div>
533
+ <ToggleButton
534
+ value={settings.notifications}
535
+ onValueChange={(value) => updateSetting('notifications', value)}
536
+ size="Small"
537
+ leadingIcon={<Icon name={settings.notifications ? 'InfoFilled' : 'InfoOutlined'} />}
538
+ >
539
+ {settings.notifications ? 'On' : 'Off'}
540
+ </ToggleButton>
541
+ </div>
542
+
543
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
544
+ <div>
545
+ <Text weight="medium">Auto Save</Text>
546
+ <Text size="small" color="secondary" style={{ display: 'block', marginTop: '2px' }}>
547
+ Automatically save your work
548
+ </Text>
549
+ </div>
550
+ <ToggleButton
551
+ value={settings.autoSave}
552
+ onValueChange={(value) => updateSetting('autoSave', value)}
553
+ size="Small"
554
+ leadingIcon={<Icon name={settings.autoSave ? 'CheckFilled' : 'CheckOutlined'} />}
555
+ >
556
+ {settings.autoSave ? 'Enabled' : 'Disabled'}
557
+ </ToggleButton>
558
+ </div>
559
+
560
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
561
+ <div>
562
+ <Text weight="medium">Dark Mode</Text>
563
+ <Text size="small" color="secondary" style={{ display: 'block', marginTop: '2px' }}>
564
+ Switch to dark theme
565
+ </Text>
566
+ </div>
567
+ <ToggleButton
568
+ value={settings.darkMode}
569
+ onValueChange={(value) => updateSetting('darkMode', value)}
570
+ size="Small"
571
+ style={settings.darkMode ? 'Primary' : 'Secondary'}
572
+ >
573
+ {settings.darkMode ? '🌙 Dark' : '☀️ Light'}
574
+ </ToggleButton>
575
+ </div>
576
+
577
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
578
+ <div>
579
+ <Text weight="medium">Compact View</Text>
580
+ <Text size="small" color="secondary" style={{ display: 'block', marginTop: '2px' }}>
581
+ Use smaller spacing
582
+ </Text>
583
+ </div>
584
+ <ToggleButton
585
+ value={settings.compactView}
586
+ onValueChange={(value) => updateSetting('compactView', value)}
587
+ size="Small"
588
+ leadingIcon={<Icon name={settings.compactView ? 'AddFilled' : 'AddOutlined'} />}
589
+ >
590
+ {settings.compactView ? 'Compact' : 'Normal'}
591
+ </ToggleButton>
592
+ </div>
593
+ </div>
594
+ </div>
595
+ );
596
+ }
597
+ ```
598
+
599
+ ### Form Integration
600
+
601
+ ```tsx
602
+ import { Form, FormField, ToggleButton, Button, Text } from '@delightui/components';
603
+
604
+ function FormToggleButtonExample() {
605
+ const handleSubmit = (data: any) => {
606
+ console.log('Form submitted:', data);
607
+ };
608
+
609
+ return (
610
+ <Form onSubmit={handleSubmit}>
611
+ <Text weight="bold" style={{ marginBottom: '16px' }}>
612
+ Subscription Preferences
613
+ </Text>
614
+
615
+ <FormField
616
+ name="newsletter"
617
+ label="Newsletter Subscription"
618
+ >
619
+ <ToggleButton
620
+ initialValue={true}
621
+ size="Small"
622
+ >
623
+ Subscribe to Newsletter
624
+ </ToggleButton>
625
+ </FormField>
626
+
627
+ <FormField
628
+ name="marketing"
629
+ label="Marketing Emails"
630
+ >
631
+ <ToggleButton
632
+ initialValue={false}
633
+ size="Small"
634
+ >
635
+ Receive Marketing Emails
636
+ </ToggleButton>
637
+ </FormField>
638
+
639
+ <FormField
640
+ name="urgent"
641
+ label="Urgent Notifications"
642
+ required
643
+ >
644
+ <ToggleButton
645
+ initialValue={true}
646
+ size="Small"
647
+ style="Primary"
648
+ >
649
+ Enable Urgent Notifications
650
+ </ToggleButton>
651
+ </FormField>
652
+
653
+ <Button type="submit">
654
+ Save Preferences
655
+ </Button>
656
+ </Form>
657
+ );
658
+ }
659
+ ```
660
+
661
+ ### Disabled States
662
+
663
+ ```tsx
664
+ import { ToggleButton, Icon } from '@delightui/components';
665
+
666
+ function DisabledToggleButtonExample() {
667
+ return (
668
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
669
+ <div style={{ display: 'flex', gap: '8px' }}>
670
+ <ToggleButton value={false}>
671
+ Normal (Off)
672
+ </ToggleButton>
673
+
674
+ <ToggleButton value={true}>
675
+ Normal (On)
676
+ </ToggleButton>
677
+ </div>
678
+
679
+ <div style={{ display: 'flex', gap: '8px' }}>
680
+ <ToggleButton value={false} disabled>
681
+ Disabled (Off)
682
+ </ToggleButton>
683
+
684
+ <ToggleButton value={true} disabled>
685
+ Disabled (On)
686
+ </ToggleButton>
687
+ </div>
688
+
689
+ <div style={{ display: 'flex', gap: '8px' }}>
690
+ <ToggleButton
691
+ value={false}
692
+ disabled
693
+ leadingIcon={<Icon name="ErrorOutlined" />}
694
+ >
695
+ Disabled with Icon
696
+ </ToggleButton>
697
+
698
+ <ToggleButton
699
+ value={true}
700
+ disabled
701
+ leadingIcon={<Icon name="CheckFilled" />}
702
+ >
703
+ Disabled Active
704
+ </ToggleButton>
705
+ </div>
706
+ </div>
707
+ );
708
+ }
709
+ ```
710
+
711
+ ### Loading State
712
+
713
+ ```tsx
714
+ import { ToggleButton, Spinner, Button } from '@delightui/components';
715
+
716
+ function LoadingToggleButtonExample() {
717
+ const [isLoading, setIsLoading] = useState(false);
718
+ const [isToggled, setIsToggled] = useState(false);
719
+
720
+ const handleToggle = async (value: boolean) => {
721
+ setIsLoading(true);
722
+ // Simulate API call
723
+ await new Promise(resolve => setTimeout(resolve, 2000));
724
+ setIsToggled(value);
725
+ setIsLoading(false);
726
+ };
727
+
728
+ return (
729
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
730
+ <ToggleButton
731
+ value={isToggled}
732
+ onValueChange={handleToggle}
733
+ loading={isLoading}
734
+ disabled={isLoading}
735
+ leadingIcon={isLoading ? <Spinner /> : undefined}
736
+ >
737
+ {isLoading ? 'Saving...' : isToggled ? 'Feature Enabled' : 'Enable Feature'}
738
+ </ToggleButton>
739
+
740
+ <Button
741
+ size="Small"
742
+ type="Outlined"
743
+ onClick={() => handleToggle(!isToggled)}
744
+ disabled={isLoading}
745
+ >
746
+ Toggle Programmatically
747
+ </Button>
748
+ </div>
749
+ );
750
+ }
751
+ ```