@svelte-atoms/core 1.0.0-alpha.27 → 1.0.0-alpha.29

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 (186) hide show
  1. package/README.md +852 -645
  2. package/dist/components/accordion/accordion-root.svelte +61 -61
  3. package/dist/components/accordion/item/accordion-item-body.svelte +42 -42
  4. package/dist/components/accordion/item/accordion-item-header.svelte +50 -50
  5. package/dist/components/accordion/item/accordion-item-indicator.svelte +50 -50
  6. package/dist/components/accordion/item/accordion-item-root.svelte +65 -65
  7. package/dist/components/alert/alert-actions.svelte +43 -42
  8. package/dist/components/alert/alert-close-button.svelte +70 -72
  9. package/dist/components/alert/alert-content.svelte +43 -42
  10. package/dist/components/alert/alert-description.svelte +42 -41
  11. package/dist/components/alert/alert-icon.svelte +47 -46
  12. package/dist/components/alert/alert-root.svelte +103 -102
  13. package/dist/components/alert/alert-title.svelte +42 -41
  14. package/dist/components/alert/alert.stories.svelte +384 -23
  15. package/dist/components/alert/alert.stories.svelte.d.ts +2 -5
  16. package/dist/components/atom/html-atom.svelte +207 -201
  17. package/dist/components/atom/html-atom.svelte.d.ts +1 -1
  18. package/dist/components/atom/snippet-renderer.svelte +5 -0
  19. package/dist/components/atom/snippet-renderer.svelte.d.ts +5 -0
  20. package/dist/components/avatar/avatar.stories.svelte.d.ts +1 -1
  21. package/dist/components/badge/badge.stories.svelte.d.ts +1 -1
  22. package/dist/components/breadcrumb/breadcrumb.stories.svelte.d.ts +1 -1
  23. package/dist/components/button/button.stories.svelte +17 -14
  24. package/dist/components/calendar/atoms.d.ts +5 -0
  25. package/dist/components/calendar/atoms.js +5 -0
  26. package/dist/components/calendar/bond.svelte.d.ts +72 -0
  27. package/dist/components/calendar/bond.svelte.js +132 -0
  28. package/dist/components/calendar/calendar-body.svelte +107 -0
  29. package/dist/components/calendar/calendar-body.svelte.d.ts +8 -0
  30. package/dist/components/calendar/calendar-day.svelte +96 -0
  31. package/dist/components/calendar/calendar-day.svelte.d.ts +4 -0
  32. package/dist/components/calendar/calendar-header.svelte +29 -0
  33. package/dist/components/calendar/calendar-header.svelte.d.ts +6 -0
  34. package/dist/components/calendar/calendar-root.svelte +206 -0
  35. package/dist/components/calendar/calendar-root.svelte.d.ts +8 -0
  36. package/dist/components/calendar/calendar-week-day.svelte +34 -0
  37. package/dist/components/calendar/calendar-week-day.svelte.d.ts +9 -0
  38. package/dist/components/calendar/calendar.css +26 -0
  39. package/dist/components/calendar/calendar.stories.svelte +31 -0
  40. package/dist/components/calendar/calendar.stories.svelte.d.ts +26 -0
  41. package/dist/components/calendar/index.d.ts +4 -0
  42. package/dist/components/calendar/index.js +4 -0
  43. package/dist/components/calendar/runes.svelte.d.ts +3 -0
  44. package/dist/components/calendar/runes.svelte.js +25 -0
  45. package/dist/components/calendar/types.d.ts +62 -0
  46. package/dist/components/calendar/types.js +1 -0
  47. package/dist/components/card/card-body.svelte +39 -39
  48. package/dist/components/card/card-description.svelte +41 -41
  49. package/dist/components/card/card-footer.svelte +41 -41
  50. package/dist/components/card/card-header.svelte +41 -41
  51. package/dist/components/card/card-media.svelte +41 -41
  52. package/dist/components/card/card-root.svelte +91 -91
  53. package/dist/components/card/card-subtitle.svelte +41 -41
  54. package/dist/components/card/card-title.svelte +45 -45
  55. package/dist/components/collapsible/collapsible-body.svelte +39 -39
  56. package/dist/components/collapsible/collapsible-header.svelte +39 -39
  57. package/dist/components/collapsible/collapsible-indicator.svelte +50 -50
  58. package/dist/components/collapsible/collapsible-root.svelte +66 -66
  59. package/dist/components/combobox/combobox-root.svelte +65 -65
  60. package/dist/components/container/container.stories.svelte.d.ts +1 -1
  61. package/dist/components/contextmenu/contextmenu-trigger.svelte.d.ts +1 -1
  62. package/dist/components/datagrid/bond.svelte.d.ts +2 -2
  63. package/dist/components/datagrid/datagrid-body.svelte +37 -37
  64. package/dist/components/datagrid/datagrid-checkbox.svelte +101 -101
  65. package/dist/components/datagrid/datagrid-footer.svelte +34 -34
  66. package/dist/components/datagrid/datagrid-header.svelte +49 -49
  67. package/dist/components/datagrid/datagrid-root.svelte +2 -2
  68. package/dist/components/datagrid/datagrid.css +5 -47
  69. package/dist/components/datagrid/td/datagrid-td.svelte +66 -66
  70. package/dist/components/datagrid/th/datagrid-th.svelte +106 -106
  71. package/dist/components/datagrid/tr/datagrid-tr.svelte +88 -88
  72. package/dist/components/datagrid/types.d.ts +1 -1
  73. package/dist/components/date-picker/atoms.d.ts +3 -0
  74. package/dist/components/date-picker/atoms.js +3 -0
  75. package/dist/components/date-picker/bond.svelte.d.ts +67 -0
  76. package/dist/components/date-picker/bond.svelte.js +174 -0
  77. package/dist/components/date-picker/date-picker-calendar.svelte +67 -0
  78. package/dist/components/date-picker/date-picker-calendar.svelte.d.ts +4 -0
  79. package/dist/components/date-picker/date-picker-header.svelte +100 -0
  80. package/dist/components/date-picker/date-picker-header.svelte.d.ts +4 -0
  81. package/dist/components/date-picker/date-picker-months.svelte +142 -0
  82. package/dist/components/date-picker/date-picker-months.svelte.d.ts +4 -0
  83. package/dist/components/date-picker/date-picker-root.svelte +95 -0
  84. package/dist/components/date-picker/date-picker-root.svelte.d.ts +4 -0
  85. package/dist/components/date-picker/date-picker-years.svelte +205 -0
  86. package/dist/components/date-picker/date-picker-years.svelte.d.ts +4 -0
  87. package/dist/components/date-picker/date-picker.stories.svelte +42 -0
  88. package/dist/components/date-picker/date-picker.stories.svelte.d.ts +3 -0
  89. package/dist/components/date-picker/index.d.ts +3 -0
  90. package/dist/components/date-picker/index.js +3 -0
  91. package/dist/components/date-picker/types.d.ts +53 -0
  92. package/dist/components/date-picker/types.js +1 -0
  93. package/dist/components/dialog/dialog-body.svelte +39 -39
  94. package/dist/components/dialog/dialog-close-button.svelte +58 -58
  95. package/dist/components/dialog/dialog-content.svelte +1 -1
  96. package/dist/components/dialog/dialog-description.svelte +40 -40
  97. package/dist/components/dialog/dialog-footer.svelte +39 -39
  98. package/dist/components/dialog/dialog-header.svelte +39 -39
  99. package/dist/components/dialog/dialog-root.svelte +110 -110
  100. package/dist/components/dialog/dialog-title.svelte +41 -41
  101. package/dist/components/drawer/drawer-backdrop.svelte +38 -38
  102. package/dist/components/drawer/drawer-body.svelte +42 -42
  103. package/dist/components/drawer/drawer-content.svelte +42 -42
  104. package/dist/components/drawer/drawer-description.svelte +44 -44
  105. package/dist/components/drawer/drawer-footer.svelte +41 -41
  106. package/dist/components/drawer/drawer-header.svelte +43 -43
  107. package/dist/components/drawer/drawer-root.svelte +93 -93
  108. package/dist/components/drawer/drawer-title.svelte +44 -44
  109. package/dist/components/dropdown/dropdown-query.svelte +54 -54
  110. package/dist/components/dropdown/dropdown-root.svelte +59 -59
  111. package/dist/components/dropdown/dropdown-trigger.svelte +41 -41
  112. package/dist/components/dropdown/dropdown-value.svelte +60 -60
  113. package/dist/components/element/types.d.ts +1 -1
  114. package/dist/components/form/bond.svelte.d.ts +1 -1
  115. package/dist/components/form/field/field-control.svelte +48 -48
  116. package/dist/components/form/field/field-label.svelte +24 -24
  117. package/dist/components/form/field/field-root.svelte +59 -59
  118. package/dist/components/icon/icon.svelte +44 -44
  119. package/dist/components/image/image.stories.svelte.d.ts +1 -1
  120. package/dist/components/index.d.ts +4 -0
  121. package/dist/components/index.js +4 -0
  122. package/dist/components/input/input-control.svelte +103 -103
  123. package/dist/components/label/label.svelte +25 -25
  124. package/dist/components/lazy/index.d.ts +1 -0
  125. package/dist/components/lazy/index.js +1 -0
  126. package/dist/components/lazy/lazy.stories.svelte +35 -0
  127. package/dist/components/lazy/lazy.stories.svelte.d.ts +19 -0
  128. package/dist/components/lazy/lazy.svelte +28 -0
  129. package/dist/components/lazy/lazy.svelte.d.ts +5 -0
  130. package/dist/components/lazy/types.d.ts +10 -0
  131. package/dist/components/lazy/types.js +1 -0
  132. package/dist/components/menu/menu-list.svelte +40 -39
  133. package/dist/components/menu/menu-list.svelte.d.ts +1 -0
  134. package/dist/components/popover/popover-arrow.svelte +111 -111
  135. package/dist/components/popover/popover-content.svelte +178 -139
  136. package/dist/components/popover/popover-root.svelte +16 -17
  137. package/dist/components/popover/popover.stories.svelte +0 -15
  138. package/dist/components/portal/portal-root.svelte +83 -83
  139. package/dist/components/portal/teleport.svelte +50 -50
  140. package/dist/components/qr-code/index.d.ts +2 -0
  141. package/dist/components/qr-code/index.js +2 -0
  142. package/dist/components/qr-code/qr-code.stories.svelte +27 -0
  143. package/dist/components/qr-code/qr-code.stories.svelte.d.ts +26 -0
  144. package/dist/components/qr-code/qr-code.svelte +75 -0
  145. package/dist/components/qr-code/qr-code.svelte.d.ts +4 -0
  146. package/dist/components/qr-code/types.d.ts +14 -0
  147. package/dist/components/qr-code/types.js +1 -0
  148. package/dist/components/radio/radio.svelte +109 -109
  149. package/dist/components/radio/types.svelte.d.ts +1 -1
  150. package/dist/components/scrollable/scrollable-container.svelte +82 -82
  151. package/dist/components/scrollable/scrollable-content.svelte +41 -41
  152. package/dist/components/scrollable/scrollable-root.svelte +100 -100
  153. package/dist/components/scrollable/scrollable-thumb.svelte +75 -75
  154. package/dist/components/scrollable/scrollable-track.svelte +59 -59
  155. package/dist/components/scrollable/scrollable.stories.svelte.d.ts +1 -1
  156. package/dist/components/sidebar/bond.svelte.d.ts +0 -5
  157. package/dist/components/sidebar/bond.svelte.js +1 -12
  158. package/dist/components/sidebar/sidebar-content.svelte +39 -39
  159. package/dist/components/sidebar/sidebar-content.svelte.d.ts +2 -2
  160. package/dist/components/sidebar/sidebar-root.svelte +41 -68
  161. package/dist/components/sidebar/sidebar-root.svelte.d.ts +2 -2
  162. package/dist/components/sidebar/sidebar.stories.svelte +54 -52
  163. package/dist/components/sidebar/types.d.ts +6 -6
  164. package/dist/components/tabs/tab/tab-body.svelte +52 -52
  165. package/dist/components/tabs/tab/tab-description.svelte +41 -41
  166. package/dist/components/tabs/tab/tab-header.svelte +71 -71
  167. package/dist/components/tabs/tab/tab-root.svelte +86 -86
  168. package/dist/components/toast/toast-description.svelte +38 -38
  169. package/dist/components/toast/toast-root.svelte +61 -61
  170. package/dist/components/toast/toast-title.svelte +35 -35
  171. package/dist/components/tree/tree-body.svelte +39 -39
  172. package/dist/components/tree/tree-header.svelte +54 -54
  173. package/dist/components/tree/tree-indicator.svelte +40 -40
  174. package/dist/components/tree/tree-root.svelte +65 -65
  175. package/dist/components/virtual/virtual-root.svelte +239 -239
  176. package/dist/context/preset.svelte.d.ts +1 -1
  177. package/dist/icons/icon-arrow-down.svelte.d.ts +1 -1
  178. package/dist/icons/icon-checkmark.svelte.d.ts +1 -1
  179. package/dist/icons/icon-close.svelte.d.ts +1 -1
  180. package/dist/icons/icon-more-vert.svelte.d.ts +1 -1
  181. package/dist/runes/container.svelte.d.ts +2 -2
  182. package/dist/shared/bond.svelte.d.ts +1 -1
  183. package/dist/utils/state.d.ts +1 -1
  184. package/dist/utils/state.js +2 -1
  185. package/llm/variants.md +650 -103
  186. package/package.json +465 -437
package/llm/variants.md CHANGED
@@ -195,51 +195,67 @@ setPreset({
195
195
  - Local variant classes (ghost, loading)
196
196
  - Merged intelligently - local overrides preset
197
197
 
198
- ```typescript
199
- import { defineVariants } from '@svelte-atoms/core/utils';
198
+ ## Basic Usage
200
199
 
201
- const buttonVariants = defineVariants({
202
- class: 'rounded-md font-medium transition-colors',
203
- variants: {
204
- variant: {
205
- primary: 'bg-blue-500 text-white hover:bg-blue-600',
206
- secondary: 'bg-gray-500 text-white hover:bg-gray-600',
207
- danger: 'bg-red-500 text-white hover:bg-red-600'
200
+ **Key Pattern:** `defineVariants()` returns a **function** that you pass to `HtmlAtom`. The component calls this function internally with bond and props.
201
+
202
+ ```svelte
203
+ <script lang="ts">
204
+ import { HtmlAtom } from '@svelte-atoms/core';
205
+ import { defineVariants } from '@svelte-atoms/core/utils';
206
+
207
+ // defineVariants returns a FUNCTION
208
+ const variants = defineVariants({
209
+ class: 'rounded-md font-medium transition-colors',
210
+ variants: {
211
+ variant: {
212
+ primary: {
213
+ class: 'bg-blue-500 text-white hover:bg-blue-600'
214
+ },
215
+ secondary: {
216
+ class: 'bg-gray-500 text-white hover:bg-gray-600'
217
+ },
218
+ danger: {
219
+ class: 'bg-red-500 text-white hover:bg-red-600'
220
+ }
221
+ },
222
+ size: {
223
+ sm: 'px-2 py-1 text-sm',
224
+ md: 'px-4 py-2 text-base',
225
+ lg: 'px-6 py-3 text-lg'
226
+ }
208
227
  },
209
- size: {
210
- sm: 'px-2 py-1 text-sm',
211
- md: 'px-4 py-2 text-base',
212
- lg: 'px-6 py-3 text-lg'
213
- }
214
- },
215
- compounds: [
216
- {
228
+ compounds: [
229
+ {
230
+ variant: 'primary',
231
+ size: 'lg',
232
+ class: 'shadow-lg' // Applied when both conditions match
233
+ }
234
+ ],
235
+ defaults: {
217
236
  variant: 'primary',
218
- size: 'lg',
219
- class: 'shadow-lg' // Applied when both conditions match
237
+ size: 'md'
220
238
  }
221
- ],
222
- defaults: {
223
- variant: 'primary',
224
- size: 'md'
225
- }
226
- });
227
- ```
228
-
229
- ```svelte
230
- <script>
231
- import { buttonVariants } from './variants';
239
+ });
232
240
 
233
241
  let { variant, size, ...props } = $props();
234
-
235
- const variantProps = buttonVariants({ variant, size });
236
242
  </script>
237
243
 
238
- <HtmlAtom {...variantProps} {...props}>
244
+ <!-- Pass the variant FUNCTION to HtmlAtom -->
245
+ <!-- HtmlAtom will call it internally: variants(bond, { variant, size }) -->
246
+ <HtmlAtom {variants} {variant} {size} {...props}>
239
247
  {@render children?.()}
240
248
  </HtmlAtom>
241
249
  ```
242
250
 
251
+ **How it works:**
252
+
253
+ 1. `defineVariants(config)` → returns a function
254
+ 2. You pass this function to `HtmlAtom` via `{variants}`
255
+ 3. `HtmlAtom` internally calls `variants(bond, restProps)`
256
+ 4. The function returns `{ class: [...], ...attributes }`
257
+ 5. `HtmlAtom` applies these to the rendered element
258
+
243
259
  ## Key Features
244
260
 
245
261
  ### 1. Access to Component State (Bond)
@@ -264,9 +280,12 @@ const accordionVariants = defineVariants({
264
280
  }
265
281
  });
266
282
 
267
- // Usage:
268
- const bond = AccordionBond.get();
269
- const variantProps = accordionVariants(bond, { state: 'open' });
283
+ // Usage in component:
284
+ let { state = 'open', ...props } = $props();
285
+
286
+ <HtmlAtom {variants} {state} {...props}>
287
+ {@render children?.()}
288
+ </HtmlAtom>
270
289
  ```
271
290
 
272
291
  ### 2. Return Both Classes and Attributes
@@ -291,7 +310,7 @@ const buttonVariants = defineVariants({
291
310
  }
292
311
  });
293
312
 
294
- // Returns: { class: '...', 'aria-label': '...', 'data-variant': '...', ... }
313
+ // When called by HtmlAtom, returns: { class: [...], 'aria-label': '...', 'data-variant': '...', ... }
295
314
  ```
296
315
 
297
316
  ### 3. Compound Variants
@@ -353,8 +372,10 @@ const buttonVariants = defineVariants({
353
372
  }
354
373
  });
355
374
 
356
- // Call without props - uses defaults
357
- buttonVariants(null); // Returns variant='primary', size='md'
375
+ // Pass to HtmlAtom - uses defaults when props not provided
376
+ <HtmlAtom {variants} {...props}>
377
+ {@render children?.()}
378
+ </HtmlAtom>
358
379
  ```
359
380
 
360
381
  ## Complete Examples
@@ -419,9 +440,41 @@ setPreset({
419
440
  </HtmlAtom>
420
441
  ```
421
442
 
422
- ### Example 2: Local Variants Only
443
+ ### Example 2: Local Variants with HtmlAtom
444
+
445
+ ```svelte
446
+ <script lang="ts">
447
+ import { HtmlAtom } from '@svelte-atoms/core';
448
+ import { defineVariants } from '@svelte-atoms/core/utils';
449
+
450
+ const buttonVariants = defineVariants({
451
+ class: 'inline-flex items-center justify-center rounded-md font-medium',
452
+ variants: {
453
+ variant: {
454
+ primary: 'bg-blue-500 text-white hover:bg-blue-600',
455
+ secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
456
+ ghost: 'hover:bg-gray-100'
457
+ },
458
+ size: {
459
+ sm: 'h-8 px-3 text-sm',
460
+ md: 'h-10 px-4',
461
+ lg: 'h-12 px-6 text-lg'
462
+ }
463
+ },
464
+ defaults: {
465
+ variant: 'primary',
466
+ size: 'md'
467
+ }
468
+ });
469
+
470
+ let { variant, size, ...props } = $props();
471
+ </script>
472
+
473
+ <HtmlAtom {variants} as="button" {variant} {size} {...props}>
474
+ {@render children?.()}
475
+ </HtmlAtom>
476
+ ```
423
477
 
424
- ````svelte
425
478
  ### Example 3: Extending Preset with Local Variants
426
479
 
427
480
  Combine global preset variants with component-specific variants:
@@ -466,53 +519,52 @@ Combine global preset variants with component-specific variants:
466
519
  >
467
520
  {@render children?.()}
468
521
  </HtmlAtom>
469
- ````
522
+ ```
470
523
 
471
- ### Example 4: Reactive Variants with Bond State
524
+ ### Example 4: Alert Component with Compound Variants
472
525
 
473
- <script>
474
- import { HtmlAtom } from '@svelte-atoms/core';
475
- import { defineVariants } from '@svelte-atoms/core/utils';
476
-
477
- const alertVariants = defineVariants({
478
- class: 'rounded-lg p-4 border',
479
- variants: {
480
- variant: {
481
- info: 'bg-blue-50 border-blue-200 text-blue-900',
482
- success: 'bg-green-50 border-green-200 text-green-900',
483
- warning: 'bg-yellow-50 border-yellow-200 text-yellow-900',
484
- error: 'bg-red-50 border-red-200 text-red-900'
485
- },
486
- size: {
487
- sm: 'text-sm p-2',
488
- md: 'text-base p-4',
489
- lg: 'text-lg p-6'
490
- }
491
- },
492
- compounds: [
493
- {
494
- variant: 'error',
495
- size: 'lg',
496
- class: 'font-bold',
497
- role: 'alert',
498
- 'aria-live': 'assertive'
499
- }
500
- ],
501
- defaults: {
502
- variant: 'info',
503
- size: 'md'
504
- }
505
- });
506
-
507
- let { variant, size, ...props } = $props();
508
-
509
- const bond = null; // or get from context if needed
510
- const variantProps = alertVariants(bond, { variant, size });
526
+ ```svelte
527
+ <script lang="ts">
528
+ import { HtmlAtom } from '@svelte-atoms/core';
529
+ import { defineVariants } from '@svelte-atoms/core/utils';
530
+
531
+ const alertVariants = defineVariants({
532
+ class: 'rounded-lg p-4 border',
533
+ variants: {
534
+ variant: {
535
+ info: 'bg-blue-50 border-blue-200 text-blue-900',
536
+ success: 'bg-green-50 border-green-200 text-green-900',
537
+ warning: 'bg-yellow-50 border-yellow-200 text-yellow-900',
538
+ error: 'bg-red-50 border-red-200 text-red-900'
539
+ },
540
+ size: {
541
+ sm: 'text-sm p-2',
542
+ md: 'text-base p-4',
543
+ lg: 'text-lg p-6'
544
+ }
545
+ },
546
+ compounds: [
547
+ {
548
+ variant: 'error',
549
+ size: 'lg',
550
+ class: 'font-bold',
551
+ role: 'alert',
552
+ 'aria-live': 'assertive'
553
+ }
554
+ ],
555
+ defaults: {
556
+ variant: 'info',
557
+ size: 'md'
558
+ }
559
+ });
560
+
561
+ let { variant, size, ...props } = $props();
511
562
  </script>
512
563
 
513
- <HtmlAtom {...variantProps} {...props}>
514
- {@render children?.()}
564
+ <HtmlAtom {variants} {variant} {size} {...props}>
565
+ {@render children?.()}
515
566
  </HtmlAtom>
567
+ ```
516
568
 
517
569
  ````
518
570
 
@@ -547,14 +599,11 @@ Combine global preset variants with component-specific variants:
547
599
  }
548
600
  });
549
601
 
550
- const bond = AccordionBond.get();
551
-
552
- // Automatically reactive - updates when bond state changes
553
- const variantProps = $derived(accordionVariants(bond, { state: 'open' }));
602
+ let { state = 'open', ...props } = $props();
554
603
  </script>
555
604
 
556
- <HtmlAtom {...variantProps}>
557
- {@render children?.({ accordion: bond })}
605
+ <HtmlAtom {variants} {state} {...props}>
606
+ {@render children?.()}
558
607
  </HtmlAtom>
559
608
  ````
560
609
 
@@ -612,12 +661,10 @@ Combine global preset variants with component-specific variants:
612
661
  });
613
662
 
614
663
  let { variant, size, ...props } = $props();
615
-
616
- const bond = null; // or get from context if needed
617
- const variantProps = buttonVariants(bond, { variant, size });
618
664
  </script>
619
665
 
620
- <HtmlAtom as="button" {...variantProps} {...props}>Click me</HtmlAtom>
666
+ <!-- Pass the variant function to HtmlAtom -->
667
+ <HtmlAtom {variants} as="button" {variant} {size} {...props}>Click me</HtmlAtom>
621
668
  ```
622
669
 
623
670
  ### Benefits After Migration
@@ -658,17 +705,21 @@ export const cardVariants = defineVariants({
658
705
  });
659
706
  ```
660
707
 
661
- ### 2. Use $derived for Reactive Variants
708
+ ### 2. Pass Variants Function to Components
662
709
 
663
- When using bond state, wrap the variant call in `$derived`:
710
+ Always pass the variant function (not the result) to `HtmlAtom`:
664
711
 
665
712
  ```svelte
666
713
  <script>
667
- const bond = AccordionBond.get();
668
-
669
- // Reactive - updates when bond state changes
670
- const variantProps = $derived(accordionVariants(bond, { state: 'open' }));
714
+ const variants = defineVariants({ ... });
715
+
716
+ let { variant, size, ...props } = $props();
671
717
  </script>
718
+
719
+ <!-- Correct: Pass the function -->
720
+ <HtmlAtom {variants} {variant} {size} {...props}>
721
+ {@render children?.()}
722
+ </HtmlAtom>
672
723
  ```
673
724
 
674
725
  ### 3. Extend with Additional Classes
@@ -677,11 +728,12 @@ Merge variant classes with custom classes:
677
728
 
678
729
  ```svelte
679
730
  <script>
680
- const bond = null; // or get from context if needed
681
- const variantProps = buttonVariants(bond, { variant, size });
731
+ let { variant, size, class: klass = '', ...props } = $props();
682
732
  </script>
683
733
 
684
- <HtmlAtom class={[variantProps.class, 'custom-class']} {...variantProps} />
734
+ <HtmlAtom {variants} {variant} {size} class={['custom-class', klass]} {...props}>
735
+ {@render children?.()}
736
+ </HtmlAtom>
685
737
  ```
686
738
 
687
739
  ### 4. Type Props from Variants
@@ -698,6 +750,499 @@ type ButtonProps = VariantPropsType<typeof buttonVariants> & {
698
750
  };
699
751
  ```
700
752
 
753
+ ## Creating Variants: Local vs Global
754
+
755
+ ### Local Variants (Component-Specific)
756
+
757
+ Create variants directly in your component file when they're only used in one place:
758
+
759
+ ```svelte
760
+ <!-- my-button.svelte -->
761
+ <script lang="ts">
762
+ import { HtmlAtom } from '@svelte-atoms/core';
763
+ import { defineVariants, type VariantPropsType } from '@svelte-atoms/core/utils';
764
+
765
+ // Define variants locally
766
+ const buttonVariants = defineVariants({
767
+ class: 'inline-flex items-center justify-center rounded-md font-medium',
768
+ variants: {
769
+ variant: {
770
+ primary: 'bg-blue-500 text-white hover:bg-blue-600',
771
+ secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
772
+ ghost: 'hover:bg-gray-100'
773
+ },
774
+ size: {
775
+ sm: 'h-8 px-3 text-sm',
776
+ md: 'h-10 px-4',
777
+ lg: 'h-12 px-6 text-lg'
778
+ }
779
+ },
780
+ compounds: [
781
+ {
782
+ variant: 'primary',
783
+ size: 'lg',
784
+ class: 'shadow-md font-semibold'
785
+ },
786
+ {
787
+ variant: 'secondary',
788
+ size: 'sm',
789
+ class: 'text-xs'
790
+ }
791
+ ],
792
+ defaults: {
793
+ variant: 'primary',
794
+ size: 'md'
795
+ }
796
+ });
797
+
798
+ // Extract variant prop types
799
+ type ButtonVariantProps = VariantPropsType<typeof buttonVariants>;
800
+
801
+ // Define component props extending variant props
802
+ type ButtonProps = ButtonVariantProps & {
803
+ disabled?: boolean;
804
+ onclick?: (e: MouseEvent) => void;
805
+ class?: string;
806
+ };
807
+
808
+ let { variant, size, disabled = false, class: klass = '', ...props }: ButtonProps = $props();
809
+
810
+ const variants = buttonVariants; // The variant function
811
+ </script>
812
+
813
+ <HtmlAtom {variants} as="button" {variant} {size} {disabled} class={klass} {...props}>
814
+ {@render children?.()}
815
+ </HtmlAtom>
816
+ ```
817
+
818
+ **Use local variants when:**
819
+
820
+ - The component is unique and won't be reused elsewhere
821
+ - You need quick prototyping
822
+ - Variants are tightly coupled to the component logic
823
+
824
+ ### Global Variants (Preset-Based)
825
+
826
+ Define variants globally in your theme/preset configuration for reusable components:
827
+
828
+ ```typescript
829
+ // +layout.svelte or theme.svelte
830
+ import { setPreset } from '@svelte-atoms/core/context';
831
+
832
+ setPreset({
833
+ // Global button variants
834
+ button: () => ({
835
+ class:
836
+ 'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2',
837
+ variants: {
838
+ variant: {
839
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
840
+ destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
841
+ outline: 'border border-input bg-background hover:bg-accent',
842
+ secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
843
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
844
+ link: 'text-primary underline-offset-4 hover:underline'
845
+ },
846
+ size: {
847
+ default: 'h-10 px-4 py-2',
848
+ sm: 'h-9 px-3',
849
+ lg: 'h-11 px-8',
850
+ icon: 'h-10 w-10'
851
+ }
852
+ },
853
+ compounds: [
854
+ {
855
+ variant: 'default',
856
+ size: 'lg',
857
+ class: 'text-base font-semibold'
858
+ }
859
+ ],
860
+ defaults: {
861
+ variant: 'default',
862
+ size: 'default'
863
+ }
864
+ }),
865
+
866
+ // Global card variants
867
+ card: () => ({
868
+ class: 'rounded-lg border bg-card text-card-foreground shadow-sm',
869
+ variants: {
870
+ variant: {
871
+ default: 'border-border',
872
+ elevated: 'shadow-lg',
873
+ outlined: 'border-2'
874
+ }
875
+ },
876
+ defaults: {
877
+ variant: 'default'
878
+ }
879
+ })
880
+ });
881
+ ```
882
+
883
+ ```svelte
884
+ <!-- button.svelte - Consume global variants -->
885
+ <script lang="ts">
886
+ import { HtmlAtom } from '@svelte-atoms/core';
887
+
888
+ // Type-safe props based on preset
889
+ type ButtonProps = {
890
+ variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
891
+ size?: 'default' | 'sm' | 'lg' | 'icon';
892
+ disabled?: boolean;
893
+ class?: string;
894
+ };
895
+
896
+ let {
897
+ variant,
898
+ size,
899
+ disabled = false,
900
+ class: klass = '',
901
+ ...props
902
+ }: ButtonProps = $props();
903
+ </script>
904
+
905
+ <HtmlAtom
906
+ preset="button" <!-- Uses global preset variants -->
907
+ as="button"
908
+ {variant}
909
+ {size}
910
+ {disabled}
911
+ class={klass}
912
+ {...props}
913
+ >
914
+ {@render children?.()}
915
+ </HtmlAtom>
916
+ ```
917
+
918
+ **Use global variants when:**
919
+
920
+ - Building a design system with consistent styling
921
+ - Components are used across multiple pages/features
922
+ - You want centralized theme control
923
+ - You need to support theme switching
924
+
925
+ ### Extending Global Variants Locally
926
+
927
+ Combine the best of both worlds - use global presets as a base and extend with local variants:
928
+
929
+ ```svelte
930
+ <!-- special-button.svelte -->
931
+ <script lang="ts">
932
+ import { HtmlAtom } from '@svelte-atoms/core';
933
+ import { defineVariants, type VariantPropsType } from '@svelte-atoms/core/utils';
934
+
935
+ // Local variants that extend the global preset
936
+ const extendedVariants = defineVariants({
937
+ variants: {
938
+ variant: {
939
+ // Add new variants not in preset
940
+ gradient: 'bg-gradient-to-r from-purple-500 to-pink-500 text-white hover:from-purple-600 hover:to-pink-600',
941
+ neon: 'bg-black text-green-400 border-2 border-green-400 hover:bg-green-400 hover:text-black',
942
+ glass: 'bg-white/10 backdrop-blur-lg border border-white/20 hover:bg-white/20'
943
+ },
944
+ // Add new variant dimension
945
+ animated: {
946
+ true: 'animate-pulse',
947
+ false: ''
948
+ },
949
+ shadow: {
950
+ none: '',
951
+ sm: 'shadow-sm',
952
+ md: 'shadow-md',
953
+ lg: 'shadow-lg'
954
+ }
955
+ },
956
+ defaults: {
957
+ animated: false,
958
+ shadow: 'none'
959
+ }
960
+ });
961
+
962
+ // Extract extended variant types
963
+ type ExtendedVariantProps = VariantPropsType<typeof extendedVariants>;
964
+
965
+ // Combine preset variants with extended variants
966
+ type SpecialButtonProps = {
967
+ // Preset variant types
968
+ variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' | 'gradient' | 'neon' | 'glass';
969
+ size?: 'default' | 'sm' | 'lg' | 'icon';
970
+ // Extended variant types
971
+ animated?: boolean;
972
+ shadow?: 'none' | 'sm' | 'md' | 'lg';
973
+ disabled?: boolean;
974
+ class?: string;
975
+ };
976
+
977
+ let {
978
+ variant,
979
+ size,
980
+ animated,
981
+ shadow,
982
+ disabled = false,
983
+ class: klass = '',
984
+ ...props
985
+ }: SpecialButtonProps = $props();
986
+ </script>
987
+
988
+ <HtmlAtom
989
+ preset="button" <!-- Gets base global variants -->
990
+ variants={extendedVariants} <!-- Extends with local variants -->
991
+ as="button"
992
+ {variant}
993
+ {size}
994
+ {animated}
995
+ {shadow}
996
+ {disabled}
997
+ class={klass}
998
+ {...props}
999
+ >
1000
+ {@render children?.()}
1001
+ </HtmlAtom>
1002
+ ```
1003
+
1004
+ ## Type-Safe Component Props with Variants
1005
+
1006
+ ### Method 1: Manual Type Definition (Preset-based)
1007
+
1008
+ When using presets, manually define the variant types based on your preset configuration:
1009
+
1010
+ ```svelte
1011
+ <script lang="ts">
1012
+ import { HtmlAtom } from '@svelte-atoms/core';
1013
+
1014
+ // Manually typed based on preset definition
1015
+ type ButtonProps = {
1016
+ variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
1017
+ size?: 'default' | 'sm' | 'lg' | 'icon';
1018
+ disabled?: boolean;
1019
+ class?: string;
1020
+ onclick?: (e: MouseEvent) => void;
1021
+ };
1022
+
1023
+ let { variant, size, disabled = false, class: klass = '', ...props }: ButtonProps = $props();
1024
+ </script>
1025
+
1026
+ <HtmlAtom preset="button" as="button" {variant} {size} {disabled} class={klass} {...props}>
1027
+ {@render children?.()}
1028
+ </HtmlAtom>
1029
+ ```
1030
+
1031
+ ### Method 2: Extract Types from defineVariants
1032
+
1033
+ For local variants, use `VariantPropsType` to automatically extract types:
1034
+
1035
+ ```svelte
1036
+ <script lang="ts">
1037
+ import { HtmlAtom } from '@svelte-atoms/core';
1038
+ import { defineVariants, type VariantPropsType } from '@svelte-atoms/core/utils';
1039
+
1040
+ const buttonVariants = defineVariants({
1041
+ class: 'rounded-md',
1042
+ variants: {
1043
+ variant: {
1044
+ primary: 'bg-blue-500',
1045
+ secondary: 'bg-gray-500',
1046
+ danger: 'bg-red-500'
1047
+ },
1048
+ size: {
1049
+ sm: 'text-sm',
1050
+ md: 'text-base',
1051
+ lg: 'text-lg'
1052
+ },
1053
+ fullWidth: {
1054
+ true: 'w-full',
1055
+ false: 'w-auto'
1056
+ }
1057
+ },
1058
+ defaults: {
1059
+ variant: 'primary',
1060
+ size: 'md',
1061
+ fullWidth: false
1062
+ }
1063
+ });
1064
+
1065
+ // Automatically extract variant prop types
1066
+ type ButtonVariantProps = VariantPropsType<typeof buttonVariants>;
1067
+ // Result: { variant?: 'primary' | 'secondary' | 'danger'; size?: 'sm' | 'md' | 'lg'; fullWidth?: boolean }
1068
+
1069
+ // Extend with additional props
1070
+ type ButtonProps = ButtonVariantProps & {
1071
+ disabled?: boolean;
1072
+ onclick?: (e: MouseEvent) => void;
1073
+ class?: string;
1074
+ };
1075
+
1076
+ let {
1077
+ variant,
1078
+ size,
1079
+ fullWidth,
1080
+ disabled = false,
1081
+ class: klass = '',
1082
+ ...props
1083
+ }: ButtonProps = $props();
1084
+ </script>
1085
+
1086
+ <HtmlAtom {variants} as="button" {variant} {size} {fullWidth} {disabled} class={klass} {...props}>
1087
+ {@render children?.()}
1088
+ </HtmlAtom>
1089
+ ```
1090
+
1091
+ ### Method 3: Shared Variant Types
1092
+
1093
+ Create reusable variant type definitions:
1094
+
1095
+ ```typescript
1096
+ // types/button.ts
1097
+ import { defineVariants, type VariantPropsType } from '@svelte-atoms/core/utils';
1098
+
1099
+ export const buttonVariants = defineVariants({
1100
+ class: 'inline-flex items-center justify-center rounded-md font-medium',
1101
+ variants: {
1102
+ variant: {
1103
+ primary: 'bg-blue-500 text-white',
1104
+ secondary: 'bg-gray-200 text-gray-900',
1105
+ ghost: 'hover:bg-gray-100'
1106
+ },
1107
+ size: {
1108
+ sm: 'h-8 px-3 text-sm',
1109
+ md: 'h-10 px-4',
1110
+ lg: 'h-12 px-6 text-lg'
1111
+ }
1112
+ },
1113
+ defaults: {
1114
+ variant: 'primary',
1115
+ size: 'md'
1116
+ }
1117
+ });
1118
+
1119
+ // Export the variant types
1120
+ export type ButtonVariantProps = VariantPropsType<typeof buttonVariants>;
1121
+
1122
+ // Export full component props
1123
+ export type ButtonProps = ButtonVariantProps & {
1124
+ disabled?: boolean;
1125
+ onclick?: (e: MouseEvent) => void;
1126
+ class?: string;
1127
+ };
1128
+ ```
1129
+
1130
+ ```svelte
1131
+ <!-- button.svelte -->
1132
+ <script lang="ts">
1133
+ import { HtmlAtom } from '@svelte-atoms/core';
1134
+ import { buttonVariants, type ButtonProps } from './types/button';
1135
+
1136
+ const variants = buttonVariants; // The function from the shared file
1137
+
1138
+ let { variant, size, disabled = false, class: klass = '', ...props }: ButtonProps = $props();
1139
+ </script>
1140
+
1141
+ <HtmlAtom {variants} as="button" {variant} {size} {disabled} class={klass} {...props}>
1142
+ {@render children?.()}
1143
+ </HtmlAtom>
1144
+ ```
1145
+
1146
+ ### Method 4: Component with Bond State Types
1147
+
1148
+ For components using the Bond pattern:
1149
+
1150
+ ```typescript
1151
+ // accordion-item.svelte
1152
+ <script lang="ts">
1153
+ import { HtmlAtom } from '@svelte-atoms/core';
1154
+ import { defineVariants, type VariantPropsType } from '@svelte-atoms/core/utils';
1155
+ import { AccordionBond } from './bond.svelte';
1156
+
1157
+ const accordionVariants = defineVariants({
1158
+ class: 'border rounded-md',
1159
+ variants: {
1160
+ state: {
1161
+ open: (bond) => ({
1162
+ class: bond?.state?.isOpen ? 'bg-blue-50' : 'bg-white',
1163
+ 'aria-expanded': bond?.state?.isOpen
1164
+ })
1165
+ },
1166
+ bordered: {
1167
+ true: 'border-2',
1168
+ false: 'border'
1169
+ }
1170
+ },
1171
+ defaults: {
1172
+ bordered: false
1173
+ }
1174
+ });
1175
+
1176
+ // Extract variant types
1177
+ type AccordionVariantProps = VariantPropsType<typeof accordionVariants>;
1178
+
1179
+ // Extend with component-specific props
1180
+ type AccordionItemProps = Omit<AccordionVariantProps, 'state'> & {
1181
+ value: string;
1182
+ disabled?: boolean;
1183
+ class?: string;
1184
+ };
1185
+
1186
+ let {
1187
+ value,
1188
+ bordered,
1189
+ disabled = false,
1190
+ class: klass = '',
1191
+ ...props
1192
+ }: AccordionItemProps = $props();
1193
+
1194
+ const variants = accordionVariants; // The variant function
1195
+ </script>
1196
+
1197
+ <HtmlAtom {variants} {bordered} class={klass} {...props}>
1198
+ {@render children?.()}
1199
+ </HtmlAtom>
1200
+ ```
1201
+
1202
+ ### Best Practices for Typed Variants
1203
+
1204
+ 1. **Always extract types from defineVariants**
1205
+
1206
+ ```typescript
1207
+ const variants = defineVariants({...});
1208
+ type VariantProps = VariantPropsType<typeof variants>;
1209
+ ```
1210
+
1211
+ 2. **Extend variant types with component props**
1212
+
1213
+ ```typescript
1214
+ type ComponentProps = VariantProps & {
1215
+ disabled?: boolean;
1216
+ onclick?: () => void;
1217
+ };
1218
+ ```
1219
+
1220
+ 3. **Use Omit for bond-driven variants**
1221
+
1222
+ ```typescript
1223
+ // Remove 'state' from props since it's driven by bond
1224
+ type Props = Omit<VariantProps, 'state'> & { ... };
1225
+ ```
1226
+
1227
+ 4. **Share types across related components**
1228
+
1229
+ ```typescript
1230
+ // types/card.ts
1231
+ export type CardVariantProps = VariantPropsType<typeof cardVariants>;
1232
+ export type CardHeaderProps = { class?: string };
1233
+ export type CardBodyProps = { class?: string };
1234
+ ```
1235
+
1236
+ 5. **Document variant options in JSDoc**
1237
+ ```typescript
1238
+ /**
1239
+ * Button component with multiple variants
1240
+ * @param variant - Visual style: 'primary' | 'secondary' | 'ghost'
1241
+ * @param size - Size variant: 'sm' | 'md' | 'lg'
1242
+ */
1243
+ type ButtonProps = VariantPropsType<typeof buttonVariants> & {...};
1244
+ ```
1245
+
701
1246
  ## Summary
702
1247
 
703
1248
  `defineVariants()` provides:
@@ -707,6 +1252,8 @@ type ButtonProps = VariantPropsType<typeof buttonVariants> & {
707
1252
  ✅ **Reactive** - Access bond state for dynamic styling
708
1253
  ✅ **Powerful** - Base classes, compound variants, defaults
709
1254
  ✅ **Flexible** - Return both classes and attributes
710
- ✅ **Clean** - No manual object merging or conditionals
1255
+ ✅ **Clean** - No manual object merging or conditionals
1256
+ ✅ **Extensible** - Combine global presets with local variants
1257
+ ✅ **Type extraction** - Use `VariantPropsType` for automatic type inference
711
1258
 
712
1259
  Inspired by Class Variance Authority but integrated with @svelte-atoms/core's bond system.