saha-ui 1.4.0 → 1.5.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.
Files changed (83) hide show
  1. package/README.md +612 -184
  2. package/dist/components/Accordion/index.d.ts.map +1 -1
  3. package/dist/components/Accordion/index.js +73 -73
  4. package/dist/components/Alert/index.js +24 -24
  5. package/dist/components/Avatar/index.d.ts.map +1 -1
  6. package/dist/components/Avatar/index.js +42 -42
  7. package/dist/components/AvatarGroup/AvatarGroup.types.d.ts +4 -4
  8. package/dist/components/AvatarGroup/AvatarGroup.types.d.ts.map +1 -1
  9. package/dist/components/AvatarGroup/index.d.ts +7 -12
  10. package/dist/components/AvatarGroup/index.d.ts.map +1 -1
  11. package/dist/components/AvatarGroup/index.js +71 -70
  12. package/dist/components/Badge/index.js +34 -34
  13. package/dist/components/Breadcrumb/index.js +49 -49
  14. package/dist/components/ButtonGroup/index.d.ts.map +1 -1
  15. package/dist/components/ButtonGroup/index.js +74 -71
  16. package/dist/components/Carousel/index.d.ts.map +1 -1
  17. package/dist/components/Carousel/index.js +75 -75
  18. package/dist/components/Chip/index.js +29 -29
  19. package/dist/components/Divider/index.js +20 -20
  20. package/dist/components/Image/index.d.ts.map +1 -1
  21. package/dist/components/Image/index.js +81 -78
  22. package/dist/components/Input/index.js +72 -72
  23. package/dist/components/Link/index.js +35 -35
  24. package/dist/components/Pagination/index.d.ts.map +1 -1
  25. package/dist/components/Pagination/index.js +186 -92
  26. package/dist/components/PlayButton/index.d.ts.map +1 -1
  27. package/dist/components/PlayButton/index.js +34 -32
  28. package/dist/components/Progress/index.d.ts +2 -2
  29. package/dist/components/Progress/index.d.ts.map +1 -1
  30. package/dist/components/Progress/index.js +70 -53
  31. package/dist/components/Rating/index.d.ts.map +1 -1
  32. package/dist/components/Rating/index.js +92 -92
  33. package/dist/components/Skeleton/index.d.ts.map +1 -1
  34. package/dist/components/Skeleton/index.js +59 -43
  35. package/dist/components/Spinner/Spinner.types.d.ts +76 -0
  36. package/dist/components/Spinner/Spinner.types.d.ts.map +1 -0
  37. package/dist/components/Spinner/index.d.ts +31 -0
  38. package/dist/components/Spinner/index.d.ts.map +1 -0
  39. package/dist/components/Spinner/index.js +590 -0
  40. package/dist/components/Tab/index.d.ts.map +1 -1
  41. package/dist/components/Tab/index.js +277 -104
  42. package/dist/components/Table/index.d.ts.map +1 -1
  43. package/dist/components/Table/index.js +101 -95
  44. package/dist/components/Tooltip/Tooltip.types.d.ts +46 -21
  45. package/dist/components/Tooltip/Tooltip.types.d.ts.map +1 -1
  46. package/dist/components/Tooltip/index.d.ts +31 -12
  47. package/dist/components/Tooltip/index.d.ts.map +1 -1
  48. package/dist/components/Tooltip/index.js +134 -98
  49. package/dist/index.d.ts +4 -2
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +53 -49
  52. package/package.json +1 -1
  53. package/dist/components/Accordion/Accordion.types.js +0 -1
  54. package/dist/components/Alert/Alert.types.js +0 -1
  55. package/dist/components/Avatar/Avatar.types.js +0 -1
  56. package/dist/components/AvatarGroup/AvatarGroup.types.js +0 -1
  57. package/dist/components/Badge/Badge.types.js +0 -1
  58. package/dist/components/Breadcrumb/Breadcrumb.types.js +0 -1
  59. package/dist/components/Button/Button.types.js +0 -1
  60. package/dist/components/ButtonGroup/ButtonGroup.types.js +0 -1
  61. package/dist/components/Card/Card.types.js +0 -1
  62. package/dist/components/Carousel/Carousel.types.js +0 -1
  63. package/dist/components/Chip/Chip.types.js +0 -1
  64. package/dist/components/DatePicker/DatePicker.types.js +0 -1
  65. package/dist/components/Divider/Divider.types.js +0 -1
  66. package/dist/components/Image/Image.types.js +0 -1
  67. package/dist/components/Input/Input.types.js +0 -1
  68. package/dist/components/Link/Link.types.js +0 -1
  69. package/dist/components/List/List.types.js +0 -1
  70. package/dist/components/Pagination/Pagination.types.js +0 -1
  71. package/dist/components/PlayButton/PlayButton.types.js +0 -1
  72. package/dist/components/Popover/Popover.types.js +0 -1
  73. package/dist/components/Progress/Progress.types.js +0 -1
  74. package/dist/components/Rating/Rating.types.js +0 -1
  75. package/dist/components/Skeleton/Skeleton.types.js +0 -1
  76. package/dist/components/Steps/Steps.types.js +0 -1
  77. package/dist/components/Tab/Tab.types.js +0 -1
  78. package/dist/components/Table/Table.types.js +0 -1
  79. package/dist/components/ThemeProvider/ThemeProvider.types.js +0 -1
  80. package/dist/components/ThemeToggle/ThemeToggle.types.js +0 -1
  81. package/dist/components/Timeline/Timeline.types.js +0 -1
  82. package/dist/components/Tooltip/Tooltip.types.js +0 -1
  83. package/dist/components/Tree/Tree.types.js +0 -1
package/README.md CHANGED
@@ -166,6 +166,7 @@ import { cn } from "saha-ui/lib/utils";
166
166
  | **Popover** | Rich content popover with 11 variants, 12 positions, 4 triggers | ✅ | ✅ |
167
167
  | **PlayButton** | Animated play/pause button with 9 variants, 4 sizes, smooth transitions | ✅ | ✅ |
168
168
  | **Skeleton** | Loading placeholder with 5 variants, 4 shapes, customizable animations | ✅ | ✅ |
169
+ | **Spinner** | Loading spinner with 10 variants, 6 sizes, 4 animations, fullscreen mode | ✅ | ✅ |
169
170
  | **Pagination** | Page navigation with 5 variants, 3 sizes, ellipsis, customizable labels | ✅ | ✅ |
170
171
  | **DatePicker** | Calendar date picker with 5 variants, 3 sizes, date restrictions | ✅ | ✅ |
171
172
  | **Tab** | Tab navigation with 14 variants, 3 sizes, icons, badges, disabled states | ✅ | ✅ |
@@ -202,10 +203,9 @@ import { ButtonGroup, Button } from "saha-ui";
202
203
  ```tsx
203
204
  import { Alert } from "saha-ui";
204
205
 
205
- <Alert status="success">Operation completed successfully!</Alert>
206
- <Alert status="error" variant="filled" dismissible>
207
- Error occurred!
208
- </Alert>
206
+ <Alert status="success" message="Operation completed successfully!" />
207
+ <Alert status="danger" variant="solid" message="Error occurred!" closeable />
208
+ <Alert status="warning" variant="glass" title="Warning" message="Please review before proceeding." />
209
209
  ```
210
210
 
211
211
  ### Badge
@@ -221,16 +221,34 @@ import { Badge } from "saha-ui";
221
221
  ### Breadcrumb
222
222
 
223
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
- ];
224
+ import { Breadcrumb, BreadcrumbItem, BreadcrumbSeparator } from "saha-ui";
231
225
 
232
- <Breadcrumb items={items} />
233
- <Breadcrumb items={items} variant="pills" separator="arrow" />
226
+ // Basic breadcrumb
227
+ <Breadcrumb>
228
+ <BreadcrumbItem href="/">Home</BreadcrumbItem>
229
+ <BreadcrumbSeparator />
230
+ <BreadcrumbItem href="/products">Products</BreadcrumbItem>
231
+ <BreadcrumbSeparator />
232
+ <BreadcrumbItem isCurrentPage>Details</BreadcrumbItem>
233
+ </Breadcrumb>
234
+
235
+ // With variants and separator types
236
+ <Breadcrumb variant="pills" separator="arrow">
237
+ <BreadcrumbItem href="/">Home</BreadcrumbItem>
238
+ <BreadcrumbSeparator />
239
+ <BreadcrumbItem href="/products">Products</BreadcrumbItem>
240
+ <BreadcrumbSeparator />
241
+ <BreadcrumbItem isCurrentPage>Electronics</BreadcrumbItem>
242
+ </Breadcrumb>
243
+
244
+ // Other separator options: "chevron" (default), "slash", "dot", "arrow"
245
+ <Breadcrumb variant="glass" separator="slash">
246
+ <BreadcrumbItem href="/">Home</BreadcrumbItem>
247
+ <BreadcrumbSeparator />
248
+ <BreadcrumbItem href="/docs">Docs</BreadcrumbItem>
249
+ <BreadcrumbSeparator />
250
+ <BreadcrumbItem isCurrentPage>API</BreadcrumbItem>
251
+ </Breadcrumb>
234
252
  ```
235
253
 
236
254
  ### Card
@@ -251,13 +269,26 @@ import { Card, CardHeader, CardTitle, CardContent } from "saha-ui";
251
269
  ```tsx
252
270
  import { Chip } from "saha-ui";
253
271
 
254
- <Chip color="primary">JavaScript</Chip>
255
- <Chip deletable onDelete={() => console.log('deleted')}>
272
+ // Basic chips with variants
273
+ <Chip variant="filled" color="primary">JavaScript</Chip>
274
+ <Chip variant="outlined" color="secondary">TypeScript</Chip>
275
+ <Chip variant="soft" color="success">React</Chip>
276
+ <Chip variant="glass" color="primary">Saha UI</Chip>
277
+
278
+ // Deletable chip
279
+ <Chip deletable onDelete={() => console.log('deleted')} color="error">
256
280
  Remove me
257
281
  </Chip>
258
- <Chip clickable onClick={() => alert('clicked')}>
282
+
283
+ // Clickable chip
284
+ <Chip clickable onClick={() => alert('clicked')} color="info">
259
285
  Click me
260
286
  </Chip>
287
+
288
+ // With avatars
289
+ <Chip avatar={<Avatar name="JD" size="xs" />} color="primary">
290
+ John Doe
291
+ </Chip>
261
292
  ```
262
293
 
263
294
  ### Divider
@@ -274,21 +305,26 @@ import { Divider } from "saha-ui";
274
305
  ### Accordion
275
306
 
276
307
  ```tsx
277
- import { Accordion } from "saha-ui";
308
+ import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from "saha-ui";
278
309
 
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
- ];
310
+ <Accordion type="single" collapsible>
311
+ <AccordionItem value="item-1">
312
+ <AccordionTrigger>Section 1</AccordionTrigger>
313
+ <AccordionContent>Content for section 1</AccordionContent>
314
+ </AccordionItem>
315
+ <AccordionItem value="item-2">
316
+ <AccordionTrigger>Section 2</AccordionTrigger>
317
+ <AccordionContent>Content for section 2</AccordionContent>
318
+ </AccordionItem>
319
+ </Accordion>
289
320
 
290
- <Accordion items={items} />
291
- <Accordion items={items} variant="bordered" defaultOpen={[0]} />
321
+ // Multiple items open at once
322
+ <Accordion type="multiple" variant="glass">
323
+ <AccordionItem value="item-1">
324
+ <AccordionTrigger>Section 1</AccordionTrigger>
325
+ <AccordionContent>Content here</AccordionContent>
326
+ </AccordionItem>
327
+ </Accordion>
292
328
  ```
293
329
 
294
330
  ### Avatar
@@ -317,26 +353,32 @@ import { AvatarGroup, Avatar } from "saha-ui";
317
353
  ### Tooltip
318
354
 
319
355
  ```tsx
320
- import { Tooltip } from "saha-ui";
356
+ import { Tooltip, TooltipTrigger, TooltipContent } from "saha-ui";
321
357
 
322
358
  // Basic tooltip
323
- <Tooltip content="This is a tooltip">
324
- <Button>Hover me</Button>
359
+ <Tooltip>
360
+ <TooltipTrigger>
361
+ <Button>Hover me</Button>
362
+ </TooltipTrigger>
363
+ <TooltipContent>This is a tooltip</TooltipContent>
325
364
  </Tooltip>
326
365
 
327
366
  // With variant and position
328
- <Tooltip content="Success message!" variant="success" position="right">
329
- <Badge variant="success">Active</Badge>
367
+ <Tooltip variant="success" position="right">
368
+ <TooltipTrigger>
369
+ <Badge variant="success">Active</Badge>
370
+ </TooltipTrigger>
371
+ <TooltipContent>Success message!</TooltipContent>
330
372
  </Tooltip>
331
373
 
332
374
  // 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>
375
+ <Tooltip interactive trigger="click" variant="glass">
376
+ <TooltipTrigger>
377
+ <Button>Click Me</Button>
378
+ </TooltipTrigger>
379
+ <TooltipContent>
380
+ <div>Click <a href="#">here</a> for more</div>
381
+ </TooltipContent>
340
382
  </Tooltip>
341
383
  ```
342
384
 
@@ -355,54 +397,73 @@ import { Link } from "saha-ui";
355
397
  ### List
356
398
 
357
399
  ```tsx
358
- import { List } from "saha-ui";
400
+ import { List, ListItem } from "saha-ui";
401
+ import { CheckCircle } from "lucide-react";
359
402
 
360
- const items = [
361
- { id: 1, content: 'First item' },
362
- { id: 2, content: 'Second item' },
363
- { id: 3, content: 'Third item' }
364
- ];
403
+ <List variant="bordered">
404
+ <ListItem>First item</ListItem>
405
+ <ListItem>Second item</ListItem>
406
+ <ListItem>Third item</ListItem>
407
+ </List>
365
408
 
366
- <List items={items} />
367
- <List items={items} variant="bordered" />
409
+ // With icons
410
+ <List variant="cards">
411
+ <ListItem icon={<CheckCircle size={18} />}>Completed task</ListItem>
412
+ <ListItem icon={<CheckCircle size={18} />}>Another task</ListItem>
413
+ </List>
368
414
  ```
369
415
 
370
416
  ### Timeline
371
417
 
372
418
  ```tsx
373
- import { Timeline } from "saha-ui";
419
+ import { Timeline, TimelineItem } from "saha-ui";
374
420
  import { Rocket, Package, Check } from "lucide-react";
375
421
 
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
- ];
422
+ <Timeline variant="gradient">
423
+ <TimelineItem
424
+ icon={<Rocket size={18} />}
425
+ title="Project Started"
426
+ description="Initial setup"
427
+ time="2 hours ago"
428
+ />
429
+ <TimelineItem
430
+ icon={<Package size={18} />}
431
+ title="Development"
432
+ description="Building features"
433
+ time="1 hour ago"
434
+ status="primary"
435
+ />
436
+ <TimelineItem
437
+ icon={<Check size={18} />}
438
+ title="Completed"
439
+ description="Ready to deploy"
440
+ time="Just now"
441
+ status="success"
442
+ />
443
+ </Timeline>
381
444
 
382
- <Timeline items={events} />
383
- <Timeline items={events} variant="gradient" position="alternate" />
445
+ // Alternate positioning
446
+ <Timeline position="alternate">
447
+ <TimelineItem title="Event 1" />
448
+ <TimelineItem title="Event 2" />
449
+ </Timeline>
384
450
  ```
385
451
 
386
452
  ### Tree
387
453
 
388
454
  ```tsx
389
- import { Tree } from "saha-ui";
455
+ import { Tree, TreeItem } from "saha-ui";
390
456
  import { Folder, File } from "lucide-react";
391
457
 
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)} />
458
+ <Tree variant="glass">
459
+ <TreeItem label="src" icon={<Folder size={16} />}>
460
+ <TreeItem label="components" icon={<Folder size={16} />}>
461
+ <TreeItem label="Button.tsx" icon={<File size={16} />} />
462
+ <TreeItem label="Card.tsx" icon={<File size={16} />} />
463
+ </TreeItem>
464
+ <TreeItem label="App.tsx" icon={<File size={16} />} />
465
+ </TreeItem>
466
+ </Tree>;
406
467
  ```
407
468
 
408
469
  ### Image
@@ -428,51 +489,92 @@ import { Image } from "saha-ui";
428
489
  ### Carousel
429
490
 
430
491
  ```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 />
492
+ import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } from "saha-ui";
493
+
494
+ <Carousel autoplay autoplayInterval={3000}>
495
+ <CarouselContent>
496
+ <CarouselItem>
497
+ <img src="/image1.jpg" alt="Slide 1" />
498
+ </CarouselItem>
499
+ <CarouselItem>
500
+ <img src="/image2.jpg" alt="Slide 2" />
501
+ </CarouselItem>
502
+ <CarouselItem>
503
+ <img src="/image3.jpg" alt="Slide 3" />
504
+ </CarouselItem>
505
+ </CarouselContent>
506
+ <CarouselPrevious />
507
+ <CarouselNext />
508
+ </Carousel>
509
+
510
+ // With variants
511
+ <Carousel variant="glass" autoplay>
512
+ <CarouselContent>
513
+ {/* Your carousel items */}
514
+ </CarouselContent>
515
+ <CarouselPrevious />
516
+ <CarouselNext />
517
+ </Carousel>
441
518
  ```
442
519
 
443
520
  ### Steps
444
521
 
445
522
  ```tsx
446
- import { Steps } from "saha-ui";
523
+ import { Steps, StepsItem } from "saha-ui";
524
+ import { User, CreditCard, Check } from "lucide-react";
447
525
 
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
- ];
526
+ <Steps defaultValue={2}>
527
+ <StepsItem value={1} title="Account" description="Create your account" />
528
+ <StepsItem value={2} title="Profile" description="Fill in your details" />
529
+ <StepsItem value={3} title="Complete" description="You're all set!" />
530
+ </Steps>
531
+
532
+ // With icons
533
+ <Steps defaultValue={2} variant="glass">
534
+ <StepsItem value={1} title="Info" icon={<User className="w-5 h-5" />} />
535
+ <StepsItem value={2} title="Payment" icon={<CreditCard className="w-5 h-5" />} />
536
+ <StepsItem value={3} title="Done" icon={<Check className="w-5 h-5" />} />
537
+ </Steps>
453
538
 
454
- <Steps steps={steps} current={1} />
455
- <Steps steps={steps} current={1} variant="glass" orientation="vertical" />
539
+ // Vertical orientation
540
+ <Steps orientation="vertical" defaultValue={1}>
541
+ <StepsItem value={1} title="Step 1" status="completed" />
542
+ <StepsItem value={2} title="Step 2" status="current" />
543
+ <StepsItem value={3} title="Step 3" status="pending" />
544
+ </Steps>
456
545
  ```
457
546
 
458
547
  ### Table
459
548
 
460
549
  ```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 />
550
+ import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from "saha-ui";
551
+
552
+ <Table>
553
+ <TableHeader>
554
+ <TableRow>
555
+ <TableHead>Name</TableHead>
556
+ <TableHead>Email</TableHead>
557
+ <TableHead>Role</TableHead>
558
+ </TableRow>
559
+ </TableHeader>
560
+ <TableBody>
561
+ <TableRow>
562
+ <TableCell>Alice Johnson</TableCell>
563
+ <TableCell>alice@example.com</TableCell>
564
+ <TableCell>Admin</TableCell>
565
+ </TableRow>
566
+ <TableRow>
567
+ <TableCell>Bob Smith</TableCell>
568
+ <TableCell>bob@example.com</TableCell>
569
+ <TableCell>Developer</TableCell>
570
+ </TableRow>
571
+ </TableBody>
572
+ </Table>
573
+
574
+ // With variants
575
+ <Table variant="bordered" hoverable>
576
+ {/* Table content */}
577
+ </Table>
476
578
  ```
477
579
 
478
580
  ### Rating
@@ -547,6 +649,53 @@ import { Skeleton } from "saha-ui";
547
649
  <Skeleton shape="circle" width="48px" height="48px" variant="pulse" />
548
650
  ```
549
651
 
652
+ ### Spinner
653
+
654
+ ```tsx
655
+ import { Spinner } from "saha-ui";
656
+
657
+ // Basic usage
658
+ <Spinner />
659
+
660
+ // With variants and sizes
661
+ <Spinner variant="success" size="lg" label="Loading..." />
662
+
663
+ // Different spinner types (15 types available!)
664
+ <Spinner type="ring" variant="primary" size="lg" />
665
+ <Spinner type="orbit" variant="gradient" size="xl" />
666
+ <Spinner type="flower" variant="success" size="lg" />
667
+ <Spinner type="infinity" variant="primary" size="2xl" />
668
+ <Spinner type="wave" variant="info" size="md" />
669
+ <Spinner type="spiral" variant="accent" size="lg" />
670
+
671
+ // Fullscreen overlay
672
+ <Spinner variant="gradient" animation="pulse" fullscreen />
673
+
674
+ // With custom logo/icon
675
+ <Spinner
676
+ variant="primary"
677
+ size="xl"
678
+ logo="/your-logo.png"
679
+ logoSize="md"
680
+ label="Loading..."
681
+ />
682
+
683
+ // With custom component
684
+ <Spinner
685
+ type="orbit"
686
+ variant="success"
687
+ size="xl"
688
+ logo={<YourCustomIcon />}
689
+ logoSize="lg"
690
+ />
691
+
692
+ // In buttons
693
+ <Button variant="primary" disabled>
694
+ <Spinner type="bounce" size="sm" variant="default" />
695
+ Loading...
696
+ </Button>
697
+ ```
698
+
550
699
  ### Pagination
551
700
 
552
701
  ```tsx
@@ -564,33 +713,51 @@ import { Pagination } from "saha-ui";
564
713
  ```tsx
565
714
  import { DatePicker } from "saha-ui";
566
715
 
567
- <DatePicker value={date} onChange={(date) => setDate(date)} />
716
+ // Single date picker
717
+ <DatePicker
718
+ value={{ startDate: date, endDate: date }}
719
+ onChange={(value) => setDate(value)}
720
+ asSingle
721
+ placeholder="Select date"
722
+ />
568
723
 
569
- <DatePicker variant="primary" size="lg" placeholder="Pick a date" />
724
+ // Date range picker
725
+ <DatePicker
726
+ value={{ startDate: null, endDate: null }}
727
+ onChange={(value) => setRange(value)}
728
+ placeholder="Select date range"
729
+ />
570
730
 
571
- <DatePicker minDate={new Date()} maxDate={futureDate} />
731
+ // With variants and restrictions
732
+ <DatePicker
733
+ variant="primary"
734
+ minDate={new Date()}
735
+ maxDate={futureDate}
736
+ asSingle
737
+ />
572
738
  ```
573
739
 
574
740
  ### Tab
575
741
 
576
742
  ```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
- />
743
+ import { Tabs, TabsList, TabsTrigger, TabsContent } from "saha-ui";
744
+
745
+ <Tabs defaultValue="profile">
746
+ <TabsList>
747
+ <TabsTrigger value="profile">Profile</TabsTrigger>
748
+ <TabsTrigger value="settings">Settings</TabsTrigger>
749
+ </TabsList>
750
+ <TabsContent value="profile">Profile content</TabsContent>
751
+ <TabsContent value="settings">Settings content</TabsContent>
752
+ </Tabs>
753
+
754
+ // With variants and sizes
755
+ <Tabs defaultValue="home" variant="primary" size="lg">
756
+ <TabsList>
757
+ <TabsTrigger value="home">Home</TabsTrigger>
758
+ <TabsTrigger value="messages">Messages</TabsTrigger>
759
+ </TabsList>
760
+ </Tabs>
594
761
  ```
595
762
 
596
763
  ### Input
@@ -1555,22 +1722,21 @@ Display multiple avatars with overlap and count indicator.
1555
1722
  **Sizes:** `xs` `sm` `md` `lg` `xl` `2xl`
1556
1723
 
1557
1724
  ```tsx
1558
- import { AvatarGroup } from "saha-ui";
1725
+ import { AvatarGroup, Avatar } from "saha-ui";
1559
1726
 
1560
1727
  <AvatarGroup
1561
- avatars={[
1562
- { src: "/user1.jpg", alt: "User 1" },
1563
- { src: "/user2.jpg", alt: "User 2" },
1564
- { src: "/user3.jpg", alt: "User 3" },
1565
- { src: "/user4.jpg", alt: "User 4" },
1566
- ]}
1567
1728
  max={3}
1568
1729
  size="md"
1569
1730
  variant="stack"
1570
1731
  gap={false}
1571
1732
  withRing={false}
1572
1733
  showCount
1573
- />;
1734
+ >
1735
+ <Avatar src="/user1.jpg" alt="User 1" />
1736
+ <Avatar src="/user2.jpg" alt="User 2" />
1737
+ <Avatar src="/user3.jpg" alt="User 3" />
1738
+ <Avatar src="/user4.jpg" alt="User 4" />
1739
+ </AvatarGroup>;
1574
1740
  ```
1575
1741
 
1576
1742
  **Features:**
@@ -1593,62 +1759,63 @@ Contextual hints and information with smart positioning, multiple trigger types,
1593
1759
  **Triggers:** `hover` `click` `focus` `manual`
1594
1760
 
1595
1761
  ```tsx
1596
- import { Tooltip } from "saha-ui";
1762
+ import { Tooltip, TooltipTrigger, TooltipContent } from "saha-ui";
1597
1763
 
1598
1764
  // Basic tooltip
1599
- <Tooltip
1600
- content="This is helpful information"
1601
- position="top"
1602
- variant="glass"
1603
- >
1604
- <Button>Hover me</Button>
1765
+ <Tooltip position="top" variant="glass">
1766
+ <TooltipTrigger>
1767
+ <Button>Hover me</Button>
1768
+ </TooltipTrigger>
1769
+ <TooltipContent>This is helpful information</TooltipContent>
1605
1770
  </Tooltip>
1606
1771
 
1607
1772
  // Status tooltips
1608
- <Tooltip content="All systems operational" variant="success">
1609
- <Badge variant="success">Active</Badge>
1773
+ <Tooltip variant="success">
1774
+ <TooltipTrigger>
1775
+ <Badge variant="success">Active</Badge>
1776
+ </TooltipTrigger>
1777
+ <TooltipContent>All systems operational</TooltipContent>
1610
1778
  </Tooltip>
1611
1779
 
1612
- <Tooltip content="Warning: Check this!" variant="warning" position="right">
1613
- <span className="cursor-help">⚠</span>
1780
+ <Tooltip variant="warning" position="right">
1781
+ <TooltipTrigger>
1782
+ <span className="cursor-help">⚠</span>
1783
+ </TooltipTrigger>
1784
+ <TooltipContent>Warning: Check this!</TooltipContent>
1614
1785
  </Tooltip>
1615
1786
 
1616
1787
  // Interactive tooltip with click trigger
1617
- <Tooltip
1618
- content={
1788
+ <Tooltip interactive trigger="click" variant="glass" maxWidth="200px">
1789
+ <TooltipTrigger>
1790
+ <Button>Click for Options</Button>
1791
+ </TooltipTrigger>
1792
+ <TooltipContent>
1619
1793
  <div className="space-y-2">
1620
1794
  <p className="font-semibold">Interactive Content</p>
1621
1795
  <Button size="sm">Click Me</Button>
1622
1796
  </div>
1623
- }
1624
- interactive={true}
1625
- trigger="click"
1626
- variant="glass"
1627
- maxWidth="200px"
1628
- >
1629
- <Button>Click for Options</Button>
1797
+ </TooltipContent>
1630
1798
  </Tooltip>
1631
1799
 
1632
1800
  // Controlled tooltip
1633
1801
  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>
1802
+ <Tooltip open={open} onOpenChange={setOpen} trigger="manual">
1803
+ <TooltipTrigger>
1804
+ <Button onClick={() => setOpen(!open)}>Toggle</Button>
1805
+ </TooltipTrigger>
1806
+ <TooltipContent>Controlled tooltip</TooltipContent>
1641
1807
  </Tooltip>
1642
1808
 
1643
1809
  // Help icon tooltips
1644
1810
  <div className="flex items-center gap-2">
1645
1811
  <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>
1812
+ <Tooltip variant="info" size="sm">
1813
+ <TooltipTrigger>
1814
+ <span className="cursor-help text-muted-foreground">ⓘ</span>
1815
+ </TooltipTrigger>
1816
+ <TooltipContent>
1817
+ Enter your unique username (3-20 characters)
1818
+ </TooltipContent>
1652
1819
  </Tooltip>
1653
1820
  </div>
1654
1821
 
@@ -3379,6 +3546,267 @@ import { Skeleton } from "saha-ui";
3379
3546
 
3380
3547
  ---
3381
3548
 
3549
+ ### Spinner
3550
+
3551
+ Modern loading spinner with multiple variants, animations, and fullscreen overlay support.
3552
+
3553
+ **Basic Usage:**
3554
+
3555
+ ```tsx
3556
+ import { Spinner } from "saha-ui";
3557
+
3558
+ // Basic spinner
3559
+ <Spinner />
3560
+
3561
+ // With label
3562
+ <Spinner variant="primary" label="Loading..." />
3563
+
3564
+ // Custom size and variant
3565
+ <Spinner variant="success" size="lg" label="Processing..." />
3566
+ ```
3567
+
3568
+ **Variants:**
3569
+
3570
+ ```tsx
3571
+ // 10 beautiful variants
3572
+ <Spinner variant="default" />
3573
+ <Spinner variant="primary" />
3574
+ <Spinner variant="secondary" />
3575
+ <Spinner variant="accent" />
3576
+ <Spinner variant="info" />
3577
+ <Spinner variant="success" />
3578
+ <Spinner variant="warning" />
3579
+ <Spinner variant="error" />
3580
+ <Spinner variant="glass" />
3581
+ <Spinner variant="gradient" />
3582
+ ```
3583
+
3584
+ **Sizes:**
3585
+
3586
+ ```tsx
3587
+ <Spinner size="xs" /> // 16px
3588
+ <Spinner size="sm" /> // 24px
3589
+ <Spinner size="md" /> // 40px (default)
3590
+ <Spinner size="lg" /> // 64px
3591
+ <Spinner size="xl" /> // 96px
3592
+ <Spinner size="2xl" /> // 128px
3593
+ ```
3594
+
3595
+ **Spinner Types (15 unique designs!):**
3596
+
3597
+ ```tsx
3598
+ // Classic Types
3599
+ <Spinner type="ring" /> // Classic circular border (default)
3600
+ <Spinner type="dots" /> // Rotating dots in circle
3601
+ <Spinner type="dashed" /> // Dashed ring border
3602
+ <Spinner type="bars" /> // Rotating bars/lines
3603
+ <Spinner type="dotRing" /> // Complete circle of dots
3604
+
3605
+ // Creative & Unique Types ✨
3606
+ <Spinner type="orbit" /> // Multi-orbit planetary system
3607
+ <Spinner type="pulse" /> // Expanding concentric circles
3608
+ <Spinner type="square" /> // Rotating square corners
3609
+ <Spinner type="triangle" /> // Triangular rotating pattern
3610
+ <Spinner type="wave" /> // Sequential bouncing bars
3611
+ <Spinner type="spiral" /> // Expanding spiral pattern
3612
+ <Spinner type="infinity" /> // Infinity symbol (∞) path
3613
+ <Spinner type="flower" /> // Flower petal pattern
3614
+ <Spinner type="grid" /> // 3×3 pulsing grid
3615
+ <Spinner type="bounce" /> // Classic bouncing dots
3616
+ ```
3617
+
3618
+ **Animation Types:**
3619
+
3620
+ ```tsx
3621
+ <Spinner animation="spin" /> // Continuous rotation (default)
3622
+ <Spinner animation="pulse" /> // Scale pulsing
3623
+ <Spinner animation="bounce" /> // Bouncing effect
3624
+ <Spinner animation="ping" /> // Ping ripple effect
3625
+ ```
3626
+
3627
+ **Thickness:**
3628
+
3629
+ ```tsx
3630
+ <Spinner thickness="thin" /> // 2px border
3631
+ <Spinner thickness="default" /> // 4px border
3632
+ <Spinner thickness="thick" /> // 6px border
3633
+ ```
3634
+
3635
+ **Speed Control:**
3636
+
3637
+ ```tsx
3638
+ <Spinner speed={0.5} /> // Slower
3639
+ <Spinner speed={1} /> // Normal (default)
3640
+ <Spinner speed={2} /> // Faster
3641
+ <Spinner speed={3} /> // Very fast
3642
+ ```
3643
+
3644
+ **Fullscreen Overlay:**
3645
+
3646
+ ```tsx
3647
+ // Full screen loading overlay
3648
+ <Spinner
3649
+ fullscreen
3650
+ variant="gradient"
3651
+ size="2xl"
3652
+ label="Loading application..."
3653
+ />
3654
+ ```
3655
+
3656
+ **In Buttons:**
3657
+
3658
+ ```tsx
3659
+ // Disabled button with loading spinner
3660
+ <Button variant="primary" disabled>
3661
+ <Spinner size="sm" variant="default" />
3662
+ Loading...
3663
+ </Button>
3664
+
3665
+ <Button variant="success" disabled>
3666
+ <Spinner size="sm" variant="default" />
3667
+ Saving...
3668
+ </Button>
3669
+ ```
3670
+
3671
+ **In Cards:**
3672
+
3673
+ ```tsx
3674
+ <Card>
3675
+ <CardHeader>
3676
+ <CardTitle>Loading Data</CardTitle>
3677
+ </CardHeader>
3678
+ <CardContent className="flex items-center justify-center py-8">
3679
+ <Spinner variant="primary" label="Fetching data..." />
3680
+ </CardContent>
3681
+ </Card>
3682
+ ```
3683
+
3684
+ **With Custom Logo/Icon:**
3685
+
3686
+ ```tsx
3687
+ // Image URL
3688
+ <Spinner
3689
+ variant="primary"
3690
+ size="xl"
3691
+ logo="/your-logo.png"
3692
+ logoSize="md"
3693
+ label="Loading..."
3694
+ />
3695
+
3696
+ // Custom React component
3697
+ <Spinner
3698
+ variant="success"
3699
+ size="xl"
3700
+ logo={
3701
+ <div className="w-full h-full flex items-center justify-center bg-success/10 rounded-full">
3702
+ <span className="text-2xl font-bold text-success">S</span>
3703
+ </div>
3704
+ }
3705
+ logoSize="lg"
3706
+ />
3707
+
3708
+ // SVG Icon
3709
+ <Spinner
3710
+ variant="gradient"
3711
+ size="2xl"
3712
+ logo={<YourSvgIcon />}
3713
+ logoSize="md"
3714
+ label="Building..."
3715
+ />
3716
+ ```
3717
+
3718
+ **Logo Sizes:**
3719
+
3720
+ ```tsx
3721
+ <Spinner logo="/logo.png" logoSize="xs" /> // 25% of spinner size
3722
+ <Spinner logo="/logo.png" logoSize="sm" /> // 35% of spinner size
3723
+ <Spinner logo="/logo.png" logoSize="md" /> // 50% of spinner size (default)
3724
+ <Spinner logo="/logo.png" logoSize="lg" /> // 65% of spinner size
3725
+ <Spinner logo="/logo.png" logoSize="xl" /> // 80% of spinner size
3726
+ ```
3727
+
3728
+ **Real-world Examples:**
3729
+
3730
+ ```tsx
3731
+ // Form submission
3732
+ <Button type="submit" disabled={isSubmitting}>
3733
+ {isSubmitting && <Spinner size="sm" variant="default" />}
3734
+ {isSubmitting ? "Submitting..." : "Submit"}
3735
+ </Button>;
3736
+
3737
+ // Brand loading with logo
3738
+ <Spinner
3739
+ fullscreen
3740
+ variant="gradient"
3741
+ size="2xl"
3742
+ logo="/brand-logo.png"
3743
+ logoSize="lg"
3744
+ label="Loading your app..."
3745
+ />;
3746
+
3747
+ // Page loading
3748
+ {
3749
+ isLoading && (
3750
+ <Spinner
3751
+ fullscreen
3752
+ variant="primary"
3753
+ size="xl"
3754
+ label="Loading content..."
3755
+ />
3756
+ );
3757
+ }
3758
+
3759
+ // Inline loading
3760
+ <div className="flex items-center gap-3">
3761
+ <Spinner size="sm" variant="info" />
3762
+ <span>Syncing data...</span>
3763
+ </div>;
3764
+
3765
+ // Conditional rendering
3766
+ {
3767
+ isFetching ? (
3768
+ <Spinner variant="success" label="Loading items..." />
3769
+ ) : (
3770
+ <ItemsList items={items} />
3771
+ );
3772
+ }
3773
+ ```
3774
+
3775
+ **Variants:** `default` `primary` `secondary` `accent` `info` `success` `warning` `error` `glass` `gradient`
3776
+ **Sizes:** `xs` `sm` `md` `lg` `xl` `2xl`
3777
+ **Types:** `ring` `dots` `dashed` `bars` `dotRing` `orbit` `pulse` `square` `triangle` `wave` `spiral` `infinity` `flower` `grid` `bounce`
3778
+ **Animations:** `spin` `pulse` `bounce` `ping`
3779
+ **Thickness:** `thin` `default` `thick`
3780
+ **Logo Sizes:** `xs` `sm` `md` `lg` `xl`
3781
+
3782
+ **Features:**
3783
+
3784
+ - 🎨 10 stunning variants with shadows and effects
3785
+ - 🎯 **15 unique spinner types** - from classic to creative designs
3786
+ - 📏 6 size options from xs (16px) to 2xl (128px)
3787
+ - 🎭 4 different animation types
3788
+ - ⚡ Customizable animation speed (0.5x to 3x+)
3789
+ - 🎯 Optional loading labels
3790
+ - 🖼️ Fullscreen overlay mode with backdrop
3791
+ - 🔲 3 thickness options
3792
+ - 🌈 Gradient variant with multi-color effects
3793
+ - 💎 Glass variant with backdrop blur
3794
+ - 🖼️ **Custom logo/icon support** (image URL or React component)
3795
+ - 📐 5 logo size options for perfect fit
3796
+ - 🎨 Logo positioned in center with spinner animation around it
3797
+ - 🌌 **Creative types**: Orbit, Spiral, Infinity, Flower, Wave patterns
3798
+ - 🔄 All 15 types work with all 10 variants (150 combinations!)
3799
+ - ⚡ Mathematical precision for perfect centering
3800
+ - 🎪 **Unique designs**: Grid, Triangle, Pulse, Square, Bounce
3801
+ - 🌓 Theme-aware styling
3802
+ - ♿ Accessibility with proper ARIA attributes
3803
+ - 💫 Smooth CSS animations (GPU-accelerated)
3804
+ - 📱 Responsive and flexible
3805
+ - 🎛️ Works great in buttons, cards, and overlays
3806
+ - 🎨 **900+ possible configurations** (types × variants × sizes)
3807
+
3808
+ ---
3809
+
3382
3810
  ### Pagination
3383
3811
 
3384
3812
  Comprehensive pagination component for navigating through large datasets.
@@ -4044,24 +4472,24 @@ import { Mail, Lock, Search, User } from "lucide-react";
4044
4472
 
4045
4473
  **Props:**
4046
4474
 
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 |
4475
+ | Prop | Type | Default | Description |
4476
+ | -------------------- | --------------------- | ----------- | ---------------------------------------- |
4477
+ | `variant` | `InputVariant` | `'outline'` | Visual variant |
4478
+ | `size` | `InputSize` | `'md'` | Size variant |
4479
+ | `type` | `InputType` | `'text'` | HTML input type (excludes file) |
4480
+ | `label` | `string` | `undefined` | Label text for the input |
4481
+ | `helperText` | `string` | `undefined` | Helper text below input |
4482
+ | `error` | `string` | `undefined` | Error message (overrides helperText) |
4483
+ | `startIcon` | `ReactNode` | `undefined` | Icon on the left side |
4484
+ | `endIcon` | `ReactNode` | `undefined` | Icon on the right side |
4485
+ | `showCounter` | `boolean` | `false` | Show character counter (needs maxLength) |
4486
+ | `required` | `boolean` | `false` | Mark field as required |
4487
+ | `fullWidth` | `boolean` | `false` | Full width styling |
4488
+ | `containerClassName` | `string` | `undefined` | Custom className for container |
4489
+ | `labelClassName` | `string` | `undefined` | Custom className for label |
4490
+ | `disabled` | `boolean` | `false` | Disable the input |
4491
+ | `maxLength` | `number` | `undefined` | Maximum character length |
4492
+ | `...props` | `InputHTMLAttributes` | - | All standard input attributes |
4065
4493
 
4066
4494
  **Features:**
4067
4495