@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.
- 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/Popover/Popover.presenter.d.ts +26 -0
- package/dist/cjs/components/molecules/Select/Option/Option.types.d.ts +6 -0
- package/dist/cjs/components/molecules/Select/Select.Context.d.ts +1 -1
- package/dist/cjs/components/molecules/Select/Select.d.ts +5 -5
- package/dist/cjs/components/molecules/Select/Select.presenter.d.ts +1 -0
- package/dist/cjs/components/molecules/Select/Select.types.d.ts +5 -0
- package/dist/cjs/components/molecules/Select/index.d.ts +2 -9
- package/dist/cjs/components/molecules/index.d.ts +2 -0
- package/dist/cjs/components/utils/accessibilityUtils.d.ts +41 -0
- package/dist/cjs/components/utils/index.d.ts +2 -0
- package/dist/cjs/library.css +13 -0
- package/dist/cjs/library.js +2 -2
- 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/Popover/Popover.presenter.d.ts +26 -0
- package/dist/esm/components/molecules/Select/Option/Option.types.d.ts +6 -0
- package/dist/esm/components/molecules/Select/Select.Context.d.ts +1 -1
- package/dist/esm/components/molecules/Select/Select.d.ts +5 -5
- package/dist/esm/components/molecules/Select/Select.presenter.d.ts +1 -0
- package/dist/esm/components/molecules/Select/Select.types.d.ts +5 -0
- package/dist/esm/components/molecules/Select/index.d.ts +2 -9
- package/dist/esm/components/molecules/index.d.ts +2 -0
- package/dist/esm/components/utils/accessibilityUtils.d.ts +41 -0
- package/dist/esm/components/utils/index.d.ts +2 -0
- package/dist/esm/library.css +13 -0
- package/dist/esm/library.js +3 -3
- package/dist/esm/library.js.map +1 -1
- package/dist/index.d.ts +156 -12
- 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,1091 @@
|
|
|
1
|
+
# TabItem
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
A clickable tab item component that serves as the interactive element for switching between different tab content panels. TabItem extends Button functionality with specialized behavior for tab navigation, supporting various styles and states. It works in conjunction with TabContent to create comprehensive tabbed interfaces with proper accessibility and user experience.
|
|
6
|
+
|
|
7
|
+
## Aliases
|
|
8
|
+
|
|
9
|
+
- TabItem
|
|
10
|
+
- Tab Button
|
|
11
|
+
- Tab Header
|
|
12
|
+
- Tab Navigation
|
|
13
|
+
- Tab Selector
|
|
14
|
+
|
|
15
|
+
## Props Breakdown
|
|
16
|
+
|
|
17
|
+
**Extends:** `ButtonProps` (excluding `actionType`, `appearance`, `size`, `style`, `type`)
|
|
18
|
+
|
|
19
|
+
| Prop | Type | Default | Required | Description |
|
|
20
|
+
|------|------|---------|----------|-------------|
|
|
21
|
+
| `value` | `number \| string` | - | Yes | The tabs value used for determining which tab is selected |
|
|
22
|
+
| `defaultTab` | `boolean` | `false` | No | True means that this tab will be displayed initially |
|
|
23
|
+
| `style` | `TabItemStyleEnum` | `'Filled'` | No | The tab item style to apply ('Filled' \| 'Underlined') |
|
|
24
|
+
| `loading` | `boolean` | `false` | No | Indicates if the button is in a loading state |
|
|
25
|
+
| `disabled` | `boolean` | `false` | No | Specifies if the button is disabled |
|
|
26
|
+
| `leadingIcon` | `ReactNode` | - | No | Icon to be displayed before the button's content |
|
|
27
|
+
| `trailingIcon` | `ReactNode` | - | No | Icon to be displayed after the button's content |
|
|
28
|
+
| `onClick` | `(event?: MouseEvent<HTMLElement>) => void` | - | No | Click event handler for the button |
|
|
29
|
+
| `className` | `string` | - | No | Additional CSS class names |
|
|
30
|
+
| `children` | `ReactNode` | - | No | Content to display in the tab item |
|
|
31
|
+
|
|
32
|
+
Plus all standard HTML button attributes (except excluded ButtonProps).
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
### Basic Tab Items
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { Tabs, TabItem, TabContent } from '@delightui/components';
|
|
40
|
+
|
|
41
|
+
function BasicTabItemExample() {
|
|
42
|
+
return (
|
|
43
|
+
<Tabs>
|
|
44
|
+
<div style={{ display: 'flex', borderBottom: '1px solid #e0e0e0' }}>
|
|
45
|
+
<TabItem value="dashboard" defaultTab>
|
|
46
|
+
Dashboard
|
|
47
|
+
</TabItem>
|
|
48
|
+
<TabItem value="analytics">
|
|
49
|
+
Analytics
|
|
50
|
+
</TabItem>
|
|
51
|
+
<TabItem value="settings">
|
|
52
|
+
Settings
|
|
53
|
+
</TabItem>
|
|
54
|
+
<TabItem value="profile">
|
|
55
|
+
Profile
|
|
56
|
+
</TabItem>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<TabContent value="dashboard">
|
|
60
|
+
<div style={{ padding: '20px' }}>
|
|
61
|
+
<h2>Dashboard</h2>
|
|
62
|
+
<p>Welcome to your main dashboard with overview metrics and quick actions.</p>
|
|
63
|
+
</div>
|
|
64
|
+
</TabContent>
|
|
65
|
+
|
|
66
|
+
<TabContent value="analytics">
|
|
67
|
+
<div style={{ padding: '20px' }}>
|
|
68
|
+
<h2>Analytics</h2>
|
|
69
|
+
<p>View detailed analytics and performance metrics for your account.</p>
|
|
70
|
+
</div>
|
|
71
|
+
</TabContent>
|
|
72
|
+
|
|
73
|
+
<TabContent value="settings">
|
|
74
|
+
<div style={{ padding: '20px' }}>
|
|
75
|
+
<h2>Settings</h2>
|
|
76
|
+
<p>Configure your account preferences and application settings.</p>
|
|
77
|
+
</div>
|
|
78
|
+
</TabContent>
|
|
79
|
+
|
|
80
|
+
<TabContent value="profile">
|
|
81
|
+
<div style={{ padding: '20px' }}>
|
|
82
|
+
<h2>Profile</h2>
|
|
83
|
+
<p>Manage your personal information and account details.</p>
|
|
84
|
+
</div>
|
|
85
|
+
</TabContent>
|
|
86
|
+
</Tabs>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Tab Items with Icons
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import { Tabs, TabItem, TabContent, Icon } from '@delightui/components';
|
|
95
|
+
|
|
96
|
+
function IconTabItemExample() {
|
|
97
|
+
return (
|
|
98
|
+
<Tabs style="Underlined">
|
|
99
|
+
<div style={{ display: 'flex' }}>
|
|
100
|
+
<TabItem
|
|
101
|
+
value="home"
|
|
102
|
+
defaultTab
|
|
103
|
+
leadingIcon={<Icon name="Home" />}
|
|
104
|
+
>
|
|
105
|
+
Home
|
|
106
|
+
</TabItem>
|
|
107
|
+
<TabItem
|
|
108
|
+
value="search"
|
|
109
|
+
leadingIcon={<Icon name="SearchOutlined" />}
|
|
110
|
+
>
|
|
111
|
+
Search
|
|
112
|
+
</TabItem>
|
|
113
|
+
<TabItem
|
|
114
|
+
value="notifications"
|
|
115
|
+
leadingIcon={<Icon name="Bell" />}
|
|
116
|
+
trailingIcon={<span style={{
|
|
117
|
+
backgroundColor: '#f44336',
|
|
118
|
+
color: 'white',
|
|
119
|
+
borderRadius: '10px',
|
|
120
|
+
padding: '2px 6px',
|
|
121
|
+
fontSize: '12px'
|
|
122
|
+
}}>3</span>}
|
|
123
|
+
>
|
|
124
|
+
Notifications
|
|
125
|
+
</TabItem>
|
|
126
|
+
<TabItem
|
|
127
|
+
value="messages"
|
|
128
|
+
leadingIcon={<Icon name="Message" />}
|
|
129
|
+
trailingIcon={<span style={{
|
|
130
|
+
backgroundColor: '#4caf50',
|
|
131
|
+
color: 'white',
|
|
132
|
+
borderRadius: '50%',
|
|
133
|
+
width: '8px',
|
|
134
|
+
height: '8px',
|
|
135
|
+
display: 'inline-block'
|
|
136
|
+
}} />}
|
|
137
|
+
>
|
|
138
|
+
Messages
|
|
139
|
+
</TabItem>
|
|
140
|
+
<TabItem
|
|
141
|
+
value="profile"
|
|
142
|
+
leadingIcon={<Icon name="Person" />}
|
|
143
|
+
>
|
|
144
|
+
Profile
|
|
145
|
+
</TabItem>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<TabContent value="home">
|
|
149
|
+
<div style={{ padding: '24px' }}>
|
|
150
|
+
<h2>🏠 Home Feed</h2>
|
|
151
|
+
<p>Stay updated with the latest posts and activities from your network.</p>
|
|
152
|
+
<div style={{ marginTop: '20px' }}>
|
|
153
|
+
<div style={{ padding: '16px', border: '1px solid #e0e0e0', borderRadius: '8px', marginBottom: '12px' }}>
|
|
154
|
+
<strong>John Doe</strong> shared a new post
|
|
155
|
+
<p style={{ margin: '8px 0 0 0', color: '#666' }}>Just completed an amazing project! 🎉</p>
|
|
156
|
+
</div>
|
|
157
|
+
<div style={{ padding: '16px', border: '1px solid #e0e0e0', borderRadius: '8px' }}>
|
|
158
|
+
<strong>Jane Smith</strong> updated their status
|
|
159
|
+
<p style={{ margin: '8px 0 0 0', color: '#666' }}>Working on some exciting new features!</p>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</TabContent>
|
|
164
|
+
|
|
165
|
+
<TabContent value="search">
|
|
166
|
+
<div style={{ padding: '24px' }}>
|
|
167
|
+
<h2>🔍 Search</h2>
|
|
168
|
+
<p>Find people, posts, and content across the platform.</p>
|
|
169
|
+
</div>
|
|
170
|
+
</TabContent>
|
|
171
|
+
|
|
172
|
+
<TabContent value="notifications">
|
|
173
|
+
<div style={{ padding: '24px' }}>
|
|
174
|
+
<h2>🔔 Notifications</h2>
|
|
175
|
+
<p>You have 3 unread notifications.</p>
|
|
176
|
+
<div style={{ marginTop: '20px' }}>
|
|
177
|
+
<div style={{ padding: '12px', backgroundColor: '#e3f2fd', borderRadius: '8px', marginBottom: '8px' }}>
|
|
178
|
+
<strong>New follower:</strong> Alex Johnson started following you
|
|
179
|
+
</div>
|
|
180
|
+
<div style={{ padding: '12px', backgroundColor: '#e8f5e8', borderRadius: '8px', marginBottom: '8px' }}>
|
|
181
|
+
<strong>Like:</strong> Someone liked your recent post
|
|
182
|
+
</div>
|
|
183
|
+
<div style={{ padding: '12px', backgroundColor: '#fff3e0', borderRadius: '8px' }}>
|
|
184
|
+
<strong>Comment:</strong> Sarah commented on your photo
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
</TabContent>
|
|
189
|
+
|
|
190
|
+
<TabContent value="messages">
|
|
191
|
+
<div style={{ padding: '24px' }}>
|
|
192
|
+
<h2>💬 Messages</h2>
|
|
193
|
+
<p>Chat with your connections and stay in touch.</p>
|
|
194
|
+
</div>
|
|
195
|
+
</TabContent>
|
|
196
|
+
|
|
197
|
+
<TabContent value="profile">
|
|
198
|
+
<div style={{ padding: '24px' }}>
|
|
199
|
+
<h2>👤 Profile</h2>
|
|
200
|
+
<p>View and edit your profile information.</p>
|
|
201
|
+
</div>
|
|
202
|
+
</TabContent>
|
|
203
|
+
</Tabs>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Tab Items with Loading States
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import { Tabs, TabItem, TabContent, Spinner, Text } from '@delightui/components';
|
|
212
|
+
|
|
213
|
+
function LoadingTabItemExample() {
|
|
214
|
+
const [loadingTabs, setLoadingTabs] = useState<Set<string>>(new Set());
|
|
215
|
+
const [loadedData, setLoadedData] = useState<Set<string>>(new Set());
|
|
216
|
+
|
|
217
|
+
const handleTabClick = async (tabValue: string) => {
|
|
218
|
+
if (loadedData.has(tabValue)) return;
|
|
219
|
+
|
|
220
|
+
setLoadingTabs(prev => new Set(prev).add(tabValue));
|
|
221
|
+
|
|
222
|
+
// Simulate API call
|
|
223
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
224
|
+
|
|
225
|
+
setLoadingTabs(prev => {
|
|
226
|
+
const next = new Set(prev);
|
|
227
|
+
next.delete(tabValue);
|
|
228
|
+
return next;
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
setLoadedData(prev => new Set(prev).add(tabValue));
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<Tabs>
|
|
236
|
+
<div style={{ display: 'flex' }}>
|
|
237
|
+
<TabItem
|
|
238
|
+
value="reports"
|
|
239
|
+
defaultTab
|
|
240
|
+
loading={loadingTabs.has('reports')}
|
|
241
|
+
onClick={() => handleTabClick('reports')}
|
|
242
|
+
>
|
|
243
|
+
Reports
|
|
244
|
+
</TabItem>
|
|
245
|
+
<TabItem
|
|
246
|
+
value="analytics"
|
|
247
|
+
loading={loadingTabs.has('analytics')}
|
|
248
|
+
onClick={() => handleTabClick('analytics')}
|
|
249
|
+
>
|
|
250
|
+
Analytics
|
|
251
|
+
</TabItem>
|
|
252
|
+
<TabItem
|
|
253
|
+
value="exports"
|
|
254
|
+
loading={loadingTabs.has('exports')}
|
|
255
|
+
onClick={() => handleTabClick('exports')}
|
|
256
|
+
>
|
|
257
|
+
Exports
|
|
258
|
+
</TabItem>
|
|
259
|
+
<TabItem
|
|
260
|
+
value="archive"
|
|
261
|
+
loading={loadingTabs.has('archive')}
|
|
262
|
+
onClick={() => handleTabClick('archive')}
|
|
263
|
+
>
|
|
264
|
+
Archive
|
|
265
|
+
</TabItem>
|
|
266
|
+
</div>
|
|
267
|
+
|
|
268
|
+
<TabContent value="reports">
|
|
269
|
+
<div style={{ padding: '24px', textAlign: 'center' }}>
|
|
270
|
+
{loadingTabs.has('reports') ? (
|
|
271
|
+
<div>
|
|
272
|
+
<Spinner />
|
|
273
|
+
<Text style={{ marginTop: '16px' }}>Loading reports...</Text>
|
|
274
|
+
</div>
|
|
275
|
+
) : loadedData.has('reports') ? (
|
|
276
|
+
<div>
|
|
277
|
+
<h2>📊 Reports Dashboard</h2>
|
|
278
|
+
<p>Your reports have been loaded successfully!</p>
|
|
279
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '16px', marginTop: '20px' }}>
|
|
280
|
+
<div style={{ padding: '20px', border: '1px solid #e0e0e0', borderRadius: '8px' }}>
|
|
281
|
+
<Text size="Large" weight="Bold">142</Text>
|
|
282
|
+
<Text color="secondary">Total Reports</Text>
|
|
283
|
+
</div>
|
|
284
|
+
<div style={{ padding: '20px', border: '1px solid #e0e0e0', borderRadius: '8px' }}>
|
|
285
|
+
<Text size="Large" weight="Bold">28</Text>
|
|
286
|
+
<Text color="secondary">This Month</Text>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
) : (
|
|
291
|
+
<div>
|
|
292
|
+
<h2>📊 Reports</h2>
|
|
293
|
+
<p>Click the Reports tab to load your report data.</p>
|
|
294
|
+
</div>
|
|
295
|
+
)}
|
|
296
|
+
</div>
|
|
297
|
+
</TabContent>
|
|
298
|
+
|
|
299
|
+
<TabContent value="analytics">
|
|
300
|
+
<div style={{ padding: '24px', textAlign: 'center' }}>
|
|
301
|
+
{loadingTabs.has('analytics') ? (
|
|
302
|
+
<div>
|
|
303
|
+
<Spinner />
|
|
304
|
+
<Text style={{ marginTop: '16px' }}>Analyzing data...</Text>
|
|
305
|
+
</div>
|
|
306
|
+
) : loadedData.has('analytics') ? (
|
|
307
|
+
<div>
|
|
308
|
+
<h2>📈 Analytics</h2>
|
|
309
|
+
<p>Analytics data loaded and ready for analysis!</p>
|
|
310
|
+
</div>
|
|
311
|
+
) : (
|
|
312
|
+
<div>
|
|
313
|
+
<h2>📈 Analytics</h2>
|
|
314
|
+
<p>Click the Analytics tab to load your analytics data.</p>
|
|
315
|
+
</div>
|
|
316
|
+
)}
|
|
317
|
+
</div>
|
|
318
|
+
</TabContent>
|
|
319
|
+
|
|
320
|
+
<TabContent value="exports">
|
|
321
|
+
<div style={{ padding: '24px', textAlign: 'center' }}>
|
|
322
|
+
{loadingTabs.has('exports') ? (
|
|
323
|
+
<div>
|
|
324
|
+
<Spinner />
|
|
325
|
+
<Text style={{ marginTop: '16px' }}>Preparing exports...</Text>
|
|
326
|
+
</div>
|
|
327
|
+
) : loadedData.has('exports') ? (
|
|
328
|
+
<div>
|
|
329
|
+
<h2>📁 Exports</h2>
|
|
330
|
+
<p>Export files are ready for download!</p>
|
|
331
|
+
</div>
|
|
332
|
+
) : (
|
|
333
|
+
<div>
|
|
334
|
+
<h2>📁 Exports</h2>
|
|
335
|
+
<p>Click the Exports tab to prepare your export files.</p>
|
|
336
|
+
</div>
|
|
337
|
+
)}
|
|
338
|
+
</div>
|
|
339
|
+
</TabContent>
|
|
340
|
+
|
|
341
|
+
<TabContent value="archive">
|
|
342
|
+
<div style={{ padding: '24px', textAlign: 'center' }}>
|
|
343
|
+
{loadingTabs.has('archive') ? (
|
|
344
|
+
<div>
|
|
345
|
+
<Spinner />
|
|
346
|
+
<Text style={{ marginTop: '16px' }}>Loading archive...</Text>
|
|
347
|
+
</div>
|
|
348
|
+
) : loadedData.has('archive') ? (
|
|
349
|
+
<div>
|
|
350
|
+
<h2>🗄️ Archive</h2>
|
|
351
|
+
<p>Archived items loaded successfully!</p>
|
|
352
|
+
</div>
|
|
353
|
+
) : (
|
|
354
|
+
<div>
|
|
355
|
+
<h2>🗄️ Archive</h2>
|
|
356
|
+
<p>Click the Archive tab to access archived content.</p>
|
|
357
|
+
</div>
|
|
358
|
+
)}
|
|
359
|
+
</div>
|
|
360
|
+
</TabContent>
|
|
361
|
+
</Tabs>
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Disabled Tab Items
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
import { Tabs, TabItem, TabContent, Text, Button } from '@delightui/components';
|
|
370
|
+
|
|
371
|
+
function DisabledTabItemExample() {
|
|
372
|
+
const [userRole, setUserRole] = useState<'user' | 'admin' | 'moderator'>('user');
|
|
373
|
+
|
|
374
|
+
const hasAccess = (requiredRole: string) => {
|
|
375
|
+
const roles = { user: 1, moderator: 2, admin: 3 };
|
|
376
|
+
return roles[userRole] >= roles[requiredRole as keyof typeof roles];
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
return (
|
|
380
|
+
<div style={{ padding: '20px' }}>
|
|
381
|
+
<div style={{ marginBottom: '20px' }}>
|
|
382
|
+
<Text weight="Bold">Current Role: {userRole}</Text>
|
|
383
|
+
<div style={{ display: 'flex', gap: '8px', marginTop: '8px' }}>
|
|
384
|
+
<Button
|
|
385
|
+
size="Small"
|
|
386
|
+
type={userRole === 'user' ? 'Filled' : 'Outlined'}
|
|
387
|
+
onClick={() => setUserRole('user')}
|
|
388
|
+
>
|
|
389
|
+
User
|
|
390
|
+
</Button>
|
|
391
|
+
<Button
|
|
392
|
+
size="Small"
|
|
393
|
+
type={userRole === 'moderator' ? 'Filled' : 'Outlined'}
|
|
394
|
+
onClick={() => setUserRole('moderator')}
|
|
395
|
+
>
|
|
396
|
+
Moderator
|
|
397
|
+
</Button>
|
|
398
|
+
<Button
|
|
399
|
+
size="Small"
|
|
400
|
+
type={userRole === 'admin' ? 'Filled' : 'Outlined'}
|
|
401
|
+
onClick={() => setUserRole('admin')}
|
|
402
|
+
>
|
|
403
|
+
Admin
|
|
404
|
+
</Button>
|
|
405
|
+
</div>
|
|
406
|
+
</div>
|
|
407
|
+
|
|
408
|
+
<Tabs>
|
|
409
|
+
<div style={{ display: 'flex' }}>
|
|
410
|
+
<TabItem value="dashboard" defaultTab>
|
|
411
|
+
Dashboard
|
|
412
|
+
</TabItem>
|
|
413
|
+
<TabItem
|
|
414
|
+
value="users"
|
|
415
|
+
disabled={!hasAccess('moderator')}
|
|
416
|
+
title={!hasAccess('moderator') ? 'Requires Moderator access' : ''}
|
|
417
|
+
>
|
|
418
|
+
User Management
|
|
419
|
+
</TabItem>
|
|
420
|
+
<TabItem
|
|
421
|
+
value="content"
|
|
422
|
+
disabled={!hasAccess('moderator')}
|
|
423
|
+
title={!hasAccess('moderator') ? 'Requires Moderator access' : ''}
|
|
424
|
+
>
|
|
425
|
+
Content Moderation
|
|
426
|
+
</TabItem>
|
|
427
|
+
<TabItem
|
|
428
|
+
value="system"
|
|
429
|
+
disabled={!hasAccess('admin')}
|
|
430
|
+
title={!hasAccess('admin') ? 'Requires Admin access' : ''}
|
|
431
|
+
>
|
|
432
|
+
System Settings
|
|
433
|
+
</TabItem>
|
|
434
|
+
<TabItem
|
|
435
|
+
value="logs"
|
|
436
|
+
disabled={!hasAccess('admin')}
|
|
437
|
+
title={!hasAccess('admin') ? 'Requires Admin access' : ''}
|
|
438
|
+
>
|
|
439
|
+
Audit Logs
|
|
440
|
+
</TabItem>
|
|
441
|
+
</div>
|
|
442
|
+
|
|
443
|
+
<TabContent value="dashboard">
|
|
444
|
+
<div style={{ padding: '24px' }}>
|
|
445
|
+
<h2>Dashboard</h2>
|
|
446
|
+
<p>Welcome to your dashboard! This section is available to all users.</p>
|
|
447
|
+
<div style={{ marginTop: '20px', padding: '16px', backgroundColor: '#f5f5f5', borderRadius: '8px' }}>
|
|
448
|
+
<Text>Your current role ({userRole}) provides access to this section.</Text>
|
|
449
|
+
</div>
|
|
450
|
+
</div>
|
|
451
|
+
</TabContent>
|
|
452
|
+
|
|
453
|
+
<TabContent value="users">
|
|
454
|
+
<div style={{ padding: '24px' }}>
|
|
455
|
+
<h2>User Management</h2>
|
|
456
|
+
<p>Manage user accounts, permissions, and access levels.</p>
|
|
457
|
+
<Text color="secondary">
|
|
458
|
+
This feature requires Moderator or Admin privileges.
|
|
459
|
+
</Text>
|
|
460
|
+
</div>
|
|
461
|
+
</TabContent>
|
|
462
|
+
|
|
463
|
+
<TabContent value="content">
|
|
464
|
+
<div style={{ padding: '24px' }}>
|
|
465
|
+
<h2>Content Moderation</h2>
|
|
466
|
+
<p>Review and moderate user-generated content.</p>
|
|
467
|
+
<Text color="secondary">
|
|
468
|
+
This feature requires Moderator or Admin privileges.
|
|
469
|
+
</Text>
|
|
470
|
+
</div>
|
|
471
|
+
</TabContent>
|
|
472
|
+
|
|
473
|
+
<TabContent value="system">
|
|
474
|
+
<div style={{ padding: '24px' }}>
|
|
475
|
+
<h2>System Settings</h2>
|
|
476
|
+
<p>Configure system-wide settings and preferences.</p>
|
|
477
|
+
<Text color="secondary">
|
|
478
|
+
This feature requires Admin privileges.
|
|
479
|
+
</Text>
|
|
480
|
+
</div>
|
|
481
|
+
</TabContent>
|
|
482
|
+
|
|
483
|
+
<TabContent value="logs">
|
|
484
|
+
<div style={{ padding: '24px' }}>
|
|
485
|
+
<h2>Audit Logs</h2>
|
|
486
|
+
<p>View system audit logs and security events.</p>
|
|
487
|
+
<Text color="secondary">
|
|
488
|
+
This feature requires Admin privileges.
|
|
489
|
+
</Text>
|
|
490
|
+
</div>
|
|
491
|
+
</TabContent>
|
|
492
|
+
</Tabs>
|
|
493
|
+
</div>
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Tab Items with Badges and Counters
|
|
499
|
+
|
|
500
|
+
```tsx
|
|
501
|
+
import { Tabs, TabItem, TabContent, Text } from '@delightui/components';
|
|
502
|
+
|
|
503
|
+
function BadgeTabItemExample() {
|
|
504
|
+
const [counts, setCounts] = useState({
|
|
505
|
+
inbox: 15,
|
|
506
|
+
sent: 0,
|
|
507
|
+
drafts: 3,
|
|
508
|
+
spam: 142,
|
|
509
|
+
trash: 8
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
const Badge = ({ count, type = 'primary' }: { count: number; type?: 'primary' | 'danger' | 'warning' }) => {
|
|
513
|
+
if (count === 0) return null;
|
|
514
|
+
|
|
515
|
+
const colors = {
|
|
516
|
+
primary: { bg: '#2196f3', color: 'white' },
|
|
517
|
+
danger: { bg: '#f44336', color: 'white' },
|
|
518
|
+
warning: { bg: '#ff9800', color: 'white' }
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
const style = colors[type];
|
|
522
|
+
|
|
523
|
+
return (
|
|
524
|
+
<span style={{
|
|
525
|
+
backgroundColor: style.bg,
|
|
526
|
+
color: style.color,
|
|
527
|
+
borderRadius: '12px',
|
|
528
|
+
padding: '2px 8px',
|
|
529
|
+
fontSize: '12px',
|
|
530
|
+
fontWeight: 'bold',
|
|
531
|
+
marginLeft: '8px',
|
|
532
|
+
minWidth: '20px',
|
|
533
|
+
textAlign: 'center',
|
|
534
|
+
display: 'inline-block'
|
|
535
|
+
}}>
|
|
536
|
+
{count > 99 ? '99+' : count}
|
|
537
|
+
</span>
|
|
538
|
+
);
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
return (
|
|
542
|
+
<Tabs style="Underlined">
|
|
543
|
+
<div style={{ display: 'flex' }}>
|
|
544
|
+
<TabItem
|
|
545
|
+
value="inbox"
|
|
546
|
+
defaultTab
|
|
547
|
+
trailingIcon={<Badge count={counts.inbox} type="primary" />}
|
|
548
|
+
>
|
|
549
|
+
Inbox
|
|
550
|
+
</TabItem>
|
|
551
|
+
<TabItem
|
|
552
|
+
value="sent"
|
|
553
|
+
trailingIcon={<Badge count={counts.sent} />}
|
|
554
|
+
>
|
|
555
|
+
Sent
|
|
556
|
+
</TabItem>
|
|
557
|
+
<TabItem
|
|
558
|
+
value="drafts"
|
|
559
|
+
trailingIcon={<Badge count={counts.drafts} type="warning" />}
|
|
560
|
+
>
|
|
561
|
+
Drafts
|
|
562
|
+
</TabItem>
|
|
563
|
+
<TabItem
|
|
564
|
+
value="spam"
|
|
565
|
+
trailingIcon={<Badge count={counts.spam} type="danger" />}
|
|
566
|
+
>
|
|
567
|
+
Spam
|
|
568
|
+
</TabItem>
|
|
569
|
+
<TabItem
|
|
570
|
+
value="trash"
|
|
571
|
+
trailingIcon={<Badge count={counts.trash} />}
|
|
572
|
+
>
|
|
573
|
+
Trash
|
|
574
|
+
</TabItem>
|
|
575
|
+
</div>
|
|
576
|
+
|
|
577
|
+
<TabContent value="inbox">
|
|
578
|
+
<div style={{ padding: '24px' }}>
|
|
579
|
+
<h2>📥 Inbox ({counts.inbox})</h2>
|
|
580
|
+
<p>You have {counts.inbox} unread messages in your inbox.</p>
|
|
581
|
+
<div style={{ marginTop: '20px' }}>
|
|
582
|
+
{Array.from({ length: Math.min(counts.inbox, 5) }, (_, i) => (
|
|
583
|
+
<div key={i} style={{
|
|
584
|
+
padding: '12px',
|
|
585
|
+
border: '1px solid #e0e0e0',
|
|
586
|
+
borderRadius: '8px',
|
|
587
|
+
marginBottom: '8px',
|
|
588
|
+
backgroundColor: i < 3 ? '#e3f2fd' : 'white'
|
|
589
|
+
}}>
|
|
590
|
+
<Text weight="Bold">Message {i + 1}</Text>
|
|
591
|
+
<Text size="Small" color="secondary">
|
|
592
|
+
{i < 3 ? 'Unread' : 'Read'} • 2 hours ago
|
|
593
|
+
</Text>
|
|
594
|
+
</div>
|
|
595
|
+
))}
|
|
596
|
+
</div>
|
|
597
|
+
</div>
|
|
598
|
+
</TabContent>
|
|
599
|
+
|
|
600
|
+
<TabContent value="sent">
|
|
601
|
+
<div style={{ padding: '24px' }}>
|
|
602
|
+
<h2>📤 Sent Messages</h2>
|
|
603
|
+
<p>Your sent messages appear here.</p>
|
|
604
|
+
{counts.sent === 0 && (
|
|
605
|
+
<Text color="secondary">No sent messages yet.</Text>
|
|
606
|
+
)}
|
|
607
|
+
</div>
|
|
608
|
+
</TabContent>
|
|
609
|
+
|
|
610
|
+
<TabContent value="drafts">
|
|
611
|
+
<div style={{ padding: '24px' }}>
|
|
612
|
+
<h2>📝 Draft Messages ({counts.drafts})</h2>
|
|
613
|
+
<p>You have {counts.drafts} draft messages waiting to be sent.</p>
|
|
614
|
+
<div style={{ marginTop: '20px' }}>
|
|
615
|
+
{Array.from({ length: counts.drafts }, (_, i) => (
|
|
616
|
+
<div key={i} style={{
|
|
617
|
+
padding: '12px',
|
|
618
|
+
border: '1px solid #e0e0e0',
|
|
619
|
+
borderRadius: '8px',
|
|
620
|
+
marginBottom: '8px',
|
|
621
|
+
backgroundColor: '#fff3e0'
|
|
622
|
+
}}>
|
|
623
|
+
<Text weight="Bold">Draft {i + 1}</Text>
|
|
624
|
+
<Text size="Small" color="secondary">
|
|
625
|
+
Last edited 1 hour ago
|
|
626
|
+
</Text>
|
|
627
|
+
</div>
|
|
628
|
+
))}
|
|
629
|
+
</div>
|
|
630
|
+
</div>
|
|
631
|
+
</TabContent>
|
|
632
|
+
|
|
633
|
+
<TabContent value="spam">
|
|
634
|
+
<div style={{ padding: '24px' }}>
|
|
635
|
+
<h2>🚫 Spam ({counts.spam})</h2>
|
|
636
|
+
<p>Messages identified as spam are moved here automatically.</p>
|
|
637
|
+
<Text size="Small" color="secondary">
|
|
638
|
+
Spam messages are automatically deleted after 30 days.
|
|
639
|
+
</Text>
|
|
640
|
+
</div>
|
|
641
|
+
</TabContent>
|
|
642
|
+
|
|
643
|
+
<TabContent value="trash">
|
|
644
|
+
<div style={{ padding: '24px' }}>
|
|
645
|
+
<h2>🗑️ Trash ({counts.trash})</h2>
|
|
646
|
+
<p>Deleted messages are stored here temporarily.</p>
|
|
647
|
+
<Text size="Small" color="secondary">
|
|
648
|
+
Messages in trash are permanently deleted after 30 days.
|
|
649
|
+
</Text>
|
|
650
|
+
</div>
|
|
651
|
+
</TabContent>
|
|
652
|
+
</Tabs>
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### Tab Items with Custom Styling
|
|
658
|
+
|
|
659
|
+
```tsx
|
|
660
|
+
import { Tabs, TabItem, TabContent, Text } from '@delightui/components';
|
|
661
|
+
|
|
662
|
+
function CustomStyledTabItemExample() {
|
|
663
|
+
const [activeTab, setActiveTab] = useState('design');
|
|
664
|
+
|
|
665
|
+
return (
|
|
666
|
+
<Tabs
|
|
667
|
+
style="Filled"
|
|
668
|
+
onClick={(value) => setActiveTab(value as string)}
|
|
669
|
+
>
|
|
670
|
+
<div style={{
|
|
671
|
+
display: 'flex',
|
|
672
|
+
backgroundColor: '#f5f5f5',
|
|
673
|
+
borderRadius: '12px',
|
|
674
|
+
padding: '4px',
|
|
675
|
+
width: 'fit-content'
|
|
676
|
+
}}>
|
|
677
|
+
<TabItem
|
|
678
|
+
value="design"
|
|
679
|
+
defaultTab
|
|
680
|
+
style={{
|
|
681
|
+
borderRadius: '8px',
|
|
682
|
+
margin: '2px',
|
|
683
|
+
backgroundColor: activeTab === 'design' ? '#2196f3' : 'transparent',
|
|
684
|
+
color: activeTab === 'design' ? 'white' : '#666',
|
|
685
|
+
border: 'none',
|
|
686
|
+
transition: 'all 0.2s ease'
|
|
687
|
+
}}
|
|
688
|
+
>
|
|
689
|
+
🎨 Design
|
|
690
|
+
</TabItem>
|
|
691
|
+
<TabItem
|
|
692
|
+
value="development"
|
|
693
|
+
style={{
|
|
694
|
+
borderRadius: '8px',
|
|
695
|
+
margin: '2px',
|
|
696
|
+
backgroundColor: activeTab === 'development' ? '#4caf50' : 'transparent',
|
|
697
|
+
color: activeTab === 'development' ? 'white' : '#666',
|
|
698
|
+
border: 'none',
|
|
699
|
+
transition: 'all 0.2s ease'
|
|
700
|
+
}}
|
|
701
|
+
>
|
|
702
|
+
💻 Development
|
|
703
|
+
</TabItem>
|
|
704
|
+
<TabItem
|
|
705
|
+
value="testing"
|
|
706
|
+
style={{
|
|
707
|
+
borderRadius: '8px',
|
|
708
|
+
margin: '2px',
|
|
709
|
+
backgroundColor: activeTab === 'testing' ? '#ff9800' : 'transparent',
|
|
710
|
+
color: activeTab === 'testing' ? 'white' : '#666',
|
|
711
|
+
border: 'none',
|
|
712
|
+
transition: 'all 0.2s ease'
|
|
713
|
+
}}
|
|
714
|
+
>
|
|
715
|
+
🧪 Testing
|
|
716
|
+
</TabItem>
|
|
717
|
+
<TabItem
|
|
718
|
+
value="deployment"
|
|
719
|
+
style={{
|
|
720
|
+
borderRadius: '8px',
|
|
721
|
+
margin: '2px',
|
|
722
|
+
backgroundColor: activeTab === 'deployment' ? '#9c27b0' : 'transparent',
|
|
723
|
+
color: activeTab === 'deployment' ? 'white' : '#666',
|
|
724
|
+
border: 'none',
|
|
725
|
+
transition: 'all 0.2s ease'
|
|
726
|
+
}}
|
|
727
|
+
>
|
|
728
|
+
🚀 Deployment
|
|
729
|
+
</TabItem>
|
|
730
|
+
</div>
|
|
731
|
+
|
|
732
|
+
<TabContent value="design">
|
|
733
|
+
<div style={{
|
|
734
|
+
padding: '24px',
|
|
735
|
+
background: 'linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%)',
|
|
736
|
+
borderRadius: '12px',
|
|
737
|
+
marginTop: '16px'
|
|
738
|
+
}}>
|
|
739
|
+
<h2 style={{ color: '#1976d2' }}>🎨 Design Phase</h2>
|
|
740
|
+
<Text>Create wireframes, mockups, and design systems for the project.</Text>
|
|
741
|
+
<div style={{ marginTop: '20px' }}>
|
|
742
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '12px' }}>
|
|
743
|
+
<div style={{ padding: '16px', backgroundColor: 'rgba(255,255,255,0.8)', borderRadius: '8px' }}>
|
|
744
|
+
<Text weight="Bold">Wireframes</Text>
|
|
745
|
+
<Text size="Small">Complete</Text>
|
|
746
|
+
</div>
|
|
747
|
+
<div style={{ padding: '16px', backgroundColor: 'rgba(255,255,255,0.8)', borderRadius: '8px' }}>
|
|
748
|
+
<Text weight="Bold">UI Design</Text>
|
|
749
|
+
<Text size="Small">In Progress</Text>
|
|
750
|
+
</div>
|
|
751
|
+
</div>
|
|
752
|
+
</div>
|
|
753
|
+
</div>
|
|
754
|
+
</TabContent>
|
|
755
|
+
|
|
756
|
+
<TabContent value="development">
|
|
757
|
+
<div style={{
|
|
758
|
+
padding: '24px',
|
|
759
|
+
background: 'linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%)',
|
|
760
|
+
borderRadius: '12px',
|
|
761
|
+
marginTop: '16px'
|
|
762
|
+
}}>
|
|
763
|
+
<h2 style={{ color: '#2e7d32' }}>💻 Development Phase</h2>
|
|
764
|
+
<Text>Build the application using modern development practices and tools.</Text>
|
|
765
|
+
<div style={{ marginTop: '20px' }}>
|
|
766
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '12px' }}>
|
|
767
|
+
<div style={{ padding: '16px', backgroundColor: 'rgba(255,255,255,0.8)', borderRadius: '8px' }}>
|
|
768
|
+
<Text weight="Bold">Frontend</Text>
|
|
769
|
+
<Text size="Small">80% Complete</Text>
|
|
770
|
+
</div>
|
|
771
|
+
<div style={{ padding: '16px', backgroundColor: 'rgba(255,255,255,0.8)', borderRadius: '8px' }}>
|
|
772
|
+
<Text weight="Bold">Backend</Text>
|
|
773
|
+
<Text size="Small">60% Complete</Text>
|
|
774
|
+
</div>
|
|
775
|
+
</div>
|
|
776
|
+
</div>
|
|
777
|
+
</div>
|
|
778
|
+
</TabContent>
|
|
779
|
+
|
|
780
|
+
<TabContent value="testing">
|
|
781
|
+
<div style={{
|
|
782
|
+
padding: '24px',
|
|
783
|
+
background: 'linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%)',
|
|
784
|
+
borderRadius: '12px',
|
|
785
|
+
marginTop: '16px'
|
|
786
|
+
}}>
|
|
787
|
+
<h2 style={{ color: '#f57c00' }}>🧪 Testing Phase</h2>
|
|
788
|
+
<Text>Comprehensive testing to ensure quality and reliability.</Text>
|
|
789
|
+
<div style={{ marginTop: '20px' }}>
|
|
790
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '12px' }}>
|
|
791
|
+
<div style={{ padding: '16px', backgroundColor: 'rgba(255,255,255,0.8)', borderRadius: '8px' }}>
|
|
792
|
+
<Text weight="Bold">Unit Tests</Text>
|
|
793
|
+
<Text size="Small">Not Started</Text>
|
|
794
|
+
</div>
|
|
795
|
+
<div style={{ padding: '16px', backgroundColor: 'rgba(255,255,255,0.8)', borderRadius: '8px' }}>
|
|
796
|
+
<Text weight="Bold">Integration Tests</Text>
|
|
797
|
+
<Text size="Small">Not Started</Text>
|
|
798
|
+
</div>
|
|
799
|
+
</div>
|
|
800
|
+
</div>
|
|
801
|
+
</div>
|
|
802
|
+
</TabContent>
|
|
803
|
+
|
|
804
|
+
<TabContent value="deployment">
|
|
805
|
+
<div style={{
|
|
806
|
+
padding: '24px',
|
|
807
|
+
background: 'linear-gradient(135deg, #f3e5f5 0%, #e1bee7 100%)',
|
|
808
|
+
borderRadius: '12px',
|
|
809
|
+
marginTop: '16px'
|
|
810
|
+
}}>
|
|
811
|
+
<h2 style={{ color: '#7b1fa2' }}>🚀 Deployment Phase</h2>
|
|
812
|
+
<Text>Deploy the application to production environments.</Text>
|
|
813
|
+
<div style={{ marginTop: '20px' }}>
|
|
814
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minWidth(200px, 1fr))', gap: '12px' }}>
|
|
815
|
+
<div style={{ padding: '16px', backgroundColor: 'rgba(255,255,255,0.8)', borderRadius: '8px' }}>
|
|
816
|
+
<Text weight="Bold">Staging</Text>
|
|
817
|
+
<Text size="Small">Not Started</Text>
|
|
818
|
+
</div>
|
|
819
|
+
<div style={{ padding: '16px', backgroundColor: 'rgba(255,255,255,0.8)', borderRadius: '8px' }}>
|
|
820
|
+
<Text weight="Bold">Production</Text>
|
|
821
|
+
<Text size="Small">Not Started</Text>
|
|
822
|
+
</div>
|
|
823
|
+
</div>
|
|
824
|
+
</div>
|
|
825
|
+
</div>
|
|
826
|
+
</TabContent>
|
|
827
|
+
</Tabs>
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
### Tab Items with Click Handlers
|
|
833
|
+
|
|
834
|
+
```tsx
|
|
835
|
+
import { Tabs, TabItem, TabContent, Text, Button } from '@delightui/components';
|
|
836
|
+
|
|
837
|
+
function ClickHandlerTabItemExample() {
|
|
838
|
+
const [clickCounts, setClickCounts] = useState({
|
|
839
|
+
home: 0,
|
|
840
|
+
about: 0,
|
|
841
|
+
services: 0,
|
|
842
|
+
contact: 0
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
const [lastClicked, setLastClicked] = useState<string>('');
|
|
846
|
+
|
|
847
|
+
const handleTabClick = (tabValue: string) => {
|
|
848
|
+
setClickCounts(prev => ({
|
|
849
|
+
...prev,
|
|
850
|
+
[tabValue]: prev[tabValue as keyof typeof prev] + 1
|
|
851
|
+
}));
|
|
852
|
+
setLastClicked(tabValue);
|
|
853
|
+
console.log(`Tab ${tabValue} clicked ${clickCounts[tabValue as keyof typeof clickCounts] + 1} times`);
|
|
854
|
+
};
|
|
855
|
+
|
|
856
|
+
const resetCounts = () => {
|
|
857
|
+
setClickCounts({ home: 0, about: 0, services: 0, contact: 0 });
|
|
858
|
+
setLastClicked('');
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
return (
|
|
862
|
+
<div>
|
|
863
|
+
<div style={{ marginBottom: '20px', padding: '16px', backgroundColor: '#f5f5f5', borderRadius: '8px' }}>
|
|
864
|
+
<Text weight="Bold">Click Analytics</Text>
|
|
865
|
+
<Text size="Small">Last clicked: {lastClicked || 'None'}</Text>
|
|
866
|
+
<div style={{ display: 'flex', gap: '16px', marginTop: '8px' }}>
|
|
867
|
+
<Text size="Small">Home: {clickCounts.home}</Text>
|
|
868
|
+
<Text size="Small">About: {clickCounts.about}</Text>
|
|
869
|
+
<Text size="Small">Services: {clickCounts.services}</Text>
|
|
870
|
+
<Text size="Small">Contact: {clickCounts.contact}</Text>
|
|
871
|
+
</div>
|
|
872
|
+
<Button size="Small" type="Outlined" onClick={resetCounts} style={{ marginTop: '8px' }}>
|
|
873
|
+
Reset Counts
|
|
874
|
+
</Button>
|
|
875
|
+
</div>
|
|
876
|
+
|
|
877
|
+
<Tabs>
|
|
878
|
+
<div style={{ display: 'flex' }}>
|
|
879
|
+
<TabItem
|
|
880
|
+
value="home"
|
|
881
|
+
defaultTab
|
|
882
|
+
onClick={() => handleTabClick('home')}
|
|
883
|
+
>
|
|
884
|
+
Home ({clickCounts.home})
|
|
885
|
+
</TabItem>
|
|
886
|
+
<TabItem
|
|
887
|
+
value="about"
|
|
888
|
+
onClick={() => handleTabClick('about')}
|
|
889
|
+
>
|
|
890
|
+
About ({clickCounts.about})
|
|
891
|
+
</TabItem>
|
|
892
|
+
<TabItem
|
|
893
|
+
value="services"
|
|
894
|
+
onClick={() => handleTabClick('services')}
|
|
895
|
+
>
|
|
896
|
+
Services ({clickCounts.services})
|
|
897
|
+
</TabItem>
|
|
898
|
+
<TabItem
|
|
899
|
+
value="contact"
|
|
900
|
+
onClick={() => handleTabClick('contact')}
|
|
901
|
+
>
|
|
902
|
+
Contact ({clickCounts.contact})
|
|
903
|
+
</TabItem>
|
|
904
|
+
</div>
|
|
905
|
+
|
|
906
|
+
<TabContent value="home">
|
|
907
|
+
<div style={{ padding: '24px' }}>
|
|
908
|
+
<h2>🏠 Home</h2>
|
|
909
|
+
<Text>Welcome to our home page! You've clicked this tab {clickCounts.home} times.</Text>
|
|
910
|
+
<div style={{ marginTop: '16px', padding: '12px', backgroundColor: '#e3f2fd', borderRadius: '8px' }}>
|
|
911
|
+
<Text size="Small">
|
|
912
|
+
This tab has custom click tracking enabled. Each click is logged to the console.
|
|
913
|
+
</Text>
|
|
914
|
+
</div>
|
|
915
|
+
</div>
|
|
916
|
+
</TabContent>
|
|
917
|
+
|
|
918
|
+
<TabContent value="about">
|
|
919
|
+
<div style={{ padding: '24px' }}>
|
|
920
|
+
<h2>ℹ️ About</h2>
|
|
921
|
+
<Text>Learn more about us! Click count: {clickCounts.about}</Text>
|
|
922
|
+
</div>
|
|
923
|
+
</TabContent>
|
|
924
|
+
|
|
925
|
+
<TabContent value="services">
|
|
926
|
+
<div style={{ padding: '24px' }}>
|
|
927
|
+
<h2>🛠️ Services</h2>
|
|
928
|
+
<Text>Discover our services! Click count: {clickCounts.services}</Text>
|
|
929
|
+
</div>
|
|
930
|
+
</TabContent>
|
|
931
|
+
|
|
932
|
+
<TabContent value="contact">
|
|
933
|
+
<div style={{ padding: '24px' }}>
|
|
934
|
+
<h2>📞 Contact</h2>
|
|
935
|
+
<Text>Get in touch with us! Click count: {clickCounts.contact}</Text>
|
|
936
|
+
</div>
|
|
937
|
+
</TabContent>
|
|
938
|
+
</Tabs>
|
|
939
|
+
</div>
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
### Responsive Tab Items
|
|
945
|
+
|
|
946
|
+
```tsx
|
|
947
|
+
import { Tabs, TabItem, TabContent, Text } from '@delightui/components';
|
|
948
|
+
|
|
949
|
+
function ResponsiveTabItemExample() {
|
|
950
|
+
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
|
|
951
|
+
|
|
952
|
+
useEffect(() => {
|
|
953
|
+
const handleResize = () => {
|
|
954
|
+
setIsMobile(window.innerWidth < 768);
|
|
955
|
+
};
|
|
956
|
+
|
|
957
|
+
window.addEventListener('resize', handleResize);
|
|
958
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
959
|
+
}, []);
|
|
960
|
+
|
|
961
|
+
return (
|
|
962
|
+
<Tabs style={isMobile ? 'Filled' : 'Underlined'}>
|
|
963
|
+
<div style={{
|
|
964
|
+
display: 'flex',
|
|
965
|
+
flexDirection: isMobile ? 'column' : 'row',
|
|
966
|
+
gap: isMobile ? '8px' : '0',
|
|
967
|
+
...(isMobile && { padding: '8px' })
|
|
968
|
+
}}>
|
|
969
|
+
<TabItem
|
|
970
|
+
value="dashboard"
|
|
971
|
+
defaultTab
|
|
972
|
+
style={{
|
|
973
|
+
...(isMobile && {
|
|
974
|
+
width: '100%',
|
|
975
|
+
justifyContent: 'flex-start',
|
|
976
|
+
padding: '12px 16px'
|
|
977
|
+
})
|
|
978
|
+
}}
|
|
979
|
+
>
|
|
980
|
+
{isMobile ? '📊 Dashboard' : 'Dashboard'}
|
|
981
|
+
</TabItem>
|
|
982
|
+
<TabItem
|
|
983
|
+
value="analytics"
|
|
984
|
+
style={{
|
|
985
|
+
...(isMobile && {
|
|
986
|
+
width: '100%',
|
|
987
|
+
justifyContent: 'flex-start',
|
|
988
|
+
padding: '12px 16px'
|
|
989
|
+
})
|
|
990
|
+
}}
|
|
991
|
+
>
|
|
992
|
+
{isMobile ? '📈 Analytics' : 'Analytics'}
|
|
993
|
+
</TabItem>
|
|
994
|
+
<TabItem
|
|
995
|
+
value="reports"
|
|
996
|
+
style={{
|
|
997
|
+
...(isMobile && {
|
|
998
|
+
width: '100%',
|
|
999
|
+
justifyContent: 'flex-start',
|
|
1000
|
+
padding: '12px 16px'
|
|
1001
|
+
})
|
|
1002
|
+
}}
|
|
1003
|
+
>
|
|
1004
|
+
{isMobile ? '📋 Reports' : 'Reports'}
|
|
1005
|
+
</TabItem>
|
|
1006
|
+
<TabItem
|
|
1007
|
+
value="settings"
|
|
1008
|
+
style={{
|
|
1009
|
+
...(isMobile && {
|
|
1010
|
+
width: '100%',
|
|
1011
|
+
justifyContent: 'flex-start',
|
|
1012
|
+
padding: '12px 16px'
|
|
1013
|
+
})
|
|
1014
|
+
}}
|
|
1015
|
+
>
|
|
1016
|
+
{isMobile ? '⚙️ Settings' : 'Settings'}
|
|
1017
|
+
</TabItem>
|
|
1018
|
+
</div>
|
|
1019
|
+
|
|
1020
|
+
<TabContent value="dashboard">
|
|
1021
|
+
<div style={{ padding: isMobile ? '16px' : '24px' }}>
|
|
1022
|
+
<h2>Dashboard</h2>
|
|
1023
|
+
<Text>
|
|
1024
|
+
{isMobile
|
|
1025
|
+
? 'Mobile-optimized dashboard view with essential metrics.'
|
|
1026
|
+
: 'Full dashboard with comprehensive analytics and reporting tools.'
|
|
1027
|
+
}
|
|
1028
|
+
</Text>
|
|
1029
|
+
<div style={{
|
|
1030
|
+
display: 'grid',
|
|
1031
|
+
gridTemplateColumns: isMobile ? '1fr' : 'repeat(auto-fit, minmax(200px, 1fr))',
|
|
1032
|
+
gap: '16px',
|
|
1033
|
+
marginTop: '20px'
|
|
1034
|
+
}}>
|
|
1035
|
+
<div style={{ padding: '16px', border: '1px solid #e0e0e0', borderRadius: '8px' }}>
|
|
1036
|
+
<Text weight="Bold">Users</Text>
|
|
1037
|
+
<Text size="Large">1,234</Text>
|
|
1038
|
+
</div>
|
|
1039
|
+
<div style={{ padding: '16px', border: '1px solid #e0e0e0', borderRadius: '8px' }}>
|
|
1040
|
+
<Text weight="Bold">Revenue</Text>
|
|
1041
|
+
<Text size="Large">$45,678</Text>
|
|
1042
|
+
</div>
|
|
1043
|
+
{!isMobile && (
|
|
1044
|
+
<div style={{ padding: '16px', border: '1px solid #e0e0e0', borderRadius: '8px' }}>
|
|
1045
|
+
<Text weight="Bold">Growth</Text>
|
|
1046
|
+
<Text size="Large">+12.5%</Text>
|
|
1047
|
+
</div>
|
|
1048
|
+
)}
|
|
1049
|
+
</div>
|
|
1050
|
+
</div>
|
|
1051
|
+
</TabContent>
|
|
1052
|
+
|
|
1053
|
+
<TabContent value="analytics">
|
|
1054
|
+
<div style={{ padding: isMobile ? '16px' : '24px' }}>
|
|
1055
|
+
<h2>Analytics</h2>
|
|
1056
|
+
<Text>
|
|
1057
|
+
{isMobile
|
|
1058
|
+
? 'Key analytics metrics optimized for mobile viewing.'
|
|
1059
|
+
: 'Detailed analytics with charts, graphs, and comprehensive data visualization.'
|
|
1060
|
+
}
|
|
1061
|
+
</Text>
|
|
1062
|
+
</div>
|
|
1063
|
+
</TabContent>
|
|
1064
|
+
|
|
1065
|
+
<TabContent value="reports">
|
|
1066
|
+
<div style={{ padding: isMobile ? '16px' : '24px' }}>
|
|
1067
|
+
<h2>Reports</h2>
|
|
1068
|
+
<Text>
|
|
1069
|
+
{isMobile
|
|
1070
|
+
? 'Essential reports formatted for mobile devices.'
|
|
1071
|
+
: 'Complete reporting suite with advanced filtering and export options.'
|
|
1072
|
+
}
|
|
1073
|
+
</Text>
|
|
1074
|
+
</div>
|
|
1075
|
+
</TabContent>
|
|
1076
|
+
|
|
1077
|
+
<TabContent value="settings">
|
|
1078
|
+
<div style={{ padding: isMobile ? '16px' : '24px' }}>
|
|
1079
|
+
<h2>Settings</h2>
|
|
1080
|
+
<Text>
|
|
1081
|
+
{isMobile
|
|
1082
|
+
? 'Core settings available on mobile.'
|
|
1083
|
+
: 'Full settings panel with advanced configuration options.'
|
|
1084
|
+
}
|
|
1085
|
+
</Text>
|
|
1086
|
+
</div>
|
|
1087
|
+
</TabContent>
|
|
1088
|
+
</Tabs>
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
```
|