saha-ui 1.2.0 → 1.4.0
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 +3054 -87
- package/dist/components/Accordion/Accordion.types.d.ts +62 -27
- package/dist/components/Accordion/Accordion.types.d.ts.map +1 -1
- package/dist/components/Accordion/index.d.ts +5 -3
- package/dist/components/Accordion/index.d.ts.map +1 -1
- package/dist/components/Accordion/index.js +188 -68
- package/dist/components/Alert/Alert.types.d.ts +1 -1
- package/dist/components/Alert/Alert.types.d.ts.map +1 -1
- package/dist/components/Alert/index.d.ts.map +1 -1
- package/dist/components/Alert/index.js +23 -1
- package/dist/components/Badge/index.d.ts +1 -1
- package/dist/components/Breadcrumb/Breadcrumb.types.d.ts +12 -70
- package/dist/components/Breadcrumb/Breadcrumb.types.d.ts.map +1 -1
- package/dist/components/Breadcrumb/index.d.ts +5 -55
- package/dist/components/Breadcrumb/index.d.ts.map +1 -1
- package/dist/components/Breadcrumb/index.js +112 -143
- package/dist/components/Button/Button.types.d.ts +1 -1
- package/dist/components/Button/Button.types.d.ts.map +1 -1
- package/dist/components/Button/index.d.ts +1 -1
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +15 -11
- package/dist/components/ButtonGroup/index.d.ts +12 -42
- package/dist/components/ButtonGroup/index.d.ts.map +1 -1
- package/dist/components/ButtonGroup/index.js +98 -87
- package/dist/components/Card/index.d.ts +1 -1
- package/dist/components/Card/index.js +2 -2
- package/dist/components/Carousel/Carousel.types.d.ts +18 -127
- package/dist/components/Carousel/Carousel.types.d.ts.map +1 -1
- package/dist/components/Carousel/index.d.ts +6 -22
- package/dist/components/Carousel/index.d.ts.map +1 -1
- package/dist/components/Carousel/index.js +192 -134
- package/dist/components/Chip/Chip.types.d.ts +82 -0
- package/dist/components/Chip/Chip.types.d.ts.map +1 -0
- package/dist/components/Chip/Chip.types.js +1 -0
- package/dist/components/Chip/index.d.ts +68 -0
- package/dist/components/Chip/index.d.ts.map +1 -0
- package/dist/components/Chip/index.js +295 -0
- package/dist/components/DatePicker/DatePicker.types.d.ts +228 -0
- package/dist/components/DatePicker/DatePicker.types.d.ts.map +1 -0
- package/dist/components/DatePicker/DatePicker.types.js +1 -0
- package/dist/components/DatePicker/index.d.ts +23 -0
- package/dist/components/DatePicker/index.d.ts.map +1 -0
- package/dist/components/DatePicker/index.js +867 -0
- package/dist/components/Divider/Divider.types.d.ts +61 -0
- package/dist/components/Divider/Divider.types.d.ts.map +1 -0
- package/dist/components/Divider/Divider.types.js +1 -0
- package/dist/components/Divider/index.d.ts +65 -0
- package/dist/components/Divider/index.d.ts.map +1 -0
- package/dist/components/Divider/index.js +275 -0
- package/dist/components/Input/Input.types.d.ts +71 -0
- package/dist/components/Input/Input.types.d.ts.map +1 -0
- package/dist/components/Input/Input.types.js +1 -0
- package/dist/components/Input/index.d.ts +41 -0
- package/dist/components/Input/index.d.ts.map +1 -0
- package/dist/components/Input/index.js +304 -0
- package/dist/components/Link/index.d.ts +1 -1
- package/dist/components/List/List.types.d.ts +1 -1
- package/dist/components/List/List.types.d.ts.map +1 -1
- package/dist/components/List/ListItem.d.ts +1 -1
- package/dist/components/List/ListItem.d.ts.map +1 -1
- package/dist/components/List/ListItem.js +8 -7
- package/dist/components/List/index.d.ts +8 -34
- package/dist/components/List/index.d.ts.map +1 -1
- package/dist/components/List/index.js +70 -30
- package/dist/components/Pagination/Pagination.types.d.ts +99 -0
- package/dist/components/Pagination/Pagination.types.d.ts.map +1 -0
- package/dist/components/Pagination/Pagination.types.js +1 -0
- package/dist/components/Pagination/index.d.ts +38 -0
- package/dist/components/Pagination/index.d.ts.map +1 -0
- package/dist/components/Pagination/index.js +318 -0
- package/dist/components/PlayButton/PlayButton.types.d.ts +50 -0
- package/dist/components/PlayButton/PlayButton.types.d.ts.map +1 -0
- package/dist/components/PlayButton/PlayButton.types.js +1 -0
- package/dist/components/PlayButton/index.d.ts +53 -0
- package/dist/components/PlayButton/index.d.ts.map +1 -0
- package/dist/components/PlayButton/index.js +162 -0
- package/dist/components/Popover/Popover.types.d.ts +126 -0
- package/dist/components/Popover/Popover.types.d.ts.map +1 -0
- package/dist/components/Popover/Popover.types.js +1 -0
- package/dist/components/Popover/index.d.ts +77 -0
- package/dist/components/Popover/index.d.ts.map +1 -0
- package/dist/components/Popover/index.js +295 -0
- package/dist/components/Progress/Progress.types.d.ts +121 -0
- package/dist/components/Progress/Progress.types.d.ts.map +1 -0
- package/dist/components/Progress/Progress.types.js +1 -0
- package/dist/components/Progress/index.d.ts +72 -0
- package/dist/components/Progress/index.d.ts.map +1 -0
- package/dist/components/Progress/index.js +215 -0
- package/dist/components/Rating/Rating.types.d.ts +139 -0
- package/dist/components/Rating/Rating.types.d.ts.map +1 -0
- package/dist/components/Rating/Rating.types.js +1 -0
- package/dist/components/Rating/index.d.ts +25 -0
- package/dist/components/Rating/index.d.ts.map +1 -0
- package/dist/components/Rating/index.js +277 -0
- package/dist/components/Skeleton/Skeleton.types.d.ts +65 -0
- package/dist/components/Skeleton/Skeleton.types.d.ts.map +1 -0
- package/dist/components/Skeleton/Skeleton.types.js +1 -0
- package/dist/components/Skeleton/index.d.ts +34 -0
- package/dist/components/Skeleton/index.d.ts.map +1 -0
- package/dist/components/Skeleton/index.js +142 -0
- package/dist/components/Steps/Steps.types.d.ts +27 -0
- package/dist/components/Steps/Steps.types.d.ts.map +1 -0
- package/dist/components/Steps/Steps.types.js +1 -0
- package/dist/components/Steps/index.d.ts +5 -0
- package/dist/components/Steps/index.d.ts.map +1 -0
- package/dist/components/Steps/index.js +215 -0
- package/dist/components/Tab/Tab.types.d.ts +33 -0
- package/dist/components/Tab/Tab.types.d.ts.map +1 -0
- package/dist/components/Tab/Tab.types.js +1 -0
- package/dist/components/Tab/index.d.ts +41 -0
- package/dist/components/Tab/index.d.ts.map +1 -0
- package/dist/components/Tab/index.js +330 -0
- package/dist/components/Table/Table.types.d.ts +189 -0
- package/dist/components/Table/Table.types.d.ts.map +1 -0
- package/dist/components/Table/Table.types.js +1 -0
- package/dist/components/Table/index.d.ts +10 -0
- package/dist/components/Table/index.d.ts.map +1 -0
- package/dist/components/Table/index.js +234 -0
- package/dist/components/Timeline/Timeline.types.d.ts +23 -0
- package/dist/components/Timeline/Timeline.types.d.ts.map +1 -0
- package/dist/components/Timeline/Timeline.types.js +1 -0
- package/dist/components/Timeline/index.d.ts +6 -0
- package/dist/components/Timeline/index.d.ts.map +1 -0
- package/dist/components/Timeline/index.js +154 -0
- package/dist/components/Tooltip/Tooltip.types.d.ts +46 -2
- package/dist/components/Tooltip/Tooltip.types.d.ts.map +1 -1
- package/dist/components/Tooltip/index.d.ts +63 -0
- package/dist/components/Tooltip/index.d.ts.map +1 -1
- package/dist/components/Tooltip/index.js +115 -48
- package/dist/components/Tree/Tree.types.d.ts +21 -0
- package/dist/components/Tree/Tree.types.d.ts.map +1 -0
- package/dist/components/Tree/Tree.types.js +1 -0
- package/dist/components/Tree/index.d.ts +6 -0
- package/dist/components/Tree/index.d.ts.map +1 -0
- package/dist/components/Tree/index.js +132 -0
- package/dist/index.d.ts +40 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +89 -35
- package/package.json +1 -1
- package/dist/assets/components/Accordion/index.css +0 -1
- package/dist/components/Accordion/AccordionItem.d.ts +0 -5
- package/dist/components/Accordion/AccordionItem.d.ts.map +0 -1
- package/dist/components/Accordion/AccordionItem.js +0 -108
- package/dist/components/Carousel/CarouseImage.d.ts +0 -9
- package/dist/components/Carousel/CarouseImage.d.ts.map +0 -1
- package/dist/components/Carousel/CarouseImage.js +0 -72
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<a href="#-installation">Installation</a> •
|
|
19
19
|
<a href="#-features">Features</a> •
|
|
20
20
|
<a href="#-components">Components</a> •
|
|
21
|
-
<a href="#-
|
|
21
|
+
<a href="#-quick-examples">Quick Examples</a> •
|
|
22
22
|
<a href="#-documentation">Documentation</a>
|
|
23
23
|
</p>
|
|
24
24
|
</div>
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
## ✨ Features
|
|
29
29
|
|
|
30
|
-
- 🎨 **
|
|
30
|
+
- 🎨 **29 Modern Components** - Button, ButtonGroup, Alert, Badge, Breadcrumb, Card, Chip, Divider, Accordion, Avatar, AvatarGroup, Tooltip, Link, List, Timeline, Tree, Image, Carousel, Steps, Table, Rating, Progress, Popover, PlayButton, Skeleton, Pagination, DatePicker, Tab, Input
|
|
31
31
|
- 🌓 **Dark Mode** - Seamless theme switching with full dark mode support
|
|
32
32
|
- 🔮 **Glass Morphism** - Beautiful backdrop blur effects across components
|
|
33
33
|
- 🎯 **Type-Safe** - Full TypeScript support with comprehensive prop types
|
|
@@ -139,22 +139,502 @@ import { cn } from "saha-ui/lib/utils";
|
|
|
139
139
|
|
|
140
140
|
### Overview
|
|
141
141
|
|
|
142
|
-
| Component | Description
|
|
143
|
-
| --------------- |
|
|
144
|
-
| **Button** | Action buttons with
|
|
145
|
-
| **ButtonGroup** | Grouped buttons with horizontal/vertical layouts
|
|
146
|
-
| **Alert** | Notification messages with 5 variants × 4 statuses
|
|
147
|
-
| **Badge** | Status indicators and labels with 9 variants
|
|
148
|
-
| **Breadcrumb** | Navigation trail with 5 variants, 4 separators, and collapsing
|
|
149
|
-
| **Card** | Container with 5 variants and sub-components
|
|
150
|
-
| **
|
|
151
|
-
| **
|
|
152
|
-
| **
|
|
153
|
-
| **
|
|
154
|
-
| **
|
|
155
|
-
| **
|
|
156
|
-
| **
|
|
157
|
-
| **
|
|
142
|
+
| Component | Description | Status | CVA |
|
|
143
|
+
| --------------- | ------------------------------------------------------------------------ | ------ | --- |
|
|
144
|
+
| **Button** | Action buttons with 9 variants and 4 sizes | ✅ | ✅ |
|
|
145
|
+
| **ButtonGroup** | Grouped buttons with horizontal/vertical layouts | ✅ | ✅ |
|
|
146
|
+
| **Alert** | Notification messages with 5 variants × 4 statuses | ✅ | ✅ |
|
|
147
|
+
| **Badge** | Status indicators and labels with 9 variants | ✅ | ✅ |
|
|
148
|
+
| **Breadcrumb** | Navigation trail with 5 variants, 4 separators, and collapsing | ✅ | ✅ |
|
|
149
|
+
| **Card** | Container with 5 variants and sub-components | ✅ | ✅ |
|
|
150
|
+
| **Chip** | Interactive tags with 5 variants, deletable, and avatars | ✅ | ✅ |
|
|
151
|
+
| **Divider** | Content separator with 5 variants and label support | ✅ | ✅ |
|
|
152
|
+
| **Accordion** | Collapsible content with 5 behavior modes | ✅ | ✅ |
|
|
153
|
+
| **Avatar** | User profile images with status indicators | ✅ | ✅ |
|
|
154
|
+
| **AvatarGroup** | Grouped avatars with overlap and count | ✅ | ✅ |
|
|
155
|
+
| **Tooltip** | Contextual hints with 9 variants, 4 triggers, and interactive mode | ✅ | ✅ |
|
|
156
|
+
| **Link** | Smart links with 9 variants and icon support | ✅ | ✅ |
|
|
157
|
+
| **List** | Modern lists with 5 variants and icon support | ✅ | ✅ |
|
|
158
|
+
| **Timeline** | Chronological events with 4 variants, positions, and statuses | ✅ | ✅ |
|
|
159
|
+
| **Tree** | Hierarchical data with 4 variants, icons, and expand/collapse | ✅ | ✅ |
|
|
160
|
+
| **Image** | Advanced image with lazy loading | ✅ | ✅ |
|
|
161
|
+
| **Carousel** | Image slider with 4 transition effects | ✅ | ✅ |
|
|
162
|
+
| **Steps** | Progress indicator with 4 variants, horizontal/vertical layouts | ✅ | ✅ |
|
|
163
|
+
| **Table** | Data table with sorting, selection, 5 variants, and responsive | ✅ | ✅ |
|
|
164
|
+
| **Rating** | Star rating with 6 variants, 4 sizes, multiple icons, half stars | ✅ | ✅ |
|
|
165
|
+
| **Progress** | Progress bar with 9 variants, 5 sizes, animations, striped | ✅ | ✅ |
|
|
166
|
+
| **Popover** | Rich content popover with 11 variants, 12 positions, 4 triggers | ✅ | ✅ |
|
|
167
|
+
| **PlayButton** | Animated play/pause button with 9 variants, 4 sizes, smooth transitions | ✅ | ✅ |
|
|
168
|
+
| **Skeleton** | Loading placeholder with 5 variants, 4 shapes, customizable animations | ✅ | ✅ |
|
|
169
|
+
| **Pagination** | Page navigation with 5 variants, 3 sizes, ellipsis, customizable labels | ✅ | ✅ |
|
|
170
|
+
| **DatePicker** | Calendar date picker with 5 variants, 3 sizes, date restrictions | ✅ | ✅ |
|
|
171
|
+
| **Tab** | Tab navigation with 14 variants, 3 sizes, icons, badges, disabled states | ✅ | ✅ |
|
|
172
|
+
| **Input** | Text input with 10 variants, 4 sizes, icons, validation, all input types | ✅ | ✅ |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## ⚡ Quick Examples
|
|
177
|
+
|
|
178
|
+
Here are simple examples for all 29 components to get you started quickly:
|
|
179
|
+
|
|
180
|
+
### Button
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
import { Button } from "saha-ui";
|
|
184
|
+
|
|
185
|
+
<Button variant="primary">Click Me</Button>
|
|
186
|
+
<Button variant="ghost" size="sm">Small Ghost</Button>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### ButtonGroup
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
import { ButtonGroup, Button } from "saha-ui";
|
|
193
|
+
|
|
194
|
+
<ButtonGroup>
|
|
195
|
+
<Button variant="primary">Save</Button>
|
|
196
|
+
<Button variant="ghost">Cancel</Button>
|
|
197
|
+
</ButtonGroup>;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Alert
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
import { Alert } from "saha-ui";
|
|
204
|
+
|
|
205
|
+
<Alert status="success">Operation completed successfully!</Alert>
|
|
206
|
+
<Alert status="error" variant="filled" dismissible>
|
|
207
|
+
Error occurred!
|
|
208
|
+
</Alert>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Badge
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { Badge } from "saha-ui";
|
|
215
|
+
|
|
216
|
+
<Badge variant="primary">New</Badge>
|
|
217
|
+
<Badge variant="success" dot pulse>Online</Badge>
|
|
218
|
+
<Badge removable onRemove={() => console.log('removed')}>Tag</Badge>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Breadcrumb
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
import { Breadcrumb } from "saha-ui";
|
|
225
|
+
|
|
226
|
+
const items = [
|
|
227
|
+
{ label: 'Home', href: '/' },
|
|
228
|
+
{ label: 'Products', href: '/products' },
|
|
229
|
+
{ label: 'Details', href: '/products/123' }
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
<Breadcrumb items={items} />
|
|
233
|
+
<Breadcrumb items={items} variant="pills" separator="arrow" />
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Card
|
|
237
|
+
|
|
238
|
+
```tsx
|
|
239
|
+
import { Card, CardHeader, CardTitle, CardContent } from "saha-ui";
|
|
240
|
+
|
|
241
|
+
<Card variant="glass" hoverable>
|
|
242
|
+
<CardHeader>
|
|
243
|
+
<CardTitle>Card Title</CardTitle>
|
|
244
|
+
</CardHeader>
|
|
245
|
+
<CardContent>Your content here</CardContent>
|
|
246
|
+
</Card>;
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Chip
|
|
250
|
+
|
|
251
|
+
```tsx
|
|
252
|
+
import { Chip } from "saha-ui";
|
|
253
|
+
|
|
254
|
+
<Chip color="primary">JavaScript</Chip>
|
|
255
|
+
<Chip deletable onDelete={() => console.log('deleted')}>
|
|
256
|
+
Remove me
|
|
257
|
+
</Chip>
|
|
258
|
+
<Chip clickable onClick={() => alert('clicked')}>
|
|
259
|
+
Click me
|
|
260
|
+
</Chip>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Divider
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
import { Divider } from "saha-ui";
|
|
267
|
+
|
|
268
|
+
<Divider />
|
|
269
|
+
<Divider label="OR" />
|
|
270
|
+
<Divider variant="gradient" thickness="medium" />
|
|
271
|
+
<Divider orientation="vertical" className="h-24" />
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Accordion
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
import { Accordion } from "saha-ui";
|
|
278
|
+
|
|
279
|
+
const items = [
|
|
280
|
+
{
|
|
281
|
+
title: 'Section 1',
|
|
282
|
+
content: 'Content for section 1'
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
title: 'Section 2',
|
|
286
|
+
content: 'Content for section 2'
|
|
287
|
+
}
|
|
288
|
+
];
|
|
289
|
+
|
|
290
|
+
<Accordion items={items} />
|
|
291
|
+
<Accordion items={items} variant="bordered" defaultOpen={[0]} />
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Avatar
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import { Avatar } from "saha-ui";
|
|
298
|
+
|
|
299
|
+
<Avatar src="/user.jpg" alt="John" />
|
|
300
|
+
<Avatar name="Jane Doe" size="lg" />
|
|
301
|
+
<Avatar name="Bob" status="online" />
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### AvatarGroup
|
|
305
|
+
|
|
306
|
+
```tsx
|
|
307
|
+
import { AvatarGroup, Avatar } from "saha-ui";
|
|
308
|
+
|
|
309
|
+
<AvatarGroup max={3}>
|
|
310
|
+
<Avatar name="Alice" />
|
|
311
|
+
<Avatar name="Bob" />
|
|
312
|
+
<Avatar name="Carol" />
|
|
313
|
+
<Avatar name="Dave" />
|
|
314
|
+
</AvatarGroup>;
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Tooltip
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
import { Tooltip } from "saha-ui";
|
|
321
|
+
|
|
322
|
+
// Basic tooltip
|
|
323
|
+
<Tooltip content="This is a tooltip">
|
|
324
|
+
<Button>Hover me</Button>
|
|
325
|
+
</Tooltip>
|
|
326
|
+
|
|
327
|
+
// With variant and position
|
|
328
|
+
<Tooltip content="Success message!" variant="success" position="right">
|
|
329
|
+
<Badge variant="success">Active</Badge>
|
|
330
|
+
</Tooltip>
|
|
331
|
+
|
|
332
|
+
// Interactive tooltip with click trigger
|
|
333
|
+
<Tooltip
|
|
334
|
+
content={<div>Click <a href="#">here</a> for more</div>}
|
|
335
|
+
interactive={true}
|
|
336
|
+
trigger="click"
|
|
337
|
+
variant="glass"
|
|
338
|
+
>
|
|
339
|
+
<Button>Click Me</Button>
|
|
340
|
+
</Tooltip>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Link
|
|
344
|
+
|
|
345
|
+
```tsx
|
|
346
|
+
import { Link } from "saha-ui";
|
|
347
|
+
|
|
348
|
+
<Link href="/about">About Us</Link>
|
|
349
|
+
<Link href="https://example.com" variant="primary" external>
|
|
350
|
+
External Link
|
|
351
|
+
</Link>
|
|
352
|
+
<Link href="/contact" showIcon>Contact</Link>
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### List
|
|
356
|
+
|
|
357
|
+
```tsx
|
|
358
|
+
import { List } from "saha-ui";
|
|
359
|
+
|
|
360
|
+
const items = [
|
|
361
|
+
{ id: 1, content: 'First item' },
|
|
362
|
+
{ id: 2, content: 'Second item' },
|
|
363
|
+
{ id: 3, content: 'Third item' }
|
|
364
|
+
];
|
|
365
|
+
|
|
366
|
+
<List items={items} />
|
|
367
|
+
<List items={items} variant="bordered" />
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Timeline
|
|
371
|
+
|
|
372
|
+
```tsx
|
|
373
|
+
import { Timeline } from "saha-ui";
|
|
374
|
+
import { Rocket, Package, Check } from "lucide-react";
|
|
375
|
+
|
|
376
|
+
const events = [
|
|
377
|
+
{ id: 1, title: 'Project Started', description: 'Initial setup', time: '2 hours ago', icon: Rocket },
|
|
378
|
+
{ id: 2, title: 'Development', description: 'Building features', time: '1 hour ago', icon: Package, status: 'primary' as const },
|
|
379
|
+
{ id: 3, title: 'Completed', description: 'Ready to deploy', time: 'Just now', icon: Check, status: 'success' as const }
|
|
380
|
+
];
|
|
381
|
+
|
|
382
|
+
<Timeline items={events} />
|
|
383
|
+
<Timeline items={events} variant="gradient" position="alternate" />
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Tree
|
|
387
|
+
|
|
388
|
+
```tsx
|
|
389
|
+
import { Tree } from "saha-ui";
|
|
390
|
+
import { Folder, File } from "lucide-react";
|
|
391
|
+
|
|
392
|
+
const nodes = [
|
|
393
|
+
{
|
|
394
|
+
id: 1,
|
|
395
|
+
label: 'src',
|
|
396
|
+
icon: <Folder size={16} />,
|
|
397
|
+
children: [
|
|
398
|
+
{ id: 2, label: 'components', icon: <Folder size={16} /> },
|
|
399
|
+
{ id: 3, label: 'App.tsx', icon: <File size={16} /> }
|
|
400
|
+
]
|
|
401
|
+
}
|
|
402
|
+
];
|
|
403
|
+
|
|
404
|
+
<Tree nodes={nodes} />
|
|
405
|
+
<Tree nodes={nodes} variant="glass" onNodeClick={(id) => console.log(id)} />
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Image
|
|
409
|
+
|
|
410
|
+
```tsx
|
|
411
|
+
import { Image } from "saha-ui";
|
|
412
|
+
|
|
413
|
+
<Image
|
|
414
|
+
src="/photo.jpg"
|
|
415
|
+
alt="Description"
|
|
416
|
+
variant="rounded"
|
|
417
|
+
/>
|
|
418
|
+
|
|
419
|
+
<Image
|
|
420
|
+
src="/photo.jpg"
|
|
421
|
+
alt="Description"
|
|
422
|
+
fit="cover"
|
|
423
|
+
size="lg"
|
|
424
|
+
loading="lazy"
|
|
425
|
+
/>
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Carousel
|
|
429
|
+
|
|
430
|
+
```tsx
|
|
431
|
+
import { Carousel } from "saha-ui";
|
|
432
|
+
|
|
433
|
+
const images = [
|
|
434
|
+
{ src: '/image1.jpg', alt: 'Image 1' },
|
|
435
|
+
{ src: '/image2.jpg', alt: 'Image 2' },
|
|
436
|
+
{ src: '/image3.jpg', alt: 'Image 3' }
|
|
437
|
+
];
|
|
438
|
+
|
|
439
|
+
<Carousel images={images} />
|
|
440
|
+
<Carousel images={images} effect="fade" autoplay />
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Steps
|
|
444
|
+
|
|
445
|
+
```tsx
|
|
446
|
+
import { Steps } from "saha-ui";
|
|
447
|
+
|
|
448
|
+
const steps = [
|
|
449
|
+
{ id: 1, title: 'Account', description: 'Create your account' },
|
|
450
|
+
{ id: 2, title: 'Profile', description: 'Fill in your details' },
|
|
451
|
+
{ id: 3, title: 'Complete', description: 'You're all set!' }
|
|
452
|
+
];
|
|
453
|
+
|
|
454
|
+
<Steps steps={steps} current={1} />
|
|
455
|
+
<Steps steps={steps} current={1} variant="glass" orientation="vertical" />
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### Table
|
|
459
|
+
|
|
460
|
+
```tsx
|
|
461
|
+
import { Table } from "saha-ui";
|
|
462
|
+
|
|
463
|
+
const columns = [
|
|
464
|
+
{ id: 'name', header: 'Name', accessor: 'name', sortable: true },
|
|
465
|
+
{ id: 'email', header: 'Email', accessor: 'email' },
|
|
466
|
+
{ id: 'role', header: 'Role', accessor: 'role' }
|
|
467
|
+
];
|
|
468
|
+
|
|
469
|
+
const data = [
|
|
470
|
+
{ id: 1, name: 'Alice', email: 'alice@example.com', role: 'Admin' },
|
|
471
|
+
{ id: 2, name: 'Bob', email: 'bob@example.com', role: 'User' }
|
|
472
|
+
];
|
|
473
|
+
|
|
474
|
+
<Table columns={columns} data={data} sortable />
|
|
475
|
+
<Table columns={columns} data={data} variant="glass" selectable />
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Rating
|
|
479
|
+
|
|
480
|
+
```tsx
|
|
481
|
+
import { Rating } from "saha-ui";
|
|
482
|
+
|
|
483
|
+
<Rating value={4} />
|
|
484
|
+
<Rating value={4.5} precision="half" showValue count={128} />
|
|
485
|
+
<Rating value={0} onChange={(value) => console.log(value)} size="lg" />
|
|
486
|
+
<Rating value={4} icon="heart" variant="gradient" size="lg" />
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### Progress
|
|
490
|
+
|
|
491
|
+
```tsx
|
|
492
|
+
import { Progress } from "saha-ui";
|
|
493
|
+
|
|
494
|
+
<Progress value={75} />
|
|
495
|
+
<Progress value={60} variant="primary" size="lg" showValue />
|
|
496
|
+
<Progress value={80} variant="success" striped stripedAnimated />
|
|
497
|
+
<Progress indeterminate variant="gradient" />
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Popover
|
|
501
|
+
|
|
502
|
+
```tsx
|
|
503
|
+
import { Popover, Button } from "saha-ui";
|
|
504
|
+
|
|
505
|
+
<Popover content="Simple popover content">
|
|
506
|
+
<Button>Click me</Button>
|
|
507
|
+
</Popover>
|
|
508
|
+
|
|
509
|
+
<Popover
|
|
510
|
+
title="Settings"
|
|
511
|
+
variant="primary"
|
|
512
|
+
position="right"
|
|
513
|
+
content={<div>Your settings here</div>}
|
|
514
|
+
footer={<Button size="sm">Save</Button>}
|
|
515
|
+
>
|
|
516
|
+
<Button>Open Settings</Button>
|
|
517
|
+
</Popover>
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### PlayButton
|
|
521
|
+
|
|
522
|
+
```tsx
|
|
523
|
+
import { PlayButton } from "saha-ui";
|
|
524
|
+
|
|
525
|
+
<PlayButton />
|
|
526
|
+
|
|
527
|
+
<PlayButton variant="primary" size="lg" />
|
|
528
|
+
|
|
529
|
+
<PlayButton
|
|
530
|
+
isPlaying={playing}
|
|
531
|
+
onToggle={(playing) => setPlaying(playing)}
|
|
532
|
+
variant="success"
|
|
533
|
+
pulse
|
|
534
|
+
glow
|
|
535
|
+
/>
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### Skeleton
|
|
539
|
+
|
|
540
|
+
```tsx
|
|
541
|
+
import { Skeleton } from "saha-ui";
|
|
542
|
+
|
|
543
|
+
<Skeleton width="100%" height="20px" />
|
|
544
|
+
|
|
545
|
+
<Skeleton variant="shimmer" count={3} />
|
|
546
|
+
|
|
547
|
+
<Skeleton shape="circle" width="48px" height="48px" variant="pulse" />
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### Pagination
|
|
551
|
+
|
|
552
|
+
```tsx
|
|
553
|
+
import { Pagination } from "saha-ui";
|
|
554
|
+
|
|
555
|
+
<Pagination totalPages={10} currentPage={1} onPageChange={(page) => setPage(page)} />
|
|
556
|
+
|
|
557
|
+
<Pagination variant="primary" size="lg" totalPages={20} currentPage={5} />
|
|
558
|
+
|
|
559
|
+
<Pagination variant="minimal" shape="pill" totalPages={50} currentPage={25} />
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
### DatePicker
|
|
563
|
+
|
|
564
|
+
```tsx
|
|
565
|
+
import { DatePicker } from "saha-ui";
|
|
566
|
+
|
|
567
|
+
<DatePicker value={date} onChange={(date) => setDate(date)} />
|
|
568
|
+
|
|
569
|
+
<DatePicker variant="primary" size="lg" placeholder="Pick a date" />
|
|
570
|
+
|
|
571
|
+
<DatePicker minDate={new Date()} maxDate={futureDate} />
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Tab
|
|
575
|
+
|
|
576
|
+
```tsx
|
|
577
|
+
import { Tab } from "saha-ui";
|
|
578
|
+
|
|
579
|
+
const tabs = [
|
|
580
|
+
{ label: "Profile", value: "profile" },
|
|
581
|
+
{ label: "Settings", value: "settings" },
|
|
582
|
+
];
|
|
583
|
+
|
|
584
|
+
<Tab tabs={tabs} value={activeTab} onChange={setActiveTab} />
|
|
585
|
+
|
|
586
|
+
<Tab tabs={tabs} variant="primary" size="lg" fullWidth />
|
|
587
|
+
|
|
588
|
+
<Tab
|
|
589
|
+
tabs={[
|
|
590
|
+
{ label: "Home", value: "home", icon: <HomeIcon /> },
|
|
591
|
+
{ label: "Messages", value: "messages", badge: "5" },
|
|
592
|
+
]}
|
|
593
|
+
/>
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### Input
|
|
597
|
+
|
|
598
|
+
```tsx
|
|
599
|
+
import { Input } from "saha-ui";
|
|
600
|
+
import { Mail, Lock } from "lucide-react";
|
|
601
|
+
|
|
602
|
+
// Basic input
|
|
603
|
+
<Input placeholder="Enter text..." />
|
|
604
|
+
|
|
605
|
+
// With label and variant
|
|
606
|
+
<Input
|
|
607
|
+
label="Email"
|
|
608
|
+
type="email"
|
|
609
|
+
variant="primary"
|
|
610
|
+
placeholder="you@example.com"
|
|
611
|
+
/>
|
|
612
|
+
|
|
613
|
+
// With icons
|
|
614
|
+
<Input
|
|
615
|
+
label="Search"
|
|
616
|
+
variant="outline"
|
|
617
|
+
startIcon={<Mail size={18} />}
|
|
618
|
+
placeholder="Search..."
|
|
619
|
+
/>
|
|
620
|
+
|
|
621
|
+
// With validation
|
|
622
|
+
<Input
|
|
623
|
+
label="Password"
|
|
624
|
+
type="password"
|
|
625
|
+
variant="error"
|
|
626
|
+
error="Password is required"
|
|
627
|
+
startIcon={<Lock size={18} />}
|
|
628
|
+
/>
|
|
629
|
+
|
|
630
|
+
// With character counter
|
|
631
|
+
<Input
|
|
632
|
+
label="Bio"
|
|
633
|
+
maxLength={100}
|
|
634
|
+
showCounter
|
|
635
|
+
helperText="Maximum 100 characters"
|
|
636
|
+
/>
|
|
637
|
+
```
|
|
158
638
|
|
|
159
639
|
---
|
|
160
640
|
|
|
@@ -162,9 +642,9 @@ import { cn } from "saha-ui/lib/utils";
|
|
|
162
642
|
|
|
163
643
|
### Button
|
|
164
644
|
|
|
165
|
-
Action buttons with modern effects and
|
|
645
|
+
Action buttons with modern effects and 9 visual variants.
|
|
166
646
|
|
|
167
|
-
**Variants:** `primary` `secondary` `accent` `success` `warning` `error` `ghost` `glass`
|
|
647
|
+
**Variants:** `primary` `secondary` `accent` `success` `warning` `error` `outline` `ghost` `glass`
|
|
168
648
|
**Sizes:** `sm` `md` `lg` `xl`
|
|
169
649
|
|
|
170
650
|
```tsx
|
|
@@ -630,51 +1110,423 @@ const customClass = cardVariants({ variant: 'glass-strong', padding: 'xl', round
|
|
|
630
1110
|
|
|
631
1111
|
---
|
|
632
1112
|
|
|
633
|
-
###
|
|
1113
|
+
### Chip
|
|
634
1114
|
|
|
635
|
-
|
|
1115
|
+
Interactive tag component with multiple variants, deletable functionality, and icon/avatar support.
|
|
636
1116
|
|
|
637
|
-
**Variants:** `
|
|
1117
|
+
**Variants:** `filled` `outlined` `soft` `gradient` `glass`
|
|
1118
|
+
**Colors:** `default` `primary` `secondary` `success` `warning` `error` `info`
|
|
638
1119
|
**Sizes:** `sm` `md` `lg`
|
|
639
1120
|
|
|
640
1121
|
```tsx
|
|
641
|
-
import {
|
|
1122
|
+
import { Chip } from "saha-ui";
|
|
642
1123
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
<AccordionTrigger>Item 1</AccordionTrigger>
|
|
646
|
-
<AccordionContent>Content for item 1</AccordionContent>
|
|
647
|
-
</AccordionItem>
|
|
648
|
-
<AccordionItem value="item-2">
|
|
649
|
-
<AccordionTrigger>Item 2</AccordionTrigger>
|
|
650
|
-
<AccordionContent>Content for item 2</AccordionContent>
|
|
651
|
-
</AccordionItem>
|
|
652
|
-
</Accordion>;
|
|
653
|
-
```
|
|
1124
|
+
// Basic chip
|
|
1125
|
+
<Chip>JavaScript</Chip>
|
|
654
1126
|
|
|
655
|
-
|
|
1127
|
+
// With color and variant
|
|
1128
|
+
<Chip color="primary" variant="filled">Premium</Chip>
|
|
656
1129
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
- ♿ Fully accessible with ARIA attributes
|
|
1130
|
+
// Deletable chip
|
|
1131
|
+
<Chip deletable onDelete={() => console.log('deleted')}>
|
|
1132
|
+
Remove me
|
|
1133
|
+
</Chip>
|
|
662
1134
|
|
|
663
|
-
|
|
1135
|
+
// With icon
|
|
1136
|
+
import { Tag } from "lucide-react";
|
|
1137
|
+
<Chip icon={<Tag size={14} />} color="success">
|
|
1138
|
+
Tagged
|
|
1139
|
+
</Chip>
|
|
664
1140
|
|
|
665
|
-
|
|
1141
|
+
// With avatar
|
|
1142
|
+
<Chip avatar={<Avatar size="xs" src="..." />}>
|
|
1143
|
+
John Doe
|
|
1144
|
+
</Chip>
|
|
666
1145
|
|
|
667
|
-
|
|
1146
|
+
// Clickable chip
|
|
1147
|
+
<Chip clickable onClick={() => console.log('clicked')}>
|
|
1148
|
+
Click me
|
|
1149
|
+
</Chip>
|
|
668
1150
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
1151
|
+
// Different sizes
|
|
1152
|
+
<Chip size="sm">Small</Chip>
|
|
1153
|
+
<Chip size="lg">Large</Chip>
|
|
672
1154
|
|
|
673
|
-
|
|
674
|
-
|
|
1155
|
+
// Disabled state
|
|
1156
|
+
<Chip disabled color="error">Disabled</Chip>
|
|
1157
|
+
|
|
1158
|
+
// Combined features
|
|
1159
|
+
<Chip
|
|
1160
|
+
avatar={<Avatar size="xs" name="Alice" />}
|
|
1161
|
+
deletable
|
|
1162
|
+
onDelete={() => handleRemove()}
|
|
1163
|
+
color="primary"
|
|
1164
|
+
variant="outlined"
|
|
1165
|
+
>
|
|
1166
|
+
Alice
|
|
1167
|
+
</Chip>
|
|
1168
|
+
```
|
|
675
1169
|
|
|
676
|
-
|
|
677
|
-
|
|
1170
|
+
**Features:**
|
|
1171
|
+
|
|
1172
|
+
- ✨ **5 Modern Variants** - filled, outlined, soft, gradient, glass
|
|
1173
|
+
- 🎨 **7 Color Options** - comprehensive color palette
|
|
1174
|
+
- 📏 **3 Size Options** - sm, md, lg for different contexts
|
|
1175
|
+
- 🗑️ **Deletable** - built-in close button with callback
|
|
1176
|
+
- 🖼️ **Avatar Support** - integrate user avatars seamlessly
|
|
1177
|
+
- 🎯 **Icon Support** - add icons for visual context
|
|
1178
|
+
- 👆 **Clickable** - interactive chips with hover effects
|
|
1179
|
+
- ♿ **Accessible** - keyboard navigation and ARIA support
|
|
1180
|
+
- 🎭 **CVA Powered** - type-safe variant composition
|
|
1181
|
+
- 🌓 **Dark Mode** - fully themed for light and dark modes
|
|
1182
|
+
- 💫 **Interactive States** - hover, active, and disabled states
|
|
1183
|
+
|
|
1184
|
+
**Variant Details:**
|
|
1185
|
+
|
|
1186
|
+
- **filled** - Solid background with vibrant colors (default)
|
|
1187
|
+
- **outlined** - Border-only design with transparent background
|
|
1188
|
+
- **soft** - Subtle background with soft color tones
|
|
1189
|
+
- **gradient** - Gradient background with depth
|
|
1190
|
+
- **glass** - Glassmorphism effect with backdrop blur
|
|
1191
|
+
|
|
1192
|
+
**Props:**
|
|
1193
|
+
|
|
1194
|
+
```tsx
|
|
1195
|
+
interface ChipProps {
|
|
1196
|
+
variant?: "filled" | "outlined" | "soft" | "gradient" | "glass";
|
|
1197
|
+
color?:
|
|
1198
|
+
| "default"
|
|
1199
|
+
| "primary"
|
|
1200
|
+
| "secondary"
|
|
1201
|
+
| "success"
|
|
1202
|
+
| "warning"
|
|
1203
|
+
| "error"
|
|
1204
|
+
| "info";
|
|
1205
|
+
size?: "sm" | "md" | "lg";
|
|
1206
|
+
icon?: React.ReactNode; // Optional icon at start
|
|
1207
|
+
avatar?: React.ReactNode; // Optional avatar at start
|
|
1208
|
+
deletable?: boolean; // Show delete button
|
|
1209
|
+
onDelete?: () => void; // Delete callback
|
|
1210
|
+
disabled?: boolean; // Disable interactions
|
|
1211
|
+
clickable?: boolean; // Enable click interactions
|
|
1212
|
+
onClick?: () => void; // Click handler
|
|
1213
|
+
className?: string;
|
|
1214
|
+
}
|
|
1215
|
+
```
|
|
1216
|
+
|
|
1217
|
+
**Advanced Usage:**
|
|
1218
|
+
|
|
1219
|
+
```tsx
|
|
1220
|
+
// Tag management system
|
|
1221
|
+
<div className="flex flex-wrap gap-2">
|
|
1222
|
+
{tags.map((tag) => (
|
|
1223
|
+
<Chip
|
|
1224
|
+
key={tag.id}
|
|
1225
|
+
deletable
|
|
1226
|
+
onDelete={() => removeTag(tag.id)}
|
|
1227
|
+
color="primary"
|
|
1228
|
+
variant="soft"
|
|
1229
|
+
>
|
|
1230
|
+
{tag.name}
|
|
1231
|
+
</Chip>
|
|
1232
|
+
))}
|
|
1233
|
+
</div>
|
|
1234
|
+
|
|
1235
|
+
// User selection with avatars
|
|
1236
|
+
<div className="flex flex-wrap gap-2">
|
|
1237
|
+
{selectedUsers.map((user) => (
|
|
1238
|
+
<Chip
|
|
1239
|
+
key={user.id}
|
|
1240
|
+
avatar={<Avatar size="xs" src={user.avatar} name={user.name} />}
|
|
1241
|
+
deletable
|
|
1242
|
+
onDelete={() => removeUser(user.id)}
|
|
1243
|
+
variant="outlined"
|
|
1244
|
+
color="primary"
|
|
1245
|
+
>
|
|
1246
|
+
{user.name}
|
|
1247
|
+
</Chip>
|
|
1248
|
+
))}
|
|
1249
|
+
</div>
|
|
1250
|
+
|
|
1251
|
+
// Filter chips
|
|
1252
|
+
<div className="flex flex-wrap gap-2">
|
|
1253
|
+
<Chip
|
|
1254
|
+
clickable
|
|
1255
|
+
onClick={() => setFilter('all')}
|
|
1256
|
+
color={filter === 'all' ? 'primary' : 'default'}
|
|
1257
|
+
variant={filter === 'all' ? 'filled' : 'outlined'}
|
|
1258
|
+
>
|
|
1259
|
+
All
|
|
1260
|
+
</Chip>
|
|
1261
|
+
<Chip
|
|
1262
|
+
clickable
|
|
1263
|
+
onClick={() => setFilter('active')}
|
|
1264
|
+
color={filter === 'active' ? 'success' : 'default'}
|
|
1265
|
+
variant={filter === 'active' ? 'filled' : 'outlined'}
|
|
1266
|
+
>
|
|
1267
|
+
Active
|
|
1268
|
+
</Chip>
|
|
1269
|
+
<Chip
|
|
1270
|
+
clickable
|
|
1271
|
+
onClick={() => setFilter('pending')}
|
|
1272
|
+
color={filter === 'pending' ? 'warning' : 'default'}
|
|
1273
|
+
variant={filter === 'pending' ? 'filled' : 'outlined'}
|
|
1274
|
+
>
|
|
1275
|
+
Pending
|
|
1276
|
+
</Chip>
|
|
1277
|
+
</div>
|
|
1278
|
+
|
|
1279
|
+
// Technology stack showcase
|
|
1280
|
+
<div className="space-y-3">
|
|
1281
|
+
<div>
|
|
1282
|
+
<p className="text-sm font-medium mb-2">Frontend</p>
|
|
1283
|
+
<div className="flex flex-wrap gap-2">
|
|
1284
|
+
<Chip icon={<Code size={14} />} color="info" variant="soft">React</Chip>
|
|
1285
|
+
<Chip icon={<Code size={14} />} color="info" variant="soft">Vue</Chip>
|
|
1286
|
+
<Chip icon={<Code size={14} />} color="info" variant="soft">Angular</Chip>
|
|
1287
|
+
</div>
|
|
1288
|
+
</div>
|
|
1289
|
+
<div>
|
|
1290
|
+
<p className="text-sm font-medium mb-2">Backend</p>
|
|
1291
|
+
<div className="flex flex-wrap gap-2">
|
|
1292
|
+
<Chip icon={<Server size={14} />} color="success" variant="soft">Node.js</Chip>
|
|
1293
|
+
<Chip icon={<Server size={14} />} color="success" variant="soft">Python</Chip>
|
|
1294
|
+
<Chip icon={<Server size={14} />} color="success" variant="soft">Go</Chip>
|
|
1295
|
+
</div>
|
|
1296
|
+
</div>
|
|
1297
|
+
</div>
|
|
1298
|
+
```
|
|
1299
|
+
|
|
1300
|
+
**CVA Integration:**
|
|
1301
|
+
|
|
1302
|
+
```tsx
|
|
1303
|
+
import { chipVariants } from "saha-ui";
|
|
1304
|
+
|
|
1305
|
+
// Use exported variants for custom styling
|
|
1306
|
+
const customChipClass = chipVariants({
|
|
1307
|
+
variant: "gradient",
|
|
1308
|
+
color: "primary",
|
|
1309
|
+
size: "lg",
|
|
1310
|
+
clickable: true,
|
|
1311
|
+
});
|
|
1312
|
+
```
|
|
1313
|
+
|
|
1314
|
+
---
|
|
1315
|
+
|
|
1316
|
+
### Divider
|
|
1317
|
+
|
|
1318
|
+
Content separator component with 5 modern variants, optional labels, and decorative elements.
|
|
1319
|
+
|
|
1320
|
+
**Variants:** `solid` `dashed` `dotted` `gradient` `glass`
|
|
1321
|
+
**Orientation:** `horizontal` `vertical`
|
|
1322
|
+
**Thickness:** `thin` `medium` `thick`
|
|
1323
|
+
**Spacing:** `none` `xs` `sm` `md` `lg` `xl`
|
|
1324
|
+
|
|
1325
|
+
```tsx
|
|
1326
|
+
import { Divider } from "saha-ui";
|
|
1327
|
+
|
|
1328
|
+
// Basic divider
|
|
1329
|
+
<Divider />
|
|
1330
|
+
|
|
1331
|
+
// With label
|
|
1332
|
+
<Divider label="OR" />
|
|
1333
|
+
|
|
1334
|
+
// Gradient variant
|
|
1335
|
+
<Divider variant="gradient" thickness="medium" />
|
|
1336
|
+
|
|
1337
|
+
// Vertical divider
|
|
1338
|
+
<div className="flex items-center h-24">
|
|
1339
|
+
<div>Section 1</div>
|
|
1340
|
+
<Divider orientation="vertical" className="h-full" />
|
|
1341
|
+
<div>Section 2</div>
|
|
1342
|
+
</div>
|
|
1343
|
+
|
|
1344
|
+
// Decorative with label
|
|
1345
|
+
<Divider label="Continue Reading" decorative />
|
|
1346
|
+
|
|
1347
|
+
// Custom positioning
|
|
1348
|
+
<Divider label="Section Start" labelPosition="left" variant="dashed" />
|
|
1349
|
+
|
|
1350
|
+
// Different thickness
|
|
1351
|
+
<Divider thickness="thick" variant="solid" />
|
|
1352
|
+
|
|
1353
|
+
// Custom spacing
|
|
1354
|
+
<Divider spacing="xl" variant="gradient" />
|
|
1355
|
+
```
|
|
1356
|
+
|
|
1357
|
+
**Features:**
|
|
1358
|
+
|
|
1359
|
+
- ✨ **5 Modern Variants** - solid, dashed, dotted, gradient, glass
|
|
1360
|
+
- 🔄 **Dual Orientation** - horizontal and vertical support
|
|
1361
|
+
- 📏 **3 Thickness Options** - thin, medium, thick
|
|
1362
|
+
- 🏷️ **Label Support** - optional text labels with positioning
|
|
1363
|
+
- ⭐ **Decorative Elements** - sparkle icons for emphasis
|
|
1364
|
+
- 📐 **Flexible Spacing** - 6 spacing options (none to xl)
|
|
1365
|
+
- 🎨 **Theme-Aware** - OKLCH colors with dark mode support
|
|
1366
|
+
- ♿ **Accessible** - semantic HTML with ARIA roles
|
|
1367
|
+
- 🎭 **CVA Powered** - type-safe variant composition
|
|
1368
|
+
- 📱 **Responsive** - works in any layout context
|
|
1369
|
+
|
|
1370
|
+
**Variant Details:**
|
|
1371
|
+
|
|
1372
|
+
- **solid** - Clean solid line (default)
|
|
1373
|
+
- **dashed** - Dashed line pattern
|
|
1374
|
+
- **dotted** - Dotted line pattern
|
|
1375
|
+
- **gradient** - Smooth gradient transition from transparent to border color
|
|
1376
|
+
- **glass** - Glassmorphism effect with backdrop blur
|
|
1377
|
+
|
|
1378
|
+
**Props:**
|
|
1379
|
+
|
|
1380
|
+
```tsx
|
|
1381
|
+
interface DividerProps {
|
|
1382
|
+
variant?: "solid" | "dashed" | "dotted" | "gradient" | "glass";
|
|
1383
|
+
orientation?: "horizontal" | "vertical";
|
|
1384
|
+
thickness?: "thin" | "medium" | "thick";
|
|
1385
|
+
spacing?: "none" | "xs" | "sm" | "md" | "lg" | "xl";
|
|
1386
|
+
label?: React.ReactNode; // Optional label content
|
|
1387
|
+
labelPosition?: "left" | "center" | "right";
|
|
1388
|
+
decorative?: boolean; // Add sparkle icons
|
|
1389
|
+
className?: string;
|
|
1390
|
+
}
|
|
1391
|
+
```
|
|
1392
|
+
|
|
1393
|
+
**Advanced Usage:**
|
|
1394
|
+
|
|
1395
|
+
```tsx
|
|
1396
|
+
// In forms - separating auth methods
|
|
1397
|
+
<Card>
|
|
1398
|
+
<CardContent>
|
|
1399
|
+
<Button variant="primary" className="w-full">
|
|
1400
|
+
Sign in with Email
|
|
1401
|
+
</Button>
|
|
1402
|
+
|
|
1403
|
+
<Divider label="OR" variant="gradient" spacing="sm" />
|
|
1404
|
+
|
|
1405
|
+
<Button variant="outline" className="w-full">
|
|
1406
|
+
Continue with GitHub
|
|
1407
|
+
</Button>
|
|
1408
|
+
</CardContent>
|
|
1409
|
+
</Card>
|
|
1410
|
+
|
|
1411
|
+
// Content sections with labels
|
|
1412
|
+
<article>
|
|
1413
|
+
<p>Introduction paragraph...</p>
|
|
1414
|
+
|
|
1415
|
+
<Divider
|
|
1416
|
+
label="Section 1"
|
|
1417
|
+
labelPosition="left"
|
|
1418
|
+
variant="dashed"
|
|
1419
|
+
spacing="lg"
|
|
1420
|
+
/>
|
|
1421
|
+
|
|
1422
|
+
<p>Main content...</p>
|
|
1423
|
+
|
|
1424
|
+
<Divider
|
|
1425
|
+
label="Conclusion"
|
|
1426
|
+
labelPosition="left"
|
|
1427
|
+
variant="dashed"
|
|
1428
|
+
spacing="lg"
|
|
1429
|
+
/>
|
|
1430
|
+
|
|
1431
|
+
<p>Summary...</p>
|
|
1432
|
+
|
|
1433
|
+
<Divider decorative spacing="lg" variant="gradient" />
|
|
1434
|
+
</article>
|
|
1435
|
+
|
|
1436
|
+
// Vertical layout sections
|
|
1437
|
+
<div className="flex h-64">
|
|
1438
|
+
<div className="flex-1">Left Panel</div>
|
|
1439
|
+
<Divider
|
|
1440
|
+
orientation="vertical"
|
|
1441
|
+
variant="gradient"
|
|
1442
|
+
className="h-full"
|
|
1443
|
+
/>
|
|
1444
|
+
<div className="flex-1">Right Panel</div>
|
|
1445
|
+
</div>
|
|
1446
|
+
|
|
1447
|
+
// Dashboard sections
|
|
1448
|
+
<div className="flex gap-4 h-48">
|
|
1449
|
+
<Card className="flex-1">Stats 1</Card>
|
|
1450
|
+
<Divider orientation="vertical" variant="glass" className="h-full" />
|
|
1451
|
+
<Card className="flex-1">Stats 2</Card>
|
|
1452
|
+
<Divider orientation="vertical" variant="glass" className="h-full" />
|
|
1453
|
+
<Card className="flex-1">Stats 3</Card>
|
|
1454
|
+
</div>
|
|
1455
|
+
```
|
|
1456
|
+
|
|
1457
|
+
**CVA Integration:**
|
|
1458
|
+
|
|
1459
|
+
```tsx
|
|
1460
|
+
import {
|
|
1461
|
+
dividerVariants,
|
|
1462
|
+
dividerLineVariants,
|
|
1463
|
+
dividerLabelVariants,
|
|
1464
|
+
} from "saha-ui";
|
|
1465
|
+
|
|
1466
|
+
// Use exported variants for custom styling
|
|
1467
|
+
const customContainerClass = dividerVariants({
|
|
1468
|
+
orientation: "horizontal",
|
|
1469
|
+
spacing: "lg",
|
|
1470
|
+
});
|
|
1471
|
+
|
|
1472
|
+
const customLineClass = dividerLineVariants({
|
|
1473
|
+
variant: "gradient",
|
|
1474
|
+
orientation: "horizontal",
|
|
1475
|
+
thickness: "medium",
|
|
1476
|
+
});
|
|
1477
|
+
|
|
1478
|
+
const customLabelClass = dividerLabelVariants({
|
|
1479
|
+
orientation: "horizontal",
|
|
1480
|
+
});
|
|
1481
|
+
```
|
|
1482
|
+
|
|
1483
|
+
---
|
|
1484
|
+
|
|
1485
|
+
### Accordion
|
|
1486
|
+
|
|
1487
|
+
Collapsible content sections with smooth animations and multiple behavior modes.
|
|
1488
|
+
|
|
1489
|
+
**Variants:** `default` `bordered` `flush` `glass`
|
|
1490
|
+
**Sizes:** `sm` `md` `lg`
|
|
1491
|
+
|
|
1492
|
+
```tsx
|
|
1493
|
+
import { Accordion } from "saha-ui";
|
|
1494
|
+
|
|
1495
|
+
<Accordion type="single" collapsible>
|
|
1496
|
+
<AccordionItem value="item-1">
|
|
1497
|
+
<AccordionTrigger>Item 1</AccordionTrigger>
|
|
1498
|
+
<AccordionContent>Content for item 1</AccordionContent>
|
|
1499
|
+
</AccordionItem>
|
|
1500
|
+
<AccordionItem value="item-2">
|
|
1501
|
+
<AccordionTrigger>Item 2</AccordionTrigger>
|
|
1502
|
+
<AccordionContent>Content for item 2</AccordionContent>
|
|
1503
|
+
</AccordionItem>
|
|
1504
|
+
</Accordion>;
|
|
1505
|
+
```
|
|
1506
|
+
|
|
1507
|
+
**Features:**
|
|
1508
|
+
|
|
1509
|
+
- 🎭 Multiple types: single, multiple, toggle
|
|
1510
|
+
- 🚀 Fast open/close animations
|
|
1511
|
+
- 🔒 Collapsible and non-collapsible modes
|
|
1512
|
+
- 🎨 Glass morphism and gradient support
|
|
1513
|
+
- ♿ Fully accessible with ARIA attributes
|
|
1514
|
+
|
|
1515
|
+
---
|
|
1516
|
+
|
|
1517
|
+
### Avatar
|
|
1518
|
+
|
|
1519
|
+
Profile images with status indicators and smart fallbacks.
|
|
1520
|
+
|
|
1521
|
+
**Sizes:** `xs` `sm` `md` `lg` `xl` `2xl`
|
|
1522
|
+
**Shapes:** `circle` `square` `rounded`
|
|
1523
|
+
**Status:** `online` `offline` `away` `busy` `none`
|
|
1524
|
+
|
|
1525
|
+
```tsx
|
|
1526
|
+
import { Avatar } from "saha-ui";
|
|
1527
|
+
|
|
1528
|
+
<Avatar
|
|
1529
|
+
src="/user.jpg"
|
|
678
1530
|
alt="John Doe"
|
|
679
1531
|
size="lg"
|
|
680
1532
|
shape="circle"
|
|
@@ -733,33 +1585,229 @@ import { AvatarGroup } from "saha-ui";
|
|
|
733
1585
|
|
|
734
1586
|
### Tooltip
|
|
735
1587
|
|
|
736
|
-
Contextual hints with smart positioning and
|
|
1588
|
+
Contextual hints and information with smart positioning, multiple trigger types, and interactive capabilities.
|
|
737
1589
|
|
|
738
|
-
**Variants:** `default` `dark` `light` `glass` `primary`
|
|
1590
|
+
**Variants:** `default` `dark` `light` `glass` `primary` `success` `warning` `error` `info`
|
|
739
1591
|
**Positions:** `top` `bottom` `left` `right`
|
|
740
|
-
**Sizes:** `sm` `md` `lg`
|
|
1592
|
+
**Sizes:** `sm` `md` `lg`
|
|
1593
|
+
**Triggers:** `hover` `click` `focus` `manual`
|
|
741
1594
|
|
|
742
1595
|
```tsx
|
|
743
1596
|
import { Tooltip } from "saha-ui";
|
|
744
1597
|
|
|
1598
|
+
// Basic tooltip
|
|
745
1599
|
<Tooltip
|
|
746
1600
|
content="This is helpful information"
|
|
747
1601
|
position="top"
|
|
748
1602
|
variant="glass"
|
|
749
|
-
size="md"
|
|
750
|
-
delay={200}
|
|
751
|
-
arrow
|
|
752
1603
|
>
|
|
753
1604
|
<Button>Hover me</Button>
|
|
754
|
-
</Tooltip
|
|
1605
|
+
</Tooltip>
|
|
1606
|
+
|
|
1607
|
+
// Status tooltips
|
|
1608
|
+
<Tooltip content="All systems operational" variant="success">
|
|
1609
|
+
<Badge variant="success">Active</Badge>
|
|
1610
|
+
</Tooltip>
|
|
1611
|
+
|
|
1612
|
+
<Tooltip content="Warning: Check this!" variant="warning" position="right">
|
|
1613
|
+
<span className="cursor-help">⚠</span>
|
|
1614
|
+
</Tooltip>
|
|
1615
|
+
|
|
1616
|
+
// Interactive tooltip with click trigger
|
|
1617
|
+
<Tooltip
|
|
1618
|
+
content={
|
|
1619
|
+
<div className="space-y-2">
|
|
1620
|
+
<p className="font-semibold">Interactive Content</p>
|
|
1621
|
+
<Button size="sm">Click Me</Button>
|
|
1622
|
+
</div>
|
|
1623
|
+
}
|
|
1624
|
+
interactive={true}
|
|
1625
|
+
trigger="click"
|
|
1626
|
+
variant="glass"
|
|
1627
|
+
maxWidth="200px"
|
|
1628
|
+
>
|
|
1629
|
+
<Button>Click for Options</Button>
|
|
1630
|
+
</Tooltip>
|
|
1631
|
+
|
|
1632
|
+
// Controlled tooltip
|
|
1633
|
+
const [open, setOpen] = useState(false);
|
|
1634
|
+
<Tooltip
|
|
1635
|
+
content="Controlled tooltip"
|
|
1636
|
+
open={open}
|
|
1637
|
+
onOpenChange={setOpen}
|
|
1638
|
+
trigger="manual"
|
|
1639
|
+
>
|
|
1640
|
+
<Button onClick={() => setOpen(!open)}>Toggle</Button>
|
|
1641
|
+
</Tooltip>
|
|
1642
|
+
|
|
1643
|
+
// Help icon tooltips
|
|
1644
|
+
<div className="flex items-center gap-2">
|
|
1645
|
+
<span>Username</span>
|
|
1646
|
+
<Tooltip
|
|
1647
|
+
content="Enter your unique username (3-20 characters)"
|
|
1648
|
+
variant="info"
|
|
1649
|
+
size="sm"
|
|
1650
|
+
>
|
|
1651
|
+
<span className="cursor-help text-muted-foreground">ⓘ</span>
|
|
1652
|
+
</Tooltip>
|
|
1653
|
+
</div>
|
|
1654
|
+
|
|
1655
|
+
// Custom delay and no arrow
|
|
1656
|
+
<Tooltip
|
|
1657
|
+
content="Appears after 1 second"
|
|
1658
|
+
delay={1000}
|
|
1659
|
+
arrow={false}
|
|
1660
|
+
variant="primary"
|
|
1661
|
+
>
|
|
1662
|
+
<Button>Delayed Tooltip</Button>
|
|
1663
|
+
</Tooltip>
|
|
755
1664
|
```
|
|
756
1665
|
|
|
1666
|
+
**Variants:**
|
|
1667
|
+
|
|
1668
|
+
- **default** - Standard tooltip with card background and subtle shadow
|
|
1669
|
+
- **dark** - Dark theme tooltip with deep gray background
|
|
1670
|
+
- **light** - Light theme tooltip, bright background
|
|
1671
|
+
- **glass** - Glass morphism effect with backdrop blur
|
|
1672
|
+
- **primary** - Primary color with brand styling
|
|
1673
|
+
- **success** - Green success indicator
|
|
1674
|
+
- **warning** - Yellow warning indicator
|
|
1675
|
+
- **error** - Red error indicator
|
|
1676
|
+
- **info** - Blue information indicator
|
|
1677
|
+
|
|
757
1678
|
**Features:**
|
|
758
1679
|
|
|
759
|
-
-
|
|
760
|
-
-
|
|
761
|
-
-
|
|
762
|
-
-
|
|
1680
|
+
- 🎨 **9 Modern Variants** - Each optimized for different contexts
|
|
1681
|
+
- 📍 **4 Positions** - Top, bottom, left, right with smart alignment
|
|
1682
|
+
- 🖱️ **4 Trigger Types** - Hover, click, focus, or manual control
|
|
1683
|
+
- ⏱️ **Configurable Delay** - Customizable show delay (default 200ms)
|
|
1684
|
+
- ➡️ **Optional Arrow** - Pointing arrow for better UX
|
|
1685
|
+
- 💫 **Interactive Mode** - Allow interaction with tooltip content
|
|
1686
|
+
- 🎯 **Controlled Mode** - Programmatic control via props
|
|
1687
|
+
- 📏 **3 Sizes** - sm, md, lg with responsive text
|
|
1688
|
+
- 🔮 **Glass Effects** - Beautiful backdrop blur and transparency
|
|
1689
|
+
- 🌙 **Dark Mode** - Optimized for both light and dark themes
|
|
1690
|
+
- ♿ **Accessible** - Proper ARIA attributes and keyboard support
|
|
1691
|
+
- 📦 **Tree-Shakeable** - Import only what you need
|
|
1692
|
+
- 🎭 **Custom Styling** - ClassName props for tooltip and wrapper
|
|
1693
|
+
- 📐 **Adjustable Offset** - Control distance from trigger element
|
|
1694
|
+
- 🚫 **Disable Option** - Conditionally disable tooltips
|
|
1695
|
+
- � **Type-Safe** - Full CVA integration with exported variants
|
|
1696
|
+
|
|
1697
|
+
**Props:**
|
|
1698
|
+
|
|
1699
|
+
- `content`: ReactNode - Tooltip content (required)
|
|
1700
|
+
- `children`: ReactNode - Trigger element (required)
|
|
1701
|
+
- `variant`: 'default' | 'dark' | 'light' | 'glass' | 'primary' | 'success' | 'warning' | 'error' | 'info' (default: 'default')
|
|
1702
|
+
- `position`: 'top' | 'bottom' | 'left' | 'right' (default: 'top')
|
|
1703
|
+
- `size`: 'sm' | 'md' | 'lg' (default: 'md')
|
|
1704
|
+
- `trigger`: 'hover' | 'click' | 'focus' | 'manual' (default: 'hover')
|
|
1705
|
+
- `delay`: number - Show delay in ms (default: 200)
|
|
1706
|
+
- `arrow`: boolean - Show arrow pointer (default: true)
|
|
1707
|
+
- `interactive`: boolean - Allow interaction with content (default: false)
|
|
1708
|
+
- `open`: boolean - Controlled open state
|
|
1709
|
+
- `onOpenChange`: (open: boolean) => void - Open state change callback
|
|
1710
|
+
- `tooltipClassName`: string - Custom tooltip content class
|
|
1711
|
+
- `wrapperClassName`: string - Custom wrapper class
|
|
1712
|
+
- `maxWidth`: string - Maximum width (default: '320px')
|
|
1713
|
+
- `offset`: number - Distance from trigger in px (default: 8)
|
|
1714
|
+
- `disabled`: boolean - Disable tooltip (default: false)
|
|
1715
|
+
- `className`: string - Additional CSS classes
|
|
1716
|
+
|
|
1717
|
+
**Advanced Usage:**
|
|
1718
|
+
|
|
1719
|
+
```tsx
|
|
1720
|
+
// Help system with different variants
|
|
1721
|
+
const HelpTooltips = () => (
|
|
1722
|
+
<div className="space-y-4">
|
|
1723
|
+
<div className="flex items-center gap-2">
|
|
1724
|
+
<span>Email</span>
|
|
1725
|
+
<Tooltip
|
|
1726
|
+
content="We'll never share your email"
|
|
1727
|
+
variant="success"
|
|
1728
|
+
size="sm"
|
|
1729
|
+
>
|
|
1730
|
+
<span className="cursor-help">✓</span>
|
|
1731
|
+
</Tooltip>
|
|
1732
|
+
</div>
|
|
1733
|
+
|
|
1734
|
+
<div className="flex items-center gap-2">
|
|
1735
|
+
<span>Password</span>
|
|
1736
|
+
<Tooltip
|
|
1737
|
+
content="Must be at least 8 characters"
|
|
1738
|
+
variant="warning"
|
|
1739
|
+
size="sm"
|
|
1740
|
+
>
|
|
1741
|
+
<span className="cursor-help">⚠</span>
|
|
1742
|
+
</Tooltip>
|
|
1743
|
+
</div>
|
|
1744
|
+
</div>
|
|
1745
|
+
);
|
|
1746
|
+
|
|
1747
|
+
// Interactive tooltip menu
|
|
1748
|
+
<Tooltip
|
|
1749
|
+
content={
|
|
1750
|
+
<div className="space-y-2 w-48">
|
|
1751
|
+
<p className="font-semibold text-sm">Quick Actions</p>
|
|
1752
|
+
<div className="space-y-1">
|
|
1753
|
+
<Button size="sm" variant="ghost" className="w-full justify-start">
|
|
1754
|
+
Edit
|
|
1755
|
+
</Button>
|
|
1756
|
+
<Button size="sm" variant="ghost" className="w-full justify-start">
|
|
1757
|
+
Share
|
|
1758
|
+
</Button>
|
|
1759
|
+
<Button
|
|
1760
|
+
size="sm"
|
|
1761
|
+
variant="ghost"
|
|
1762
|
+
className="w-full justify-start text-red-500"
|
|
1763
|
+
>
|
|
1764
|
+
Delete
|
|
1765
|
+
</Button>
|
|
1766
|
+
</div>
|
|
1767
|
+
</div>
|
|
1768
|
+
}
|
|
1769
|
+
interactive={true}
|
|
1770
|
+
trigger="click"
|
|
1771
|
+
variant="glass"
|
|
1772
|
+
maxWidth="220px"
|
|
1773
|
+
arrow={false}
|
|
1774
|
+
>
|
|
1775
|
+
<Button size="sm" variant="ghost">
|
|
1776
|
+
⋯
|
|
1777
|
+
</Button>
|
|
1778
|
+
</Tooltip>;
|
|
1779
|
+
|
|
1780
|
+
// Status indicator tooltips
|
|
1781
|
+
const StatusIndicator = ({ status, message }) => (
|
|
1782
|
+
<Tooltip
|
|
1783
|
+
content={message}
|
|
1784
|
+
variant={status === "online" ? "success" : "error"}
|
|
1785
|
+
size="sm"
|
|
1786
|
+
>
|
|
1787
|
+
<Badge variant={status === "online" ? "success" : "error"}>{status}</Badge>
|
|
1788
|
+
</Tooltip>
|
|
1789
|
+
);
|
|
1790
|
+
```
|
|
1791
|
+
|
|
1792
|
+
**CVA Integration:**
|
|
1793
|
+
|
|
1794
|
+
```tsx
|
|
1795
|
+
import { tooltipVariants, arrowVariants } from "saha-ui";
|
|
1796
|
+
|
|
1797
|
+
// Use exported variants for custom styling
|
|
1798
|
+
const customTooltipClass = tooltipVariants({
|
|
1799
|
+
variant: "glass",
|
|
1800
|
+
size: "lg",
|
|
1801
|
+
position: "top",
|
|
1802
|
+
interactive: true,
|
|
1803
|
+
className: "my-custom-class",
|
|
1804
|
+
});
|
|
1805
|
+
|
|
1806
|
+
const customArrowClass = arrowVariants({
|
|
1807
|
+
variant: "primary",
|
|
1808
|
+
position: "bottom",
|
|
1809
|
+
});
|
|
1810
|
+
```
|
|
763
1811
|
|
|
764
1812
|
---
|
|
765
1813
|
|
|
@@ -1031,38 +2079,543 @@ const customItemClass = listItemVariants({
|
|
|
1031
2079
|
|
|
1032
2080
|
---
|
|
1033
2081
|
|
|
1034
|
-
###
|
|
2082
|
+
### Timeline
|
|
1035
2083
|
|
|
1036
|
-
|
|
2084
|
+
Chronological event display with 4 modern variants, flexible positioning, status indicators, and icon support powered by CVA.
|
|
1037
2085
|
|
|
1038
|
-
**Variants:** `default` `
|
|
1039
|
-
**
|
|
1040
|
-
**Sizes:** `
|
|
2086
|
+
**Variants:** `default` `outlined` `gradient` `minimal`
|
|
2087
|
+
**Positions:** `left` `right` `alternate`
|
|
2088
|
+
**Sizes:** `sm` `md` `lg`
|
|
2089
|
+
**Status:** `default` `primary` `success` `warning` `error` `info`
|
|
1041
2090
|
|
|
1042
2091
|
```tsx
|
|
1043
|
-
import {
|
|
2092
|
+
import { Timeline } from 'saha-ui';
|
|
2093
|
+
import { Rocket, Code, Package, Check } from 'lucide-react';
|
|
1044
2094
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
lazy
|
|
1054
|
-
showSkeleton
|
|
1055
|
-
fallbackSrc="/fallback.jpg"
|
|
1056
|
-
/>;
|
|
1057
|
-
```
|
|
2095
|
+
// Basic Timeline
|
|
2096
|
+
<Timeline
|
|
2097
|
+
items={[
|
|
2098
|
+
{ id: 1, title: 'Project Started', description: 'Initial setup', time: '2 hours ago' },
|
|
2099
|
+
{ id: 2, title: 'Development', description: 'Building features', time: '1 hour ago' },
|
|
2100
|
+
{ id: 3, title: 'Completed', description: 'Ready to deploy', time: 'Just now' }
|
|
2101
|
+
]}
|
|
2102
|
+
/>
|
|
1058
2103
|
|
|
1059
|
-
|
|
2104
|
+
// Timeline with Icons
|
|
2105
|
+
<Timeline
|
|
2106
|
+
items={[
|
|
2107
|
+
{ id: 1, title: 'Planning', description: 'Define requirements', time: 'Jan 1', icon: Rocket },
|
|
2108
|
+
{ id: 2, title: 'Development', description: 'Build features', time: 'Jan 15', icon: Code, status: 'primary' },
|
|
2109
|
+
{ id: 3, title: 'Testing', description: 'QA process', time: 'Feb 1', icon: Package, status: 'warning' },
|
|
2110
|
+
{ id: 4, title: 'Launch', description: 'Production ready', time: 'Feb 15', icon: Check, status: 'success' }
|
|
2111
|
+
]}
|
|
2112
|
+
variant="gradient"
|
|
2113
|
+
/>
|
|
1060
2114
|
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
2115
|
+
// Alternate Positioning
|
|
2116
|
+
<Timeline
|
|
2117
|
+
items={[
|
|
2118
|
+
{ id: 1, title: 'Order Placed', description: 'We received your order', time: '2h ago', status: 'success' },
|
|
2119
|
+
{ id: 2, title: 'Processing', description: 'Preparing items', time: '1h ago', status: 'primary', active: true },
|
|
2120
|
+
{ id: 3, title: 'Shipped', description: 'On the way', time: 'Pending', status: 'default' },
|
|
2121
|
+
{ id: 4, title: 'Delivered', description: 'Enjoy your purchase', time: 'Pending', status: 'default' }
|
|
2122
|
+
]}
|
|
2123
|
+
position="alternate"
|
|
2124
|
+
variant="outlined"
|
|
2125
|
+
/>
|
|
2126
|
+
|
|
2127
|
+
// Different Sizes
|
|
2128
|
+
<Timeline
|
|
2129
|
+
items={[
|
|
2130
|
+
{ id: 1, title: 'Small', description: 'Compact view', time: 'Now' },
|
|
2131
|
+
{ id: 2, title: 'Medium', description: 'Default size', time: 'Now' },
|
|
2132
|
+
{ id: 3, title: 'Large', description: 'Spacious layout', time: 'Now' }
|
|
2133
|
+
]}
|
|
2134
|
+
size="lg"
|
|
2135
|
+
/>
|
|
2136
|
+
|
|
2137
|
+
// Left/Right Positioning
|
|
2138
|
+
<Timeline
|
|
2139
|
+
position="right"
|
|
2140
|
+
items={[
|
|
2141
|
+
{ id: 1, title: 'Event 1', description: 'Content aligned right', time: '10:00 AM' },
|
|
2142
|
+
{ id: 2, title: 'Event 2', description: 'All items on right', time: '11:00 AM' }
|
|
2143
|
+
]}
|
|
2144
|
+
/>
|
|
2145
|
+
```
|
|
2146
|
+
|
|
2147
|
+
**Variants:**
|
|
2148
|
+
|
|
2149
|
+
- **default** - Clean design with colored dot and connecting line
|
|
2150
|
+
- **outlined** - Bordered container with subtle background
|
|
2151
|
+
- **gradient** - Vibrant gradient background with enhanced visual appeal
|
|
2152
|
+
- **minimal** - Ultra-clean design with minimal visual elements
|
|
2153
|
+
|
|
2154
|
+
**Features:**
|
|
2155
|
+
|
|
2156
|
+
- 🎨 **4 Modern Variants** - Each with unique visual design
|
|
2157
|
+
- 📍 **3 Positioning Modes** - Left, right, or alternating layout
|
|
2158
|
+
- 🎯 **6 Status Colors** - default, primary, success, warning, error, info
|
|
2159
|
+
- ✨ **Icon Support** - Custom icons with automatic fallbacks (Circle for active, Check for success)
|
|
2160
|
+
- 💫 **Active State** - Enhanced styling with scale and shadow effects
|
|
2161
|
+
- 📏 **3 Sizes** - sm, md, lg with responsive spacing
|
|
2162
|
+
- 🔮 **Smart Layout** - Responsive alternate positioning (left on even, right on odd)
|
|
2163
|
+
- 🌈 **Status Indicators** - Color-coded dots matching status colors
|
|
2164
|
+
- 🎭 **Compound Variants** - Position + size combinations for perfect spacing
|
|
2165
|
+
- 🌙 **Dark Mode** - Optimized colors and contrast for dark theme
|
|
2166
|
+
- ♿ **Accessible** - Semantic HTML with proper ARIA attributes
|
|
2167
|
+
- 📦 **Tree-Shakeable** - Import only what you need
|
|
2168
|
+
- 🎯 **Type-Safe** - Full CVA integration with exported variants
|
|
2169
|
+
- 🎨 **Custom Styling** - Per-item and global className overrides
|
|
2170
|
+
- 🎯 **Dot Shapes** - Circle, square, diamond, ring shapes
|
|
2171
|
+
- 📏 **Line Styles** - Solid, dashed, dotted, gradient
|
|
2172
|
+
- 🎨 **Custom Colors** - Override line and dot colors
|
|
2173
|
+
- 🔄 **Interactive** - Click handlers and custom render functions
|
|
2174
|
+
- 👁️ **Conditional Rendering** - Hide dots/lines per item
|
|
2175
|
+
- 📍 **Flexible Time Display** - Show time on opposite side in alternate mode
|
|
2176
|
+
|
|
2177
|
+
**Props:**
|
|
2178
|
+
|
|
2179
|
+
**TimelineItem Interface:**
|
|
2180
|
+
|
|
2181
|
+
```tsx
|
|
2182
|
+
interface TimelineItem {
|
|
2183
|
+
id: number | string;
|
|
2184
|
+
title: React.ReactNode;
|
|
2185
|
+
description?: React.ReactNode;
|
|
2186
|
+
time?: React.ReactNode;
|
|
2187
|
+
icon?: React.ReactNode;
|
|
2188
|
+
status?: "default" | "primary" | "success" | "warning" | "error" | "info";
|
|
2189
|
+
active?: boolean;
|
|
2190
|
+
// New customization props
|
|
2191
|
+
dotColor?: string; // Custom dot color
|
|
2192
|
+
className?: string; // Custom item className
|
|
2193
|
+
dotClassName?: string; // Custom dot className
|
|
2194
|
+
contentClassName?: string; // Custom content className
|
|
2195
|
+
hideDot?: boolean; // Hide dot for this item
|
|
2196
|
+
hideLine?: boolean; // Hide line after this item
|
|
2197
|
+
}
|
|
2198
|
+
```
|
|
2199
|
+
|
|
2200
|
+
**Timeline Component:**
|
|
2201
|
+
|
|
2202
|
+
- `items`: TimelineItem[] - Array of timeline events (required)
|
|
2203
|
+
- `variant`: 'default' | 'outlined' | 'gradient' | 'minimal' (default: 'default')
|
|
2204
|
+
- `position`: 'left' | 'right' | 'alternate' (default: 'left')
|
|
2205
|
+
- `size`: 'sm' | 'md' | 'lg' (default: 'md')
|
|
2206
|
+
- `className`: string - Additional CSS classes
|
|
2207
|
+
- `itemClassName`: string - Custom class for all items
|
|
2208
|
+
- `dotClassName`: string - Custom class for all dots
|
|
2209
|
+
- `contentClassName`: string - Custom class for all content
|
|
2210
|
+
- `lineClassName`: string - Custom class for the timeline line
|
|
2211
|
+
- `lineStyle`: 'solid' | 'dashed' | 'dotted' | 'gradient' (default: 'solid')
|
|
2212
|
+
- `dotShape`: 'circle' | 'square' | 'diamond' | 'ring' (default: 'circle')
|
|
2213
|
+
- `lineColor`: string - Custom line color
|
|
2214
|
+
- `lineWidth`: string - Line width (default: '2px')
|
|
2215
|
+
- `showTimeOnOppositeSide`: boolean - Show time on opposite side in alternate mode
|
|
2216
|
+
- `hideIcons`: boolean - Hide all icons
|
|
2217
|
+
- `animateOnScroll`: boolean - Animate items on scroll
|
|
2218
|
+
- `renderItem`: (item, index) => ReactNode - Custom render function
|
|
2219
|
+
- `onItemClick`: (item, index) => void - Click handler
|
|
2220
|
+
|
|
2221
|
+
**Advanced Usage:**
|
|
2222
|
+
|
|
2223
|
+
```tsx
|
|
2224
|
+
// Custom Dot Shapes and Line Styles
|
|
2225
|
+
<Timeline
|
|
2226
|
+
dotShape="diamond"
|
|
2227
|
+
lineStyle="dashed"
|
|
2228
|
+
items={[
|
|
2229
|
+
{ id: 1, title: 'Design Phase', time: 'Week 1' },
|
|
2230
|
+
{ id: 2, title: 'Development', time: 'Week 2-4', active: true },
|
|
2231
|
+
{ id: 3, title: 'Testing', time: 'Week 5' }
|
|
2232
|
+
]}
|
|
2233
|
+
/>
|
|
2234
|
+
|
|
2235
|
+
// Custom Colors and Per-Item Styling
|
|
2236
|
+
<Timeline
|
|
2237
|
+
lineColor="#ff6b6b"
|
|
2238
|
+
lineWidth="3px"
|
|
2239
|
+
items={[
|
|
2240
|
+
{
|
|
2241
|
+
id: 1,
|
|
2242
|
+
title: 'Custom Dot Color',
|
|
2243
|
+
dotColor: '#ffd93d',
|
|
2244
|
+
dotClassName: 'shadow-xl',
|
|
2245
|
+
time: 'Now'
|
|
2246
|
+
},
|
|
2247
|
+
{
|
|
2248
|
+
id: 2,
|
|
2249
|
+
title: 'Hidden Dot',
|
|
2250
|
+
hideDot: true,
|
|
2251
|
+
description: 'This item has no dot',
|
|
2252
|
+
time: 'Later'
|
|
2253
|
+
},
|
|
2254
|
+
{
|
|
2255
|
+
id: 3,
|
|
2256
|
+
title: 'No Line After',
|
|
2257
|
+
hideLine: true,
|
|
2258
|
+
time: 'End'
|
|
2259
|
+
}
|
|
2260
|
+
]}
|
|
2261
|
+
/>
|
|
2262
|
+
|
|
2263
|
+
// Interactive Timeline with Click Handler
|
|
2264
|
+
<Timeline
|
|
2265
|
+
onItemClick={(item, index) => {
|
|
2266
|
+
console.log(`Clicked item ${index}:`, item.title);
|
|
2267
|
+
}}
|
|
2268
|
+
items={[
|
|
2269
|
+
{ id: 1, title: 'Clickable Item 1', time: '10:00' },
|
|
2270
|
+
{ id: 2, title: 'Clickable Item 2', time: '11:00' }
|
|
2271
|
+
]}
|
|
2272
|
+
/>
|
|
2273
|
+
|
|
2274
|
+
// Time on Opposite Side (Alternate Mode)
|
|
2275
|
+
<Timeline
|
|
2276
|
+
position="alternate"
|
|
2277
|
+
showTimeOnOppositeSide={true}
|
|
2278
|
+
items={[
|
|
2279
|
+
{ id: 1, title: 'Event 1', description: 'Time shows on opposite side', time: 'Jan 1' },
|
|
2280
|
+
{ id: 2, title: 'Event 2', description: 'Clean, organized layout', time: 'Jan 15' }
|
|
2281
|
+
]}
|
|
2282
|
+
/>
|
|
2283
|
+
|
|
2284
|
+
// Different Dot Shapes
|
|
2285
|
+
<Timeline
|
|
2286
|
+
dotShape="ring"
|
|
2287
|
+
size="lg"
|
|
2288
|
+
items={[
|
|
2289
|
+
{ id: 1, title: 'Ring Shape', status: 'primary' },
|
|
2290
|
+
{ id: 2, title: 'Hollow Center', status: 'success' }
|
|
2291
|
+
]}
|
|
2292
|
+
/>
|
|
2293
|
+
|
|
2294
|
+
<Timeline
|
|
2295
|
+
dotShape="square"
|
|
2296
|
+
items={[
|
|
2297
|
+
{ id: 1, title: 'Square Dots', status: 'info' },
|
|
2298
|
+
{ id: 2, title: 'Modern Look', status: 'warning' }
|
|
2299
|
+
]}
|
|
2300
|
+
/>
|
|
2301
|
+
|
|
2302
|
+
// E-commerce Order Tracking
|
|
2303
|
+
<Timeline
|
|
2304
|
+
variant="outlined"
|
|
2305
|
+
position="alternate"
|
|
2306
|
+
items={[
|
|
2307
|
+
{
|
|
2308
|
+
id: 1,
|
|
2309
|
+
title: 'Order Confirmed',
|
|
2310
|
+
description: 'Your order has been received',
|
|
2311
|
+
time: '2 hours ago',
|
|
2312
|
+
status: 'success',
|
|
2313
|
+
icon: Check
|
|
2314
|
+
},
|
|
2315
|
+
{
|
|
2316
|
+
id: 2,
|
|
2317
|
+
title: 'Processing',
|
|
2318
|
+
description: 'We are preparing your items',
|
|
2319
|
+
time: '1 hour ago',
|
|
2320
|
+
status: 'primary',
|
|
2321
|
+
active: true,
|
|
2322
|
+
icon: Package
|
|
2323
|
+
},
|
|
2324
|
+
{
|
|
2325
|
+
id: 3,
|
|
2326
|
+
title: 'Shipped',
|
|
2327
|
+
description: 'Your order is on the way',
|
|
2328
|
+
time: 'Pending',
|
|
2329
|
+
status: 'default',
|
|
2330
|
+
icon: Rocket
|
|
2331
|
+
}
|
|
2332
|
+
]}
|
|
2333
|
+
/>
|
|
2334
|
+
|
|
2335
|
+
// Project Development Timeline
|
|
2336
|
+
<Timeline
|
|
2337
|
+
variant="gradient"
|
|
2338
|
+
size="lg"
|
|
2339
|
+
items={[
|
|
2340
|
+
{ id: 1, title: 'Sprint Planning', description: 'Q1 2024', icon: Rocket, status: 'success' },
|
|
2341
|
+
{ id: 2, title: 'Development', description: 'Q2 2024', icon: Code, status: 'primary', active: true },
|
|
2342
|
+
{ id: 3, title: 'Testing', description: 'Q3 2024', icon: Package, status: 'warning' },
|
|
2343
|
+
{ id: 4, title: 'Release', description: 'Q4 2024', icon: Check, status: 'default' }
|
|
2344
|
+
]}
|
|
2345
|
+
/>
|
|
2346
|
+
```
|
|
2347
|
+
|
|
2348
|
+
**CVA Integration:**
|
|
2349
|
+
|
|
2350
|
+
```tsx
|
|
2351
|
+
import {
|
|
2352
|
+
timelineVariants,
|
|
2353
|
+
timelineItemVariants,
|
|
2354
|
+
timelineLineVariants,
|
|
2355
|
+
timelineDotVariants,
|
|
2356
|
+
timelineContentVariants,
|
|
2357
|
+
} from "saha-ui";
|
|
2358
|
+
|
|
2359
|
+
// Use exported variants for custom styling
|
|
2360
|
+
const customTimelineClass = timelineVariants({
|
|
2361
|
+
variant: "gradient",
|
|
2362
|
+
className: "my-custom-class",
|
|
2363
|
+
});
|
|
2364
|
+
|
|
2365
|
+
const customItemClass = timelineItemVariants({
|
|
2366
|
+
position: "alternate",
|
|
2367
|
+
size: "lg",
|
|
2368
|
+
className: "hover:scale-105",
|
|
2369
|
+
});
|
|
2370
|
+
|
|
2371
|
+
const customDotClass = timelineDotVariants({
|
|
2372
|
+
status: "success",
|
|
2373
|
+
size: "lg",
|
|
2374
|
+
active: true,
|
|
2375
|
+
});
|
|
2376
|
+
```
|
|
2377
|
+
|
|
2378
|
+
---
|
|
2379
|
+
|
|
2380
|
+
### Tree
|
|
2381
|
+
|
|
2382
|
+
Hierarchical data visualization with expand/collapse functionality.
|
|
2383
|
+
|
|
2384
|
+
**Variants:** `default` `glass` `bordered` `minimal`
|
|
2385
|
+
**Sizes:** `sm` `md` `lg`
|
|
2386
|
+
|
|
2387
|
+
```tsx
|
|
2388
|
+
import { Tree } from "saha-ui";
|
|
2389
|
+
import { Folder, File } from "lucide-react";
|
|
2390
|
+
|
|
2391
|
+
<Tree
|
|
2392
|
+
variant="glass"
|
|
2393
|
+
size="md"
|
|
2394
|
+
showIcons={true}
|
|
2395
|
+
showLines={true}
|
|
2396
|
+
iconPosition="left"
|
|
2397
|
+
onNodeClick={(id) => console.log("Clicked:", id)}
|
|
2398
|
+
onNodeToggle={(id, expanded) => console.log("Toggled:", id, expanded)}
|
|
2399
|
+
nodes={[
|
|
2400
|
+
{
|
|
2401
|
+
id: "src",
|
|
2402
|
+
label: "src",
|
|
2403
|
+
icon: <Folder size={16} />,
|
|
2404
|
+
expanded: true,
|
|
2405
|
+
children: [
|
|
2406
|
+
{
|
|
2407
|
+
id: "components",
|
|
2408
|
+
label: "components",
|
|
2409
|
+
icon: <Folder size={16} />,
|
|
2410
|
+
children: [
|
|
2411
|
+
{ id: "button", label: "Button.tsx", icon: <File size={16} /> },
|
|
2412
|
+
{ id: "card", label: "Card.tsx", icon: <File size={16} /> },
|
|
2413
|
+
],
|
|
2414
|
+
},
|
|
2415
|
+
{ id: "app", label: "App.tsx", icon: <File size={16} /> },
|
|
2416
|
+
],
|
|
2417
|
+
},
|
|
2418
|
+
]}
|
|
2419
|
+
/>;
|
|
2420
|
+
```
|
|
2421
|
+
|
|
2422
|
+
**Props:**
|
|
2423
|
+
|
|
2424
|
+
**Tree Component:**
|
|
2425
|
+
|
|
2426
|
+
- `nodes`: TreeNode[] - Array of tree nodes (required)
|
|
2427
|
+
- `variant`: 'default' | 'glass' | 'bordered' | 'minimal' (default: 'default')
|
|
2428
|
+
- `size`: 'sm' | 'md' | 'lg' (default: 'md')
|
|
2429
|
+
- `className`: string - Additional CSS classes
|
|
2430
|
+
- `nodeClassName`: string - Custom class for all nodes
|
|
2431
|
+
- `iconPosition`: 'left' | 'right' (default: 'left')
|
|
2432
|
+
- `showLines`: boolean - Show connecting lines (default: true)
|
|
2433
|
+
- `showIcons`: boolean - Show node icons (default: true)
|
|
2434
|
+
- `onNodeToggle`: (id, expanded) => void - Callback when node is expanded/collapsed
|
|
2435
|
+
- `onNodeClick`: (id) => void - Callback when node is clicked
|
|
2436
|
+
|
|
2437
|
+
**TreeNode:**
|
|
2438
|
+
|
|
2439
|
+
- `id`: string | number - Unique identifier (required)
|
|
2440
|
+
- `label`: string - Display text (required)
|
|
2441
|
+
- `icon`: ReactNode - Custom icon
|
|
2442
|
+
- `children`: TreeNode[] - Child nodes
|
|
2443
|
+
- `expanded`: boolean - Initial expanded state (default: false)
|
|
2444
|
+
- `disabled`: boolean - Disable interactions
|
|
2445
|
+
- `className`: string - Custom class for this node
|
|
2446
|
+
|
|
2447
|
+
**Advanced Usage:**
|
|
2448
|
+
|
|
2449
|
+
```tsx
|
|
2450
|
+
// File System Explorer
|
|
2451
|
+
<Tree
|
|
2452
|
+
variant="bordered"
|
|
2453
|
+
showIcons={true}
|
|
2454
|
+
onNodeClick={(id) => console.log('Opened:', id)}
|
|
2455
|
+
nodes={[
|
|
2456
|
+
{
|
|
2457
|
+
id: 1,
|
|
2458
|
+
label: 'Documents',
|
|
2459
|
+
icon: <FolderOpen size={16} />,
|
|
2460
|
+
expanded: true,
|
|
2461
|
+
children: [
|
|
2462
|
+
{
|
|
2463
|
+
id: 2,
|
|
2464
|
+
label: 'Work',
|
|
2465
|
+
icon: <Folder size={16} />,
|
|
2466
|
+
children: [
|
|
2467
|
+
{ id: 3, label: 'Resume.pdf', icon: <FileText size={16} /> },
|
|
2468
|
+
{ id: 4, label: 'Cover.docx', icon: <FileText size={16} /> }
|
|
2469
|
+
]
|
|
2470
|
+
},
|
|
2471
|
+
{ id: 5, label: 'Personal', icon: <Folder size={16} /> }
|
|
2472
|
+
]
|
|
2473
|
+
},
|
|
2474
|
+
{
|
|
2475
|
+
id: 6,
|
|
2476
|
+
label: 'Media',
|
|
2477
|
+
icon: <Folder size={16} />,
|
|
2478
|
+
children: [
|
|
2479
|
+
{ id: 7, label: 'photo.jpg', icon: <ImageIcon size={16} /> },
|
|
2480
|
+
{ id: 8, label: 'video.mp4', icon: <Video size={16} /> }
|
|
2481
|
+
]
|
|
2482
|
+
}
|
|
2483
|
+
]}
|
|
2484
|
+
/>
|
|
2485
|
+
|
|
2486
|
+
// Organization Chart
|
|
2487
|
+
<Tree
|
|
2488
|
+
variant="glass"
|
|
2489
|
+
size="lg"
|
|
2490
|
+
nodes={[
|
|
2491
|
+
{
|
|
2492
|
+
id: 'ceo',
|
|
2493
|
+
label: 'CEO',
|
|
2494
|
+
icon: <User size={16} />,
|
|
2495
|
+
expanded: true,
|
|
2496
|
+
children: [
|
|
2497
|
+
{
|
|
2498
|
+
id: 'eng',
|
|
2499
|
+
label: 'Engineering',
|
|
2500
|
+
icon: <Settings size={16} />,
|
|
2501
|
+
children: [
|
|
2502
|
+
{ id: 'fe', label: 'Frontend Team', icon: <Code size={16} /> },
|
|
2503
|
+
{ id: 'be', label: 'Backend Team', icon: <Package size={16} /> }
|
|
2504
|
+
]
|
|
2505
|
+
},
|
|
2506
|
+
{
|
|
2507
|
+
id: 'mkt',
|
|
2508
|
+
label: 'Marketing',
|
|
2509
|
+
icon: <Rocket size={16} />,
|
|
2510
|
+
children: [
|
|
2511
|
+
{ id: 'content', label: 'Content', icon: <FileText size={16} /> }
|
|
2512
|
+
]
|
|
2513
|
+
}
|
|
2514
|
+
]
|
|
2515
|
+
}
|
|
2516
|
+
]}
|
|
2517
|
+
/>
|
|
2518
|
+
|
|
2519
|
+
// Without Icons or Lines
|
|
2520
|
+
<Tree
|
|
2521
|
+
showIcons={false}
|
|
2522
|
+
showLines={false}
|
|
2523
|
+
variant="minimal"
|
|
2524
|
+
nodes={[
|
|
2525
|
+
{
|
|
2526
|
+
id: 1,
|
|
2527
|
+
label: 'Parent',
|
|
2528
|
+
children: [
|
|
2529
|
+
{ id: 2, label: 'Child 1' },
|
|
2530
|
+
{ id: 3, label: 'Child 2' }
|
|
2531
|
+
]
|
|
2532
|
+
}
|
|
2533
|
+
]}
|
|
2534
|
+
/>
|
|
2535
|
+
|
|
2536
|
+
// Icon on Right Side
|
|
2537
|
+
<Tree
|
|
2538
|
+
iconPosition="right"
|
|
2539
|
+
nodes={[
|
|
2540
|
+
{
|
|
2541
|
+
id: 1,
|
|
2542
|
+
label: 'Folder',
|
|
2543
|
+
icon: <Folder size={16} />,
|
|
2544
|
+
children: [
|
|
2545
|
+
{ id: 2, label: 'File', icon: <File size={16} /> }
|
|
2546
|
+
]
|
|
2547
|
+
}
|
|
2548
|
+
]}
|
|
2549
|
+
/>
|
|
2550
|
+
|
|
2551
|
+
// With Disabled Nodes
|
|
2552
|
+
<Tree
|
|
2553
|
+
nodes={[
|
|
2554
|
+
{
|
|
2555
|
+
id: 1,
|
|
2556
|
+
label: 'Active',
|
|
2557
|
+
children: [
|
|
2558
|
+
{ id: 2, label: 'Enabled' },
|
|
2559
|
+
{ id: 3, label: 'Disabled', disabled: true }
|
|
2560
|
+
]
|
|
2561
|
+
}
|
|
2562
|
+
]}
|
|
2563
|
+
/>
|
|
2564
|
+
```
|
|
2565
|
+
|
|
2566
|
+
**CVA Integration:**
|
|
2567
|
+
|
|
2568
|
+
```tsx
|
|
2569
|
+
import { treeVariants, treeNodeVariants } from "saha-ui";
|
|
2570
|
+
|
|
2571
|
+
// Use exported variants for custom styling
|
|
2572
|
+
const customTreeClass = treeVariants({
|
|
2573
|
+
variant: "glass",
|
|
2574
|
+
size: "lg",
|
|
2575
|
+
className: "my-custom-class",
|
|
2576
|
+
});
|
|
2577
|
+
|
|
2578
|
+
const customNodeClass = treeNodeVariants({
|
|
2579
|
+
size: "md",
|
|
2580
|
+
expanded: true,
|
|
2581
|
+
className: "hover:bg-accent/20",
|
|
2582
|
+
});
|
|
2583
|
+
```
|
|
2584
|
+
|
|
2585
|
+
---
|
|
2586
|
+
|
|
2587
|
+
### Image
|
|
2588
|
+
|
|
2589
|
+
Advanced image component with loading states and effects.
|
|
2590
|
+
|
|
2591
|
+
**Variants:** `default` `rounded` `circular` `bordered` `glass`
|
|
2592
|
+
**Fit:** `cover` `contain` `fill` `none` `scale-down`
|
|
2593
|
+
**Sizes:** `xs` `sm` `md` `lg` `xl` `2xl` `full`
|
|
2594
|
+
|
|
2595
|
+
```tsx
|
|
2596
|
+
import { Image } from "saha-ui";
|
|
2597
|
+
|
|
2598
|
+
<Image
|
|
2599
|
+
src="/photo.jpg"
|
|
2600
|
+
alt="Beautiful photo"
|
|
2601
|
+
variant="rounded"
|
|
2602
|
+
size="lg"
|
|
2603
|
+
fit="cover"
|
|
2604
|
+
zoomOnHover
|
|
2605
|
+
aspectRatio="16/9"
|
|
2606
|
+
lazy
|
|
2607
|
+
showSkeleton
|
|
2608
|
+
fallbackSrc="/fallback.jpg"
|
|
2609
|
+
/>;
|
|
2610
|
+
```
|
|
2611
|
+
|
|
2612
|
+
**Features:**
|
|
2613
|
+
|
|
2614
|
+
- ⚡ Lazy loading by default
|
|
2615
|
+
- 💀 Animated loading skeleton
|
|
2616
|
+
- 🔄 Smart error handling with fallback
|
|
2617
|
+
- 🔍 Zoom on hover effect
|
|
2618
|
+
- 📐 Aspect ratio control
|
|
1066
2619
|
|
|
1067
2620
|
---
|
|
1068
2621
|
|
|
@@ -1117,6 +2670,1420 @@ import { Carousel } from "saha-ui";
|
|
|
1117
2670
|
|
|
1118
2671
|
---
|
|
1119
2672
|
|
|
2673
|
+
### Steps
|
|
2674
|
+
|
|
2675
|
+
Progress indicator for multi-step processes and wizards.
|
|
2676
|
+
|
|
2677
|
+
**Variants:** `default` `bordered` `glass` `minimal`
|
|
2678
|
+
**Orientation:** `horizontal` `vertical`
|
|
2679
|
+
**Sizes:** `sm` `md` `lg`
|
|
2680
|
+
**Status:** `completed` `current` `pending` `error`
|
|
2681
|
+
|
|
2682
|
+
```tsx
|
|
2683
|
+
import { Steps } from "saha-ui";
|
|
2684
|
+
|
|
2685
|
+
<Steps
|
|
2686
|
+
steps={[
|
|
2687
|
+
{
|
|
2688
|
+
id: 1,
|
|
2689
|
+
title: "Account",
|
|
2690
|
+
description: "Create your account",
|
|
2691
|
+
status: "completed",
|
|
2692
|
+
},
|
|
2693
|
+
{
|
|
2694
|
+
id: 2,
|
|
2695
|
+
title: "Profile",
|
|
2696
|
+
description: "Fill in your details",
|
|
2697
|
+
status: "current",
|
|
2698
|
+
},
|
|
2699
|
+
{
|
|
2700
|
+
id: 3,
|
|
2701
|
+
title: "Verification",
|
|
2702
|
+
description: "Verify your email",
|
|
2703
|
+
status: "pending",
|
|
2704
|
+
},
|
|
2705
|
+
]}
|
|
2706
|
+
current={1}
|
|
2707
|
+
variant="glass"
|
|
2708
|
+
size="md"
|
|
2709
|
+
orientation="horizontal"
|
|
2710
|
+
showNumbers
|
|
2711
|
+
showConnector
|
|
2712
|
+
clickable
|
|
2713
|
+
onStepClick={(index) => console.log("Step clicked:", index)}
|
|
2714
|
+
/>;
|
|
2715
|
+
|
|
2716
|
+
// Vertical with custom icons
|
|
2717
|
+
import { User, CreditCard, Check } from "lucide-react";
|
|
2718
|
+
|
|
2719
|
+
<Steps
|
|
2720
|
+
steps={[
|
|
2721
|
+
{
|
|
2722
|
+
id: 1,
|
|
2723
|
+
title: "Personal Info",
|
|
2724
|
+
description: "Your details",
|
|
2725
|
+
icon: <User className="w-5 h-5" />,
|
|
2726
|
+
},
|
|
2727
|
+
{
|
|
2728
|
+
id: 2,
|
|
2729
|
+
title: "Payment",
|
|
2730
|
+
description: "Billing info",
|
|
2731
|
+
icon: <CreditCard className="w-5 h-5" />,
|
|
2732
|
+
},
|
|
2733
|
+
{
|
|
2734
|
+
id: 3,
|
|
2735
|
+
title: "Complete",
|
|
2736
|
+
description: "All done",
|
|
2737
|
+
icon: <Check className="w-5 h-5" />,
|
|
2738
|
+
},
|
|
2739
|
+
]}
|
|
2740
|
+
orientation="vertical"
|
|
2741
|
+
variant="bordered"
|
|
2742
|
+
/>;
|
|
2743
|
+
```
|
|
2744
|
+
|
|
2745
|
+
**Features:**
|
|
2746
|
+
|
|
2747
|
+
- ✅ Horizontal and vertical layouts
|
|
2748
|
+
- 🎨 4 visual variants with glassmorphism
|
|
2749
|
+
- 📏 3 size options
|
|
2750
|
+
- 🔢 Auto-numbered or custom icons
|
|
2751
|
+
- 📍 Status indicators (completed, current, pending, error)
|
|
2752
|
+
- 🖱️ Clickable navigation
|
|
2753
|
+
- 📝 Optional descriptions
|
|
2754
|
+
- 🔗 Connector lines between steps
|
|
2755
|
+
- 🎭 Smooth transitions
|
|
2756
|
+
|
|
2757
|
+
---
|
|
2758
|
+
|
|
2759
|
+
### Table
|
|
2760
|
+
|
|
2761
|
+
Data table component with sorting, selection, and responsive design.
|
|
2762
|
+
|
|
2763
|
+
**Variants:** `default` `bordered` `striped` `glass` `minimal`
|
|
2764
|
+
**Sizes:** `sm` `md` `lg`
|
|
2765
|
+
**Density:** `compact` `normal` `comfortable`
|
|
2766
|
+
|
|
2767
|
+
```tsx
|
|
2768
|
+
import { Table } from "saha-ui";
|
|
2769
|
+
import { Badge, Avatar } from "saha-ui";
|
|
2770
|
+
|
|
2771
|
+
// Define columns
|
|
2772
|
+
const columns = [
|
|
2773
|
+
{
|
|
2774
|
+
id: "user",
|
|
2775
|
+
header: "User",
|
|
2776
|
+
cell: (row: any) => (
|
|
2777
|
+
<div className="flex items-center gap-3">
|
|
2778
|
+
<Avatar src={row.avatar} alt={row.name} size="sm" />
|
|
2779
|
+
<div>
|
|
2780
|
+
<div className="font-medium">{row.name}</div>
|
|
2781
|
+
<div className="text-sm text-muted-foreground">{row.email}</div>
|
|
2782
|
+
</div>
|
|
2783
|
+
</div>
|
|
2784
|
+
),
|
|
2785
|
+
sortable: true,
|
|
2786
|
+
sortFn: (a, b) => a.name.localeCompare(b.name),
|
|
2787
|
+
},
|
|
2788
|
+
{
|
|
2789
|
+
id: "role",
|
|
2790
|
+
header: "Role",
|
|
2791
|
+
accessor: "role",
|
|
2792
|
+
sortable: true,
|
|
2793
|
+
},
|
|
2794
|
+
{
|
|
2795
|
+
id: "status",
|
|
2796
|
+
header: "Status",
|
|
2797
|
+
cell: (row: any) => (
|
|
2798
|
+
<Badge variant={row.status === "active" ? "success" : "warning"}>
|
|
2799
|
+
{row.status}
|
|
2800
|
+
</Badge>
|
|
2801
|
+
),
|
|
2802
|
+
align: "center",
|
|
2803
|
+
},
|
|
2804
|
+
];
|
|
2805
|
+
|
|
2806
|
+
// Sample data
|
|
2807
|
+
const data = [
|
|
2808
|
+
{
|
|
2809
|
+
id: 1,
|
|
2810
|
+
name: "Alice Johnson",
|
|
2811
|
+
email: "alice@example.com",
|
|
2812
|
+
role: "Admin",
|
|
2813
|
+
status: "active",
|
|
2814
|
+
avatar: "https://i.pravatar.cc/150?img=1",
|
|
2815
|
+
},
|
|
2816
|
+
{
|
|
2817
|
+
id: 2,
|
|
2818
|
+
name: "Bob Smith",
|
|
2819
|
+
email: "bob@example.com",
|
|
2820
|
+
role: "Developer",
|
|
2821
|
+
status: "active",
|
|
2822
|
+
avatar: "https://i.pravatar.cc/150?img=2",
|
|
2823
|
+
},
|
|
2824
|
+
];
|
|
2825
|
+
|
|
2826
|
+
// Basic sortable table
|
|
2827
|
+
<Table columns={columns} data={data} sortable hoverable />;
|
|
2828
|
+
|
|
2829
|
+
// Glass variant with selection
|
|
2830
|
+
<Table
|
|
2831
|
+
columns={columns}
|
|
2832
|
+
data={data}
|
|
2833
|
+
variant="glass"
|
|
2834
|
+
selectable
|
|
2835
|
+
selectedRows={[1]}
|
|
2836
|
+
onRowSelect={(selected) => console.log("Selected:", selected)}
|
|
2837
|
+
/>;
|
|
2838
|
+
|
|
2839
|
+
// Compact size with striped rows
|
|
2840
|
+
<Table
|
|
2841
|
+
columns={columns}
|
|
2842
|
+
data={data}
|
|
2843
|
+
variant="striped"
|
|
2844
|
+
size="sm"
|
|
2845
|
+
density="compact"
|
|
2846
|
+
/>;
|
|
2847
|
+
|
|
2848
|
+
// With sticky header and scroll
|
|
2849
|
+
<Table
|
|
2850
|
+
columns={columns}
|
|
2851
|
+
data={data}
|
|
2852
|
+
stickyHeader
|
|
2853
|
+
maxHeight="400px"
|
|
2854
|
+
variant="bordered"
|
|
2855
|
+
/>;
|
|
2856
|
+
|
|
2857
|
+
// With clickable rows
|
|
2858
|
+
<Table
|
|
2859
|
+
columns={columns}
|
|
2860
|
+
data={data}
|
|
2861
|
+
onRowClick={(row) => console.log("Clicked:", row)}
|
|
2862
|
+
hoverable
|
|
2863
|
+
/>;
|
|
2864
|
+
|
|
2865
|
+
// Loading state
|
|
2866
|
+
<Table columns={columns} data={[]} loading />;
|
|
2867
|
+
|
|
2868
|
+
// Empty state
|
|
2869
|
+
<Table
|
|
2870
|
+
columns={columns}
|
|
2871
|
+
data={[]}
|
|
2872
|
+
emptyMessage={
|
|
2873
|
+
<div className="text-center py-8">
|
|
2874
|
+
<p>No data available</p>
|
|
2875
|
+
</div>
|
|
2876
|
+
}
|
|
2877
|
+
/>;
|
|
2878
|
+
```
|
|
2879
|
+
|
|
2880
|
+
**Features:**
|
|
2881
|
+
|
|
2882
|
+
- ✅ Sorting (controlled and uncontrolled)
|
|
2883
|
+
- ☑️ Row selection with callbacks
|
|
2884
|
+
- 🎨 5 visual variants with glassmorphism
|
|
2885
|
+
- 📏 3 size options and 3 density levels
|
|
2886
|
+
- 🎯 Custom cell renderers
|
|
2887
|
+
- 📍 Column alignment (left, center, right)
|
|
2888
|
+
- 📌 Sticky header support
|
|
2889
|
+
- 📱 Responsive with horizontal scroll
|
|
2890
|
+
- 🔄 Loading states (inline and overlay)
|
|
2891
|
+
- 📝 Empty state customization
|
|
2892
|
+
- 🖱️ Clickable rows
|
|
2893
|
+
- 🎭 Hoverable and striped row options
|
|
2894
|
+
- 📊 Footer support
|
|
2895
|
+
- 🎨 Custom row styling
|
|
2896
|
+
|
|
2897
|
+
**Column Options:**
|
|
2898
|
+
|
|
2899
|
+
- `id` - Unique column identifier
|
|
2900
|
+
- `header` - Column header text/component
|
|
2901
|
+
- `accessor` - Property key or accessor function
|
|
2902
|
+
- `cell` - Custom cell renderer function
|
|
2903
|
+
- `width`, `minWidth`, `maxWidth` - Column sizing
|
|
2904
|
+
- `align` - Text alignment (left, center, right)
|
|
2905
|
+
- `sortable` - Enable sorting for column
|
|
2906
|
+
- `sortFn` - Custom sort function
|
|
2907
|
+
- `footer` - Footer content/function
|
|
2908
|
+
- `sticky` - Make column sticky
|
|
2909
|
+
- `className` - Custom classes for header/cell
|
|
2910
|
+
|
|
2911
|
+
---
|
|
2912
|
+
|
|
2913
|
+
### Rating
|
|
2914
|
+
|
|
2915
|
+
Interactive star rating component with multiple icons and variants.
|
|
2916
|
+
|
|
2917
|
+
**Variants:** `default` `primary` `secondary` `gradient` `glass` `outline`
|
|
2918
|
+
**Sizes:** `sm` `md` `lg` `xl`
|
|
2919
|
+
**Icons:** `star` `heart` `circle` `diamond`
|
|
2920
|
+
**Precision:** `full` `half`
|
|
2921
|
+
|
|
2922
|
+
```tsx
|
|
2923
|
+
import { Rating } from "saha-ui";
|
|
2924
|
+
|
|
2925
|
+
// Basic rating
|
|
2926
|
+
<Rating value={4} max={5} />;
|
|
2927
|
+
|
|
2928
|
+
// With half stars and value display
|
|
2929
|
+
<Rating value={4.5} precision="half" showValue />;
|
|
2930
|
+
|
|
2931
|
+
// Interactive rating
|
|
2932
|
+
<Rating
|
|
2933
|
+
value={0}
|
|
2934
|
+
onChange={(value) => console.log("Rating:", value)}
|
|
2935
|
+
precision="half"
|
|
2936
|
+
size="lg"
|
|
2937
|
+
/>;
|
|
2938
|
+
|
|
2939
|
+
// Read-only with review count
|
|
2940
|
+
<Rating value={4.7} precision="half" readOnly showValue count={2541} />;
|
|
2941
|
+
|
|
2942
|
+
// Different variants
|
|
2943
|
+
<Rating value={4} variant="gradient" size="lg" />;
|
|
2944
|
+
<Rating value={4} variant="glass" size="lg" />;
|
|
2945
|
+
|
|
2946
|
+
// Different icons
|
|
2947
|
+
<Rating value={4} icon="heart" variant="primary" size="lg" />;
|
|
2948
|
+
<Rating value={4} icon="circle" variant="secondary" size="lg" />;
|
|
2949
|
+
|
|
2950
|
+
// Custom colors
|
|
2951
|
+
<Rating value={4} color="#ef4444" size="lg" />;
|
|
2952
|
+
|
|
2953
|
+
// Custom maximum
|
|
2954
|
+
<Rating value={7} max={10} showValue />;
|
|
2955
|
+
|
|
2956
|
+
// With tooltips
|
|
2957
|
+
<Rating
|
|
2958
|
+
value={0}
|
|
2959
|
+
showTooltip
|
|
2960
|
+
tooltipLabels={["Poor", "Fair", "Good", "Very Good", "Excellent"]}
|
|
2961
|
+
onChange={(value) => console.log(value)}
|
|
2962
|
+
/>;
|
|
2963
|
+
```
|
|
2964
|
+
|
|
2965
|
+
**Features:**
|
|
2966
|
+
|
|
2967
|
+
- ✅ Interactive and read-only modes
|
|
2968
|
+
- ⭐ Full and half-star precision
|
|
2969
|
+
- 🎨 6 visual variants with glassmorphism
|
|
2970
|
+
- 📏 4 size options (sm, md, lg, xl)
|
|
2971
|
+
- 🎯 Multiple icon types (star, heart, circle, diamond)
|
|
2972
|
+
- 🎨 Custom colors and icons
|
|
2973
|
+
- 📊 Review count display
|
|
2974
|
+
- 🖱️ Hover preview
|
|
2975
|
+
- ⌨️ Keyboard navigation
|
|
2976
|
+
- 🎭 Animated transitions
|
|
2977
|
+
- 🔧 Custom formatting
|
|
2978
|
+
- 💬 Tooltip support
|
|
2979
|
+
- ♿ Fully accessible
|
|
2980
|
+
|
|
2981
|
+
**Props:**
|
|
2982
|
+
|
|
2983
|
+
- `value` - Current rating value (0 to max)
|
|
2984
|
+
- `max` - Maximum rating value (default: 5)
|
|
2985
|
+
- `variant` - Visual style variant
|
|
2986
|
+
- `size` - Icon size
|
|
2987
|
+
- `icon` - Icon type to display
|
|
2988
|
+
- `precision` - Full or half stars
|
|
2989
|
+
- `readOnly` - Disable interaction
|
|
2990
|
+
- `disabled` - Disabled state
|
|
2991
|
+
- `showValue` - Display numeric value
|
|
2992
|
+
- `count` - Review count
|
|
2993
|
+
- `countLabel` - Label for count (default: "reviews")
|
|
2994
|
+
- `color` - Custom color for filled icons
|
|
2995
|
+
- `hoverable` - Enable hover effect
|
|
2996
|
+
- `showTooltip` - Show tooltips on hover
|
|
2997
|
+
- `tooltipLabels` - Custom labels for each value
|
|
2998
|
+
- `onChange` - Callback when rating changes
|
|
2999
|
+
- `onHover` - Callback when hovering
|
|
3000
|
+
- `allowClear` - Allow clearing rating
|
|
3001
|
+
- `animated` - Enable animations
|
|
3002
|
+
|
|
3003
|
+
---
|
|
3004
|
+
|
|
3005
|
+
### Progress
|
|
3006
|
+
|
|
3007
|
+
A flexible progress bar component with multiple variants, sizes, and animations for displaying progress and loading states.
|
|
3008
|
+
|
|
3009
|
+
**Basic Usage:**
|
|
3010
|
+
|
|
3011
|
+
```tsx
|
|
3012
|
+
import { Progress } from "saha-ui";
|
|
3013
|
+
|
|
3014
|
+
// Basic progress
|
|
3015
|
+
<Progress value={75} />
|
|
3016
|
+
|
|
3017
|
+
// With variant and size
|
|
3018
|
+
<Progress value={60} variant="primary" size="lg" />
|
|
3019
|
+
|
|
3020
|
+
// With label
|
|
3021
|
+
<Progress value={45} showValue labelPosition="outside" />
|
|
3022
|
+
|
|
3023
|
+
// Striped with animation
|
|
3024
|
+
<Progress value={80} variant="success" striped stripedAnimated />
|
|
3025
|
+
|
|
3026
|
+
// Indeterminate loading
|
|
3027
|
+
<Progress indeterminate variant="gradient" />
|
|
3028
|
+
|
|
3029
|
+
// With glow effect
|
|
3030
|
+
<Progress value={90} variant="gradient" glow />
|
|
3031
|
+
|
|
3032
|
+
// Custom colors
|
|
3033
|
+
<Progress value={60} color="#9333ea" trackColor="#f3e8ff" />
|
|
3034
|
+
```
|
|
3035
|
+
|
|
3036
|
+
**Variants:**
|
|
3037
|
+
|
|
3038
|
+
- `default` - Standard gray progress bar
|
|
3039
|
+
- `primary` - Primary color with gradient
|
|
3040
|
+
- `secondary` - Secondary color with gradient
|
|
3041
|
+
- `success` - Green success indicator
|
|
3042
|
+
- `warning` - Yellow/orange warning
|
|
3043
|
+
- `error` - Red error indicator
|
|
3044
|
+
- `gradient` - Multi-color gradient (blue→purple→pink)
|
|
3045
|
+
- `striped` - Striped pattern effect
|
|
3046
|
+
- `glass` - Glassmorphism with backdrop blur
|
|
3047
|
+
|
|
3048
|
+
**Features:**
|
|
3049
|
+
|
|
3050
|
+
- 🎨 **9 Modern Variants** - Each with unique visual design
|
|
3051
|
+
- 📏 **5 Size Options** - xs, sm, md, lg, xl
|
|
3052
|
+
- 🎭 **3 Shape Styles** - rounded, pill, square
|
|
3053
|
+
- 🏷️ **Label Support** - Inside, outside, or top positioned
|
|
3054
|
+
- 🎬 **Animations** - Pulse, shimmer, striped, indeterminate
|
|
3055
|
+
- 🌈 **Custom Colors** - Both bar and track colors
|
|
3056
|
+
- ✨ **Glow Effect** - Enhanced shadow for emphasis
|
|
3057
|
+
- 📊 **Value Display** - Show percentage or custom labels
|
|
3058
|
+
- ⏳ **Loading States** - Indeterminate/infinite loading
|
|
3059
|
+
- 🎯 **Type-Safe** - Full TypeScript support
|
|
3060
|
+
- ♿ **Accessible** - ARIA progressbar role
|
|
3061
|
+
- 🎭 **CVA Powered** - Type-safe variant composition
|
|
3062
|
+
|
|
3063
|
+
**Props:**
|
|
3064
|
+
|
|
3065
|
+
```tsx
|
|
3066
|
+
interface ProgressProps {
|
|
3067
|
+
variant?:
|
|
3068
|
+
| "default"
|
|
3069
|
+
| "primary"
|
|
3070
|
+
| "secondary"
|
|
3071
|
+
| "success"
|
|
3072
|
+
| "warning"
|
|
3073
|
+
| "error"
|
|
3074
|
+
| "gradient"
|
|
3075
|
+
| "striped"
|
|
3076
|
+
| "glass";
|
|
3077
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl";
|
|
3078
|
+
shape?: "rounded" | "pill" | "square";
|
|
3079
|
+
animation?: "none" | "pulse" | "shimmer" | "indeterminate";
|
|
3080
|
+
value?: number; // 0-100
|
|
3081
|
+
max?: number; // default: 100
|
|
3082
|
+
showValue?: boolean;
|
|
3083
|
+
label?: string;
|
|
3084
|
+
labelPosition?: "inside" | "outside" | "top";
|
|
3085
|
+
color?: string;
|
|
3086
|
+
trackColor?: string;
|
|
3087
|
+
striped?: boolean;
|
|
3088
|
+
stripedAnimated?: boolean;
|
|
3089
|
+
glow?: boolean;
|
|
3090
|
+
indeterminate?: boolean;
|
|
3091
|
+
valueFormat?: (value: number, max: number) => string;
|
|
3092
|
+
barClassName?: string;
|
|
3093
|
+
labelClassName?: string;
|
|
3094
|
+
className?: string;
|
|
3095
|
+
}
|
|
3096
|
+
```
|
|
3097
|
+
|
|
3098
|
+
**Real-World Examples:**
|
|
3099
|
+
|
|
3100
|
+
```tsx
|
|
3101
|
+
// File upload progress
|
|
3102
|
+
<Progress
|
|
3103
|
+
value={uploadProgress}
|
|
3104
|
+
variant="primary"
|
|
3105
|
+
size="lg"
|
|
3106
|
+
striped
|
|
3107
|
+
stripedAnimated
|
|
3108
|
+
showValue
|
|
3109
|
+
labelPosition="top"
|
|
3110
|
+
label={`Uploading ${fileName}`}
|
|
3111
|
+
/>
|
|
3112
|
+
|
|
3113
|
+
// Skill level indicator
|
|
3114
|
+
<div>
|
|
3115
|
+
<div className="flex justify-between mb-1">
|
|
3116
|
+
<span>React</span>
|
|
3117
|
+
<span>90%</span>
|
|
3118
|
+
</div>
|
|
3119
|
+
<Progress value={90} variant="primary" />
|
|
3120
|
+
</div>
|
|
3121
|
+
|
|
3122
|
+
// System resource usage
|
|
3123
|
+
<Progress
|
|
3124
|
+
value={cpuUsage}
|
|
3125
|
+
variant={cpuUsage > 80 ? "error" : "success"}
|
|
3126
|
+
size="sm"
|
|
3127
|
+
glow={cpuUsage > 80}
|
|
3128
|
+
/>
|
|
3129
|
+
|
|
3130
|
+
// Loading state
|
|
3131
|
+
<Progress indeterminate variant="gradient" />
|
|
3132
|
+
```
|
|
3133
|
+
|
|
3134
|
+
**Detailed Props:**
|
|
3135
|
+
|
|
3136
|
+
- `variant` - Visual style of the progress bar
|
|
3137
|
+
- `size` - Height of the progress bar
|
|
3138
|
+
- `shape` - Border radius style
|
|
3139
|
+
- `animation` - Animation type (pulse, shimmer, indeterminate)
|
|
3140
|
+
- `value` - Current progress value (0-100)
|
|
3141
|
+
- `max` - Maximum value (default 100)
|
|
3142
|
+
- `showValue` - Display percentage/label
|
|
3143
|
+
- `label` - Custom label text
|
|
3144
|
+
- `labelPosition` - Where to display label
|
|
3145
|
+
- `color` - Custom bar color
|
|
3146
|
+
- `trackColor` - Custom background color
|
|
3147
|
+
- `striped` - Show striped pattern
|
|
3148
|
+
- `stripedAnimated` - Animate the stripes
|
|
3149
|
+
- `glow` - Add glow shadow effect
|
|
3150
|
+
- `indeterminate` - Loading/infinite state
|
|
3151
|
+
- `valueFormat` - Custom formatter function
|
|
3152
|
+
|
|
3153
|
+
---
|
|
3154
|
+
|
|
3155
|
+
### Popover
|
|
3156
|
+
|
|
3157
|
+
A versatile popover component for displaying rich interactive content with multiple positioning options, variants, and trigger types.
|
|
3158
|
+
|
|
3159
|
+
**Basic Usage:**
|
|
3160
|
+
|
|
3161
|
+
```tsx
|
|
3162
|
+
import { Popover, Button } from "saha-ui";
|
|
3163
|
+
|
|
3164
|
+
// Basic popover
|
|
3165
|
+
<Popover content="This is a simple popover">
|
|
3166
|
+
<Button>Click me</Button>
|
|
3167
|
+
</Popover>
|
|
3168
|
+
|
|
3169
|
+
// With title and footer
|
|
3170
|
+
<Popover
|
|
3171
|
+
title="Confirm Action"
|
|
3172
|
+
content="Are you sure?"
|
|
3173
|
+
footer={
|
|
3174
|
+
<div className="flex gap-2">
|
|
3175
|
+
<Button size="sm">Cancel</Button>
|
|
3176
|
+
<Button size="sm" variant="primary">Confirm</Button>
|
|
3177
|
+
</div>
|
|
3178
|
+
}
|
|
3179
|
+
>
|
|
3180
|
+
<Button>Delete</Button>
|
|
3181
|
+
</Popover>
|
|
3182
|
+
|
|
3183
|
+
// Glass variant
|
|
3184
|
+
<Popover variant="glass" position="right" content="Beautiful glassmorphic popover">
|
|
3185
|
+
<Button>Click me</Button>
|
|
3186
|
+
</Popover>
|
|
3187
|
+
```
|
|
3188
|
+
|
|
3189
|
+
**Variants:** `default` `primary` `secondary` `success` `warning` `danger` `info` `glass` `bordered` `elevated` `flat`
|
|
3190
|
+
**Positions:** 12 options including `top`, `bottom`, `left`, `right` (with -start and -end variations)
|
|
3191
|
+
**Sizes:** `sm` `md` `lg` `xl`
|
|
3192
|
+
|
|
3193
|
+
**Features:**
|
|
3194
|
+
|
|
3195
|
+
- 🎨 11 visual variants (7 colors + 4 styles)
|
|
3196
|
+
- 📐 12 position options
|
|
3197
|
+
- 🎯 4 trigger types (click, hover, focus, manual)
|
|
3198
|
+
- 🎭 Arrow indicator
|
|
3199
|
+
- 📋 Title & footer support
|
|
3200
|
+
- ✖️ Optional close button
|
|
3201
|
+
- 🔘 Auto-dismiss (click outside, Escape key)
|
|
3202
|
+
- 💬 Rich content support
|
|
3203
|
+
- 🎛️ Controlled mode
|
|
3204
|
+
- ♿ Fully accessible
|
|
3205
|
+
|
|
3206
|
+
---
|
|
3207
|
+
|
|
3208
|
+
### PlayButton
|
|
3209
|
+
|
|
3210
|
+
An animated play/pause button with smooth transitions, multiple variants, and modern effects. Perfect for media players, video controls, and interactive applications.
|
|
3211
|
+
|
|
3212
|
+
**Basic Usage:**
|
|
3213
|
+
|
|
3214
|
+
```tsx
|
|
3215
|
+
import { PlayButton } from "saha-ui";
|
|
3216
|
+
|
|
3217
|
+
// Basic play button
|
|
3218
|
+
<PlayButton />
|
|
3219
|
+
|
|
3220
|
+
// With variant and size
|
|
3221
|
+
<PlayButton variant="primary" size="lg" />
|
|
3222
|
+
|
|
3223
|
+
// Controlled state
|
|
3224
|
+
const [playing, setPlaying] = useState(false);
|
|
3225
|
+
<PlayButton
|
|
3226
|
+
isPlaying={playing}
|
|
3227
|
+
onToggle={setPlaying}
|
|
3228
|
+
/>
|
|
3229
|
+
|
|
3230
|
+
// With effects
|
|
3231
|
+
<PlayButton variant="success" pulse glow />
|
|
3232
|
+
|
|
3233
|
+
// In a media player
|
|
3234
|
+
<div className="flex items-center gap-4">
|
|
3235
|
+
<PlayButton
|
|
3236
|
+
variant="primary"
|
|
3237
|
+
size="md"
|
|
3238
|
+
isPlaying={playing}
|
|
3239
|
+
onToggle={setPlaying}
|
|
3240
|
+
/>
|
|
3241
|
+
<span>{playing ? "Playing..." : "Paused"}</span>
|
|
3242
|
+
</div>
|
|
3243
|
+
```
|
|
3244
|
+
|
|
3245
|
+
**Variants:** `default` `primary` `secondary` `accent` `info` `success` `warning` `error` `glass`
|
|
3246
|
+
**Sizes:** `sm` `md` `lg` `xl`
|
|
3247
|
+
|
|
3248
|
+
**Features:**
|
|
3249
|
+
|
|
3250
|
+
- 🎨 9 visual variants with theme support
|
|
3251
|
+
- 📐 4 size options (12px to 24px icons)
|
|
3252
|
+
- ▶️ Smooth play/pause icon transitions
|
|
3253
|
+
- 💫 Animated pulsing ring when playing
|
|
3254
|
+
- ✨ Glow effects on hover
|
|
3255
|
+
- 🎛️ Controlled or uncontrolled state
|
|
3256
|
+
- 🎯 Click ripple effect
|
|
3257
|
+
- 🔘 Rounded, modern design
|
|
3258
|
+
- ♿ Fully accessible with ARIA labels
|
|
3259
|
+
- 🎭 Hover scale animations
|
|
3260
|
+
|
|
3261
|
+
---
|
|
3262
|
+
|
|
3263
|
+
### Skeleton
|
|
3264
|
+
|
|
3265
|
+
Loading placeholder component with smooth animations and multiple visual styles.
|
|
3266
|
+
|
|
3267
|
+
**Basic Usage:**
|
|
3268
|
+
|
|
3269
|
+
```tsx
|
|
3270
|
+
import { Skeleton } from "saha-ui";
|
|
3271
|
+
|
|
3272
|
+
// Basic skeleton
|
|
3273
|
+
<Skeleton width="100%" height="20px" />
|
|
3274
|
+
|
|
3275
|
+
// Multiple lines
|
|
3276
|
+
<Skeleton count={3} />
|
|
3277
|
+
|
|
3278
|
+
// Circle skeleton (avatar placeholder)
|
|
3279
|
+
<Skeleton
|
|
3280
|
+
shape="circle"
|
|
3281
|
+
width="48px"
|
|
3282
|
+
height="48px"
|
|
3283
|
+
variant="pulse"
|
|
3284
|
+
/>
|
|
3285
|
+
```
|
|
3286
|
+
|
|
3287
|
+
**Variants:**
|
|
3288
|
+
|
|
3289
|
+
```tsx
|
|
3290
|
+
// Default pulse animation
|
|
3291
|
+
<Skeleton variant="default" height="60px" />
|
|
3292
|
+
|
|
3293
|
+
// Wave effect
|
|
3294
|
+
<Skeleton variant="wave" height="60px" />
|
|
3295
|
+
|
|
3296
|
+
// Shimmer effect
|
|
3297
|
+
<Skeleton variant="shimmer" height="60px" />
|
|
3298
|
+
|
|
3299
|
+
// Gradient animation
|
|
3300
|
+
<Skeleton variant="gradient" height="60px" />
|
|
3301
|
+
```
|
|
3302
|
+
|
|
3303
|
+
**Shapes:**
|
|
3304
|
+
|
|
3305
|
+
```tsx
|
|
3306
|
+
// Rectangle (default)
|
|
3307
|
+
<Skeleton shape="rectangle" width="100%" height="80px" />
|
|
3308
|
+
|
|
3309
|
+
// Circle (for avatars)
|
|
3310
|
+
<Skeleton shape="circle" width="64px" height="64px" />
|
|
3311
|
+
|
|
3312
|
+
// Rounded corners
|
|
3313
|
+
<Skeleton shape="rounded" width="100%" height="80px" />
|
|
3314
|
+
|
|
3315
|
+
// Text lines
|
|
3316
|
+
<Skeleton shape="text" count={4} />
|
|
3317
|
+
```
|
|
3318
|
+
|
|
3319
|
+
**Animation Speed:**
|
|
3320
|
+
|
|
3321
|
+
```tsx
|
|
3322
|
+
<Skeleton speed="slow" variant="shimmer" />
|
|
3323
|
+
<Skeleton speed="normal" variant="shimmer" />
|
|
3324
|
+
<Skeleton speed="fast" variant="shimmer" />
|
|
3325
|
+
|
|
3326
|
+
// Disable animation
|
|
3327
|
+
<Skeleton noAnimation />
|
|
3328
|
+
```
|
|
3329
|
+
|
|
3330
|
+
**Real-world Examples:**
|
|
3331
|
+
|
|
3332
|
+
```tsx
|
|
3333
|
+
// Profile card loading
|
|
3334
|
+
<Card>
|
|
3335
|
+
<div className="flex gap-4">
|
|
3336
|
+
<Skeleton shape="circle" width="64px" height="64px" />
|
|
3337
|
+
<div className="flex-1">
|
|
3338
|
+
<Skeleton height="24px" width="60%" className="mb-2" />
|
|
3339
|
+
<Skeleton count={2} height="16px" />
|
|
3340
|
+
</div>
|
|
3341
|
+
</div>
|
|
3342
|
+
</Card>
|
|
3343
|
+
|
|
3344
|
+
// Blog post loading
|
|
3345
|
+
<Card>
|
|
3346
|
+
<Skeleton height="200px" className="mb-4" />
|
|
3347
|
+
<Skeleton height="32px" width="80%" className="mb-3" />
|
|
3348
|
+
<Skeleton count={4} height="16px" />
|
|
3349
|
+
</Card>
|
|
3350
|
+
|
|
3351
|
+
// List items loading
|
|
3352
|
+
{[1, 2, 3].map(i => (
|
|
3353
|
+
<Card key={i} className="flex gap-4">
|
|
3354
|
+
<Skeleton shape="circle" width="48px" height="48px" />
|
|
3355
|
+
<div className="flex-1">
|
|
3356
|
+
<Skeleton height="18px" width="70%" className="mb-2" />
|
|
3357
|
+
<Skeleton height="14px" width="90%" />
|
|
3358
|
+
</div>
|
|
3359
|
+
</Card>
|
|
3360
|
+
))}
|
|
3361
|
+
```
|
|
3362
|
+
|
|
3363
|
+
**Variants:** `default` `pulse` `wave` `shimmer` `gradient`
|
|
3364
|
+
**Shapes:** `rectangle` `circle` `rounded` `text`
|
|
3365
|
+
**Speeds:** `slow` `normal` `fast`
|
|
3366
|
+
|
|
3367
|
+
**Features:**
|
|
3368
|
+
|
|
3369
|
+
- 🎨 5 animation variants
|
|
3370
|
+
- 🔷 4 shape options
|
|
3371
|
+
- ⚡ 3 speed settings
|
|
3372
|
+
- 📊 Multiple line support with `count` prop
|
|
3373
|
+
- 🎯 Fully customizable width/height
|
|
3374
|
+
- 🎭 Smooth animations with CVA
|
|
3375
|
+
- 🌓 Theme-aware styling
|
|
3376
|
+
- 🔧 Custom border radius support
|
|
3377
|
+
- 📱 Responsive and flexible
|
|
3378
|
+
- 💫 No animation mode available
|
|
3379
|
+
|
|
3380
|
+
---
|
|
3381
|
+
|
|
3382
|
+
### Pagination
|
|
3383
|
+
|
|
3384
|
+
Comprehensive pagination component for navigating through large datasets.
|
|
3385
|
+
|
|
3386
|
+
**Basic Usage:**
|
|
3387
|
+
|
|
3388
|
+
```tsx
|
|
3389
|
+
import { Pagination } from "saha-ui";
|
|
3390
|
+
|
|
3391
|
+
// Basic pagination
|
|
3392
|
+
<Pagination
|
|
3393
|
+
totalPages={10}
|
|
3394
|
+
currentPage={currentPage}
|
|
3395
|
+
onPageChange={(page) => setCurrentPage(page)}
|
|
3396
|
+
/>
|
|
3397
|
+
|
|
3398
|
+
// Custom variant and size
|
|
3399
|
+
<Pagination
|
|
3400
|
+
variant="primary"
|
|
3401
|
+
size="lg"
|
|
3402
|
+
totalPages={20}
|
|
3403
|
+
currentPage={5}
|
|
3404
|
+
onPageChange={handlePageChange}
|
|
3405
|
+
/>
|
|
3406
|
+
```
|
|
3407
|
+
|
|
3408
|
+
**Variants:**
|
|
3409
|
+
|
|
3410
|
+
```tsx
|
|
3411
|
+
// Default
|
|
3412
|
+
<Pagination variant="default" totalPages={10} currentPage={1} />
|
|
3413
|
+
|
|
3414
|
+
// Primary
|
|
3415
|
+
<Pagination variant="primary" totalPages={10} currentPage={3} />
|
|
3416
|
+
|
|
3417
|
+
// Secondary
|
|
3418
|
+
<Pagination variant="secondary" totalPages={10} currentPage={5} />
|
|
3419
|
+
|
|
3420
|
+
// Outlined
|
|
3421
|
+
<Pagination variant="outlined" totalPages={10} currentPage={7} />
|
|
3422
|
+
|
|
3423
|
+
// Minimal
|
|
3424
|
+
<Pagination variant="minimal" totalPages={10} currentPage={2} />
|
|
3425
|
+
```
|
|
3426
|
+
|
|
3427
|
+
**Sizes:**
|
|
3428
|
+
|
|
3429
|
+
```tsx
|
|
3430
|
+
<Pagination size="sm" totalPages={10} currentPage={3} />
|
|
3431
|
+
<Pagination size="md" totalPages={10} currentPage={5} />
|
|
3432
|
+
<Pagination size="lg" totalPages={10} currentPage={7} />
|
|
3433
|
+
```
|
|
3434
|
+
|
|
3435
|
+
**Shapes:**
|
|
3436
|
+
|
|
3437
|
+
```tsx
|
|
3438
|
+
<Pagination shape="rounded" totalPages={10} currentPage={3} />
|
|
3439
|
+
<Pagination shape="square" totalPages={10} currentPage={5} />
|
|
3440
|
+
<Pagination shape="pill" totalPages={10} currentPage={7} />
|
|
3441
|
+
```
|
|
3442
|
+
|
|
3443
|
+
**Large Page Count (Ellipsis):**
|
|
3444
|
+
|
|
3445
|
+
```tsx
|
|
3446
|
+
// Automatically shows ellipsis for many pages
|
|
3447
|
+
<Pagination
|
|
3448
|
+
variant="primary"
|
|
3449
|
+
totalPages={50}
|
|
3450
|
+
currentPage={currentPage}
|
|
3451
|
+
onPageChange={setCurrentPage}
|
|
3452
|
+
/>
|
|
3453
|
+
|
|
3454
|
+
// Control sibling count
|
|
3455
|
+
<Pagination
|
|
3456
|
+
totalPages={100}
|
|
3457
|
+
currentPage={currentPage}
|
|
3458
|
+
onPageChange={setCurrentPage}
|
|
3459
|
+
siblingCount={2} // Show 2 pages on each side
|
|
3460
|
+
/>
|
|
3461
|
+
```
|
|
3462
|
+
|
|
3463
|
+
**Custom Labels:**
|
|
3464
|
+
|
|
3465
|
+
```tsx
|
|
3466
|
+
// Text labels
|
|
3467
|
+
<Pagination
|
|
3468
|
+
totalPages={10}
|
|
3469
|
+
currentPage={5}
|
|
3470
|
+
previousLabel="← Prev"
|
|
3471
|
+
nextLabel="Next →"
|
|
3472
|
+
firstLabel="First"
|
|
3473
|
+
lastLabel="Last"
|
|
3474
|
+
/>
|
|
3475
|
+
|
|
3476
|
+
// Without first/last buttons
|
|
3477
|
+
<Pagination
|
|
3478
|
+
variant="primary"
|
|
3479
|
+
totalPages={10}
|
|
3480
|
+
currentPage={5}
|
|
3481
|
+
showFirstLast={false}
|
|
3482
|
+
/>
|
|
3483
|
+
|
|
3484
|
+
// Only page numbers
|
|
3485
|
+
<Pagination
|
|
3486
|
+
variant="outlined"
|
|
3487
|
+
totalPages={10}
|
|
3488
|
+
currentPage={5}
|
|
3489
|
+
showFirstLast={false}
|
|
3490
|
+
showPrevNext={false}
|
|
3491
|
+
/>
|
|
3492
|
+
```
|
|
3493
|
+
|
|
3494
|
+
**Real-world Example:**
|
|
3495
|
+
|
|
3496
|
+
```tsx
|
|
3497
|
+
// Data table pagination
|
|
3498
|
+
function DataTable() {
|
|
3499
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
3500
|
+
const itemsPerPage = 10;
|
|
3501
|
+
const totalItems = 100;
|
|
3502
|
+
const totalPages = Math.ceil(totalItems / itemsPerPage);
|
|
3503
|
+
|
|
3504
|
+
return (
|
|
3505
|
+
<div>
|
|
3506
|
+
<p>
|
|
3507
|
+
Showing {(currentPage - 1) * itemsPerPage + 1} -
|
|
3508
|
+
{Math.min(currentPage * itemsPerPage, totalItems)} of {totalItems}
|
|
3509
|
+
</p>
|
|
3510
|
+
|
|
3511
|
+
<Pagination
|
|
3512
|
+
variant="primary"
|
|
3513
|
+
size="sm"
|
|
3514
|
+
totalPages={totalPages}
|
|
3515
|
+
currentPage={currentPage}
|
|
3516
|
+
onPageChange={setCurrentPage}
|
|
3517
|
+
/>
|
|
3518
|
+
</div>
|
|
3519
|
+
);
|
|
3520
|
+
}
|
|
3521
|
+
```
|
|
3522
|
+
|
|
3523
|
+
**Variants:** `default` `primary` `secondary` `outlined` `minimal`
|
|
3524
|
+
**Sizes:** `sm` `md` `lg`
|
|
3525
|
+
**Shapes:** `rounded` `square` `pill`
|
|
3526
|
+
|
|
3527
|
+
**Features:**
|
|
3528
|
+
|
|
3529
|
+
- 🎨 5 visual variants with theme support
|
|
3530
|
+
- 📐 3 size options
|
|
3531
|
+
- 🔷 3 shape styles
|
|
3532
|
+
- 🔢 Automatic ellipsis for large page counts
|
|
3533
|
+
- 🎯 Customizable sibling count
|
|
3534
|
+
- 🏷️ Custom labels for all buttons
|
|
3535
|
+
- ⚡ Fast page navigation
|
|
3536
|
+
- ♿ Fully accessible with ARIA labels
|
|
3537
|
+
- 🎭 Smooth transitions
|
|
3538
|
+
- 🎛️ Show/hide first/last/prev/next buttons
|
|
3539
|
+
- 📱 Responsive design
|
|
3540
|
+
- 🌓 Theme-aware styling
|
|
3541
|
+
- ⌨️ Keyboard navigation support
|
|
3542
|
+
- 🚫 Disabled state support
|
|
3543
|
+
|
|
3544
|
+
---
|
|
3545
|
+
|
|
3546
|
+
### DatePicker
|
|
3547
|
+
|
|
3548
|
+
Calendar-based date picker with multiple variants and date restrictions.
|
|
3549
|
+
|
|
3550
|
+
**Basic Usage:**
|
|
3551
|
+
|
|
3552
|
+
```tsx
|
|
3553
|
+
import { DatePicker } from "saha-ui";
|
|
3554
|
+
|
|
3555
|
+
// Basic date picker
|
|
3556
|
+
<DatePicker
|
|
3557
|
+
value={date}
|
|
3558
|
+
onChange={(date) => setDate(date)}
|
|
3559
|
+
placeholder="Select date"
|
|
3560
|
+
/>
|
|
3561
|
+
|
|
3562
|
+
// Custom variant and size
|
|
3563
|
+
<DatePicker
|
|
3564
|
+
variant="primary"
|
|
3565
|
+
size="lg"
|
|
3566
|
+
value={date}
|
|
3567
|
+
onChange={setDate}
|
|
3568
|
+
/>
|
|
3569
|
+
```
|
|
3570
|
+
|
|
3571
|
+
**Variants:**
|
|
3572
|
+
|
|
3573
|
+
```tsx
|
|
3574
|
+
// Default
|
|
3575
|
+
<DatePicker variant="default" />
|
|
3576
|
+
|
|
3577
|
+
// Primary
|
|
3578
|
+
<DatePicker variant="primary" />
|
|
3579
|
+
|
|
3580
|
+
// Secondary
|
|
3581
|
+
<DatePicker variant="secondary" />
|
|
3582
|
+
|
|
3583
|
+
// Outlined
|
|
3584
|
+
<DatePicker variant="outlined" />
|
|
3585
|
+
|
|
3586
|
+
// Minimal
|
|
3587
|
+
<DatePicker variant="minimal" />
|
|
3588
|
+
```
|
|
3589
|
+
|
|
3590
|
+
**Sizes:**
|
|
3591
|
+
|
|
3592
|
+
```tsx
|
|
3593
|
+
<DatePicker size="sm" />
|
|
3594
|
+
<DatePicker size="md" />
|
|
3595
|
+
<DatePicker size="lg" />
|
|
3596
|
+
```
|
|
3597
|
+
|
|
3598
|
+
**Date Restrictions:**
|
|
3599
|
+
|
|
3600
|
+
```tsx
|
|
3601
|
+
// Min date (future dates only)
|
|
3602
|
+
<DatePicker
|
|
3603
|
+
value={date}
|
|
3604
|
+
onChange={setDate}
|
|
3605
|
+
minDate={new Date()}
|
|
3606
|
+
placeholder="Select future date"
|
|
3607
|
+
/>
|
|
3608
|
+
|
|
3609
|
+
// Max date (past dates only)
|
|
3610
|
+
<DatePicker
|
|
3611
|
+
value={date}
|
|
3612
|
+
onChange={setDate}
|
|
3613
|
+
maxDate={new Date()}
|
|
3614
|
+
placeholder="Select past date"
|
|
3615
|
+
/>
|
|
3616
|
+
|
|
3617
|
+
// Date range
|
|
3618
|
+
<DatePicker
|
|
3619
|
+
value={date}
|
|
3620
|
+
onChange={setDate}
|
|
3621
|
+
minDate={startDate}
|
|
3622
|
+
maxDate={endDate}
|
|
3623
|
+
placeholder="Select date in range"
|
|
3624
|
+
/>
|
|
3625
|
+
```
|
|
3626
|
+
|
|
3627
|
+
**Customization:**
|
|
3628
|
+
|
|
3629
|
+
```tsx
|
|
3630
|
+
// Custom format
|
|
3631
|
+
<DatePicker
|
|
3632
|
+
value={date}
|
|
3633
|
+
onChange={setDate}
|
|
3634
|
+
format="DD/MM/YYYY"
|
|
3635
|
+
placeholder="DD/MM/YYYY"
|
|
3636
|
+
/>
|
|
3637
|
+
|
|
3638
|
+
// Monday as first day of week
|
|
3639
|
+
<DatePicker
|
|
3640
|
+
value={date}
|
|
3641
|
+
onChange={setDate}
|
|
3642
|
+
firstDayOfWeek={1}
|
|
3643
|
+
/>
|
|
3644
|
+
|
|
3645
|
+
// Without clear/today buttons
|
|
3646
|
+
<DatePicker
|
|
3647
|
+
value={date}
|
|
3648
|
+
onChange={setDate}
|
|
3649
|
+
showClear={false}
|
|
3650
|
+
showToday={false}
|
|
3651
|
+
/>
|
|
3652
|
+
|
|
3653
|
+
// Disabled state
|
|
3654
|
+
<DatePicker
|
|
3655
|
+
value={date}
|
|
3656
|
+
disabled
|
|
3657
|
+
/>
|
|
3658
|
+
```
|
|
3659
|
+
|
|
3660
|
+
**Real-world Examples:**
|
|
3661
|
+
|
|
3662
|
+
```tsx
|
|
3663
|
+
// Booking form
|
|
3664
|
+
<div className="grid grid-cols-2 gap-4">
|
|
3665
|
+
<DatePicker
|
|
3666
|
+
variant="primary"
|
|
3667
|
+
minDate={new Date()}
|
|
3668
|
+
placeholder="Check-in"
|
|
3669
|
+
/>
|
|
3670
|
+
<DatePicker
|
|
3671
|
+
variant="primary"
|
|
3672
|
+
minDate={new Date()}
|
|
3673
|
+
placeholder="Check-out"
|
|
3674
|
+
/>
|
|
3675
|
+
</div>
|
|
3676
|
+
|
|
3677
|
+
// Date of birth picker
|
|
3678
|
+
<DatePicker
|
|
3679
|
+
variant="outlined"
|
|
3680
|
+
maxDate={new Date()}
|
|
3681
|
+
format="MM/DD/YYYY"
|
|
3682
|
+
placeholder="Date of birth"
|
|
3683
|
+
/>
|
|
3684
|
+
|
|
3685
|
+
// Task due date
|
|
3686
|
+
<DatePicker
|
|
3687
|
+
variant="primary"
|
|
3688
|
+
size="sm"
|
|
3689
|
+
minDate={new Date()}
|
|
3690
|
+
placeholder="Due date"
|
|
3691
|
+
/>
|
|
3692
|
+
```
|
|
3693
|
+
|
|
3694
|
+
**Variants:** `default` `primary` `secondary` `outlined` `minimal`
|
|
3695
|
+
**Sizes:** `sm` `md` `lg`
|
|
3696
|
+
**Formats:** Customizable (MM/DD/YYYY, DD/MM/YYYY, etc.)
|
|
3697
|
+
|
|
3698
|
+
**Features:**
|
|
3699
|
+
|
|
3700
|
+
- 🎨 5 visual variants with theme support
|
|
3701
|
+
- 📐 3 size options
|
|
3702
|
+
- 📅 Interactive calendar view
|
|
3703
|
+
- 🔒 Min/max date restrictions
|
|
3704
|
+
- 🎯 Custom date format display
|
|
3705
|
+
- 🌍 Configurable first day of week
|
|
3706
|
+
- ✨ Today quick select button
|
|
3707
|
+
- 🗑️ Clear button for easy reset
|
|
3708
|
+
- 📱 Click outside to close
|
|
3709
|
+
- ⌨️ Keyboard navigation in calendar
|
|
3710
|
+
- 🎭 Smooth animations
|
|
3711
|
+
- 🌓 Theme-aware styling
|
|
3712
|
+
- ♿ Fully accessible
|
|
3713
|
+
- 🚫 Disabled state support
|
|
3714
|
+
- 📆 Month/year navigation
|
|
3715
|
+
|
|
3716
|
+
---
|
|
3717
|
+
|
|
3718
|
+
### Tab
|
|
3719
|
+
|
|
3720
|
+
Tab navigation component with comprehensive variant support and flexible content options.
|
|
3721
|
+
|
|
3722
|
+
```tsx
|
|
3723
|
+
import { Tab } from "saha-ui";
|
|
3724
|
+
import type { TabItem } from "saha-ui";
|
|
3725
|
+
|
|
3726
|
+
// Basic usage
|
|
3727
|
+
const tabs: TabItem[] = [
|
|
3728
|
+
{ label: "Profile", value: "profile" },
|
|
3729
|
+
{ label: "Settings", value: "settings" },
|
|
3730
|
+
{ label: "Notifications", value: "notifications" },
|
|
3731
|
+
];
|
|
3732
|
+
|
|
3733
|
+
<Tab tabs={tabs} value={activeTab} onChange={setActiveTab} />;
|
|
3734
|
+
|
|
3735
|
+
// With icons
|
|
3736
|
+
<Tab
|
|
3737
|
+
tabs={[
|
|
3738
|
+
{ label: "Home", value: "home", icon: <HomeIcon /> },
|
|
3739
|
+
{ label: "Messages", value: "messages", icon: <MessageIcon /> },
|
|
3740
|
+
{ label: "Settings", value: "settings", icon: <SettingsIcon /> },
|
|
3741
|
+
]}
|
|
3742
|
+
variant="primary"
|
|
3743
|
+
/>;
|
|
3744
|
+
|
|
3745
|
+
// With badges
|
|
3746
|
+
<Tab
|
|
3747
|
+
tabs={[
|
|
3748
|
+
{ label: "Inbox", value: "inbox", badge: "12" },
|
|
3749
|
+
{ label: "Unread", value: "unread", badge: "5" },
|
|
3750
|
+
{ label: "Archive", value: "archive" },
|
|
3751
|
+
]}
|
|
3752
|
+
variant="secondary"
|
|
3753
|
+
/>;
|
|
3754
|
+
|
|
3755
|
+
// Full width
|
|
3756
|
+
<Tab tabs={tabs} variant="outlined" fullWidth />;
|
|
3757
|
+
|
|
3758
|
+
// Different sizes
|
|
3759
|
+
<Tab tabs={tabs} size="sm" />
|
|
3760
|
+
<Tab tabs={tabs} size="md" />
|
|
3761
|
+
<Tab tabs={tabs} size="lg" />
|
|
3762
|
+
|
|
3763
|
+
// Disabled tabs
|
|
3764
|
+
<Tab
|
|
3765
|
+
tabs={[
|
|
3766
|
+
{ label: "Active", value: "active" },
|
|
3767
|
+
{ label: "Disabled", value: "disabled", disabled: true },
|
|
3768
|
+
]}
|
|
3769
|
+
/>
|
|
3770
|
+
|
|
3771
|
+
// All 14 variants
|
|
3772
|
+
<Tab tabs={tabs} variant="default" />
|
|
3773
|
+
<Tab tabs={tabs} variant="primary" />
|
|
3774
|
+
<Tab tabs={tabs} variant="secondary" />
|
|
3775
|
+
<Tab tabs={tabs} variant="accent" />
|
|
3776
|
+
<Tab tabs={tabs} variant="success" />
|
|
3777
|
+
<Tab tabs={tabs} variant="warning" />
|
|
3778
|
+
<Tab tabs={tabs} variant="danger" />
|
|
3779
|
+
<Tab tabs={tabs} variant="info" />
|
|
3780
|
+
<Tab tabs={tabs} variant="glass" />
|
|
3781
|
+
<Tab tabs={tabs} variant="bordered" />
|
|
3782
|
+
<Tab tabs={tabs} variant="elevated" />
|
|
3783
|
+
<Tab tabs={tabs} variant="flat" />
|
|
3784
|
+
<Tab tabs={tabs} variant="outlined" />
|
|
3785
|
+
<Tab tabs={tabs} variant="minimal" />
|
|
3786
|
+
|
|
3787
|
+
// Style examples
|
|
3788
|
+
<div className="space-y-4">
|
|
3789
|
+
{/* Boxed style */}
|
|
3790
|
+
<Tab tabs={tabs} variant="primary" />
|
|
3791
|
+
|
|
3792
|
+
{/* Underlined style */}
|
|
3793
|
+
<Tab tabs={tabs} variant="bordered" />
|
|
3794
|
+
|
|
3795
|
+
{/* Pill style */}
|
|
3796
|
+
<Tab tabs={tabs} variant="glass" />
|
|
3797
|
+
</div>
|
|
3798
|
+
```
|
|
3799
|
+
|
|
3800
|
+
**Variants:** `default` `primary` `secondary` `accent` `success` `warning` `danger` `info` `glass` `bordered` `elevated` `flat` `outlined` `minimal`
|
|
3801
|
+
**Sizes:** `sm` `md` `lg`
|
|
3802
|
+
|
|
3803
|
+
**Props:**
|
|
3804
|
+
|
|
3805
|
+
| Prop | Type | Default | Description |
|
|
3806
|
+
| ---------------------- | ------------ | ---------------- | ---------------------------------- |
|
|
3807
|
+
| `items` | `TabItem[]` | Required | Array of tab items |
|
|
3808
|
+
| `value` | `string` | `undefined` | Controlled active tab value |
|
|
3809
|
+
| `defaultValue` | `string` | `items[0].value` | Default active tab (uncontrolled) |
|
|
3810
|
+
| `onChange` | `function` | `undefined` | Callback when tab changes |
|
|
3811
|
+
| `variant` | `TabVariant` | `'default'` | Visual variant |
|
|
3812
|
+
| `size` | `TabSize` | `'md'` | Size variant |
|
|
3813
|
+
| `fullWidth` | `boolean` | `false` | Make tabs full width |
|
|
3814
|
+
| `className` | `string` | `undefined` | Custom className for container |
|
|
3815
|
+
| `tabClassName` | `string` | `undefined` | Custom className for all tab items |
|
|
3816
|
+
| `activeTabClassName` | `string` | `undefined` | Custom className for active tab |
|
|
3817
|
+
| `disabledTabClassName` | `string` | `undefined` | Custom className for disabled tabs |
|
|
3818
|
+
| `iconClassName` | `string` | `undefined` | Custom className for icon wrapper |
|
|
3819
|
+
| `badgeClassName` | `string` | `undefined` | Custom className for badge |
|
|
3820
|
+
| `activeBadgeClassName` | `string` | `undefined` | Custom className for active badge |
|
|
3821
|
+
|
|
3822
|
+
**TabItem Type:**
|
|
3823
|
+
|
|
3824
|
+
```typescript
|
|
3825
|
+
interface TabItem {
|
|
3826
|
+
label: string; // Tab label text
|
|
3827
|
+
value: string; // Unique tab identifier
|
|
3828
|
+
icon?: ReactNode; // Optional icon element
|
|
3829
|
+
disabled?: boolean; // Disable the tab
|
|
3830
|
+
badge?: string | number; // Optional badge content
|
|
3831
|
+
className?: string; // Custom className for this tab
|
|
3832
|
+
iconClassName?: string; // Custom className for this tab's icon
|
|
3833
|
+
badgeClassName?: string; // Custom className for this tab's badge
|
|
3834
|
+
}
|
|
3835
|
+
```
|
|
3836
|
+
|
|
3837
|
+
**Customization Examples:**
|
|
3838
|
+
|
|
3839
|
+
```tsx
|
|
3840
|
+
// Custom container with rounded-full
|
|
3841
|
+
<Tab items={tabs} className="rounded-full p-2 shadow-xl" />
|
|
3842
|
+
|
|
3843
|
+
// Underline style tabs
|
|
3844
|
+
<Tab
|
|
3845
|
+
items={tabs}
|
|
3846
|
+
variant="minimal"
|
|
3847
|
+
className="gap-4 p-0 bg-transparent border-b-2 border-base-300"
|
|
3848
|
+
tabClassName="rounded-none border-b-2 border-transparent pb-3"
|
|
3849
|
+
activeTabClassName="!border-primary !text-primary !bg-transparent"
|
|
3850
|
+
/>
|
|
3851
|
+
|
|
3852
|
+
// Per-item custom styling
|
|
3853
|
+
<Tab
|
|
3854
|
+
items={[
|
|
3855
|
+
{
|
|
3856
|
+
label: "Red Tab",
|
|
3857
|
+
value: "red",
|
|
3858
|
+
className: "data-[active=true]:bg-red-500 data-[active=true]:text-white"
|
|
3859
|
+
},
|
|
3860
|
+
// ... more tabs
|
|
3861
|
+
]}
|
|
3862
|
+
/>
|
|
3863
|
+
|
|
3864
|
+
// Custom gradient badges
|
|
3865
|
+
<Tab
|
|
3866
|
+
items={[{ label: "Inbox", value: "inbox", badge: 12 }]}
|
|
3867
|
+
badgeClassName="bg-gradient-to-r from-pink-500 to-purple-500"
|
|
3868
|
+
activeBadgeClassName="!bg-gradient-to-r !from-yellow-400 !to-orange-500"
|
|
3869
|
+
/>
|
|
3870
|
+
|
|
3871
|
+
// Vertical tabs (mobile)
|
|
3872
|
+
<Tab
|
|
3873
|
+
items={tabs}
|
|
3874
|
+
className="flex-col sm:flex-row"
|
|
3875
|
+
tabClassName="w-full sm:w-auto justify-start"
|
|
3876
|
+
/>
|
|
3877
|
+
|
|
3878
|
+
// Pill style
|
|
3879
|
+
<Tab
|
|
3880
|
+
items={tabs}
|
|
3881
|
+
className="gap-3 p-0 bg-transparent"
|
|
3882
|
+
tabClassName="rounded-full px-6 py-3 shadow-md"
|
|
3883
|
+
activeTabClassName="scale-105 shadow-lg"
|
|
3884
|
+
/>
|
|
3885
|
+
```
|
|
3886
|
+
|
|
3887
|
+
**Features:**
|
|
3888
|
+
|
|
3889
|
+
- 🎨 14 visual variants matching design system
|
|
3890
|
+
- 📐 3 size options (sm, md, lg)
|
|
3891
|
+
- 🎯 Controlled and uncontrolled modes
|
|
3892
|
+
- 🖼️ Icon support in tabs
|
|
3893
|
+
- 🔔 Badge indicators for notifications
|
|
3894
|
+
- 🚫 Disabled tab states
|
|
3895
|
+
- 📱 Full width responsive layout
|
|
3896
|
+
- ⌨️ Keyboard navigation (arrow keys)
|
|
3897
|
+
- 🎭 Smooth transitions
|
|
3898
|
+
- 🌓 Theme-aware styling
|
|
3899
|
+
- ♿ ARIA-compliant accessibility
|
|
3900
|
+
- 🎪 Active state indicators
|
|
3901
|
+
- ✨ Hover effects
|
|
3902
|
+
- 🔄 Flexible content with icons/badges
|
|
3903
|
+
- 🎨 **Fully customizable with Tailwind classes**
|
|
3904
|
+
- 💅 **Per-item styling support**
|
|
3905
|
+
- 🔧 **No SCSS required - pure Tailwind**
|
|
3906
|
+
|
|
3907
|
+
---
|
|
3908
|
+
|
|
3909
|
+
### Input
|
|
3910
|
+
|
|
3911
|
+
Flexible and customizable input field component with comprehensive variant support and validation states.
|
|
3912
|
+
|
|
3913
|
+
```tsx
|
|
3914
|
+
import { Input } from "saha-ui";
|
|
3915
|
+
import { Mail, Lock, Search, User } from "lucide-react";
|
|
3916
|
+
|
|
3917
|
+
// Basic input
|
|
3918
|
+
<Input placeholder="Enter text..." />
|
|
3919
|
+
|
|
3920
|
+
// With label and helper text
|
|
3921
|
+
<Input
|
|
3922
|
+
label="Email"
|
|
3923
|
+
type="email"
|
|
3924
|
+
placeholder="you@example.com"
|
|
3925
|
+
helperText="We'll never share your email"
|
|
3926
|
+
/>
|
|
3927
|
+
|
|
3928
|
+
// Different variants
|
|
3929
|
+
<Input variant="primary" placeholder="Primary input" />
|
|
3930
|
+
<Input variant="secondary" placeholder="Secondary input" />
|
|
3931
|
+
<Input variant="accent" placeholder="Accent input" />
|
|
3932
|
+
<Input variant="success" placeholder="Success input" />
|
|
3933
|
+
<Input variant="warning" placeholder="Warning input" />
|
|
3934
|
+
<Input variant="error" placeholder="Error input" />
|
|
3935
|
+
<Input variant="outline" placeholder="Outline input (default)" />
|
|
3936
|
+
<Input variant="ghost" placeholder="Ghost input" />
|
|
3937
|
+
<Input variant="glass" placeholder="Glass morphism input" />
|
|
3938
|
+
|
|
3939
|
+
// With icons
|
|
3940
|
+
<Input
|
|
3941
|
+
label="Search"
|
|
3942
|
+
startIcon={<Search size={18} />}
|
|
3943
|
+
placeholder="Search..."
|
|
3944
|
+
/>
|
|
3945
|
+
|
|
3946
|
+
<Input
|
|
3947
|
+
label="Email"
|
|
3948
|
+
type="email"
|
|
3949
|
+
startIcon={<Mail size={18} />}
|
|
3950
|
+
placeholder="you@example.com"
|
|
3951
|
+
/>
|
|
3952
|
+
|
|
3953
|
+
// With validation
|
|
3954
|
+
<Input
|
|
3955
|
+
label="Password"
|
|
3956
|
+
type="password"
|
|
3957
|
+
variant="error"
|
|
3958
|
+
error="Password must be at least 8 characters"
|
|
3959
|
+
startIcon={<Lock size={18} />}
|
|
3960
|
+
/>
|
|
3961
|
+
|
|
3962
|
+
<Input
|
|
3963
|
+
label="Username"
|
|
3964
|
+
variant="success"
|
|
3965
|
+
defaultValue="johndoe"
|
|
3966
|
+
helperText="Username is available!"
|
|
3967
|
+
startIcon={<User size={18} />}
|
|
3968
|
+
/>
|
|
3969
|
+
|
|
3970
|
+
// Character counter
|
|
3971
|
+
<Input
|
|
3972
|
+
label="Bio"
|
|
3973
|
+
placeholder="Tell us about yourself..."
|
|
3974
|
+
maxLength={100}
|
|
3975
|
+
showCounter
|
|
3976
|
+
helperText="Maximum 100 characters"
|
|
3977
|
+
/>
|
|
3978
|
+
|
|
3979
|
+
// Different sizes
|
|
3980
|
+
<Input size="sm" placeholder="Small input" />
|
|
3981
|
+
<Input size="md" placeholder="Medium input (default)" />
|
|
3982
|
+
<Input size="lg" placeholder="Large input" />
|
|
3983
|
+
<Input size="xl" placeholder="Extra large input" />
|
|
3984
|
+
|
|
3985
|
+
// Full width
|
|
3986
|
+
<Input
|
|
3987
|
+
fullWidth
|
|
3988
|
+
label="Full Name"
|
|
3989
|
+
placeholder="Enter your full name"
|
|
3990
|
+
/>
|
|
3991
|
+
|
|
3992
|
+
// All input types (except file)
|
|
3993
|
+
<Input type="text" placeholder="Text input" />
|
|
3994
|
+
<Input type="email" placeholder="Email input" />
|
|
3995
|
+
<Input type="password" placeholder="Password input" />
|
|
3996
|
+
<Input type="number" placeholder="Number input" />
|
|
3997
|
+
<Input type="tel" placeholder="Phone input" />
|
|
3998
|
+
<Input type="url" placeholder="URL input" />
|
|
3999
|
+
<Input type="search" placeholder="Search input" />
|
|
4000
|
+
<Input type="date" />
|
|
4001
|
+
<Input type="time" />
|
|
4002
|
+
<Input type="color" />
|
|
4003
|
+
|
|
4004
|
+
// Required field
|
|
4005
|
+
<Input
|
|
4006
|
+
label="Username"
|
|
4007
|
+
placeholder="Enter username"
|
|
4008
|
+
required
|
|
4009
|
+
/>
|
|
4010
|
+
|
|
4011
|
+
// Disabled
|
|
4012
|
+
<Input
|
|
4013
|
+
label="Disabled Input"
|
|
4014
|
+
placeholder="Cannot edit"
|
|
4015
|
+
disabled
|
|
4016
|
+
/>
|
|
4017
|
+
|
|
4018
|
+
// Login form example
|
|
4019
|
+
<div className="space-y-4">
|
|
4020
|
+
<Input
|
|
4021
|
+
fullWidth
|
|
4022
|
+
label="Email"
|
|
4023
|
+
type="email"
|
|
4024
|
+
variant="glass"
|
|
4025
|
+
startIcon={<Mail size={18} />}
|
|
4026
|
+
placeholder="you@example.com"
|
|
4027
|
+
required
|
|
4028
|
+
/>
|
|
4029
|
+
<Input
|
|
4030
|
+
fullWidth
|
|
4031
|
+
label="Password"
|
|
4032
|
+
type="password"
|
|
4033
|
+
variant="glass"
|
|
4034
|
+
startIcon={<Lock size={18} />}
|
|
4035
|
+
placeholder="Enter your password"
|
|
4036
|
+
required
|
|
4037
|
+
/>
|
|
4038
|
+
</div>
|
|
4039
|
+
```
|
|
4040
|
+
|
|
4041
|
+
**Variants:** `primary` `secondary` `accent` `info` `success` `warning` `error` `outline` `ghost` `glass`
|
|
4042
|
+
**Sizes:** `sm` `md` `lg` `xl`
|
|
4043
|
+
**Input Types:** All HTML input types except `file`
|
|
4044
|
+
|
|
4045
|
+
**Props:**
|
|
4046
|
+
|
|
4047
|
+
| Prop | Type | Default | Description |
|
|
4048
|
+
| --------------------- | ------------- | ----------- | ---------------------------------------- |
|
|
4049
|
+
| `variant` | `InputVariant`| `'outline'` | Visual variant |
|
|
4050
|
+
| `size` | `InputSize` | `'md'` | Size variant |
|
|
4051
|
+
| `type` | `InputType` | `'text'` | HTML input type (excludes file) |
|
|
4052
|
+
| `label` | `string` | `undefined` | Label text for the input |
|
|
4053
|
+
| `helperText` | `string` | `undefined` | Helper text below input |
|
|
4054
|
+
| `error` | `string` | `undefined` | Error message (overrides helperText) |
|
|
4055
|
+
| `startIcon` | `ReactNode` | `undefined` | Icon on the left side |
|
|
4056
|
+
| `endIcon` | `ReactNode` | `undefined` | Icon on the right side |
|
|
4057
|
+
| `showCounter` | `boolean` | `false` | Show character counter (needs maxLength) |
|
|
4058
|
+
| `required` | `boolean` | `false` | Mark field as required |
|
|
4059
|
+
| `fullWidth` | `boolean` | `false` | Full width styling |
|
|
4060
|
+
| `containerClassName` | `string` | `undefined` | Custom className for container |
|
|
4061
|
+
| `labelClassName` | `string` | `undefined` | Custom className for label |
|
|
4062
|
+
| `disabled` | `boolean` | `false` | Disable the input |
|
|
4063
|
+
| `maxLength` | `number` | `undefined` | Maximum character length |
|
|
4064
|
+
| `...props` | `InputHTMLAttributes` | - | All standard input attributes |
|
|
4065
|
+
|
|
4066
|
+
**Features:**
|
|
4067
|
+
|
|
4068
|
+
- 🎨 10 visual variants matching design system
|
|
4069
|
+
- 📐 4 size options (sm, md, lg, xl)
|
|
4070
|
+
- 🔤 Supports all HTML input types except file
|
|
4071
|
+
- 🖼️ Icon support (start and end positions)
|
|
4072
|
+
- ✅ Built-in validation states
|
|
4073
|
+
- 📝 Character counter with maxLength
|
|
4074
|
+
- 💬 Helper text and error messaging
|
|
4075
|
+
- ⚠️ Required field indicators
|
|
4076
|
+
- 📱 Full width responsive option
|
|
4077
|
+
- ⌨️ Standard input attributes support
|
|
4078
|
+
- 🎭 Smooth transitions and focus states
|
|
4079
|
+
- 🌓 Theme-aware styling
|
|
4080
|
+
- ♿ Accessible with proper labels
|
|
4081
|
+
- 🔒 Type-safe with TypeScript
|
|
4082
|
+
- 🎪 Hover and focus effects
|
|
4083
|
+
- 🔧 **No SCSS required - pure Tailwind**
|
|
4084
|
+
|
|
4085
|
+
---
|
|
4086
|
+
|
|
1120
4087
|
## 🎨 Theming
|
|
1121
4088
|
|
|
1122
4089
|
### Theme Provider
|