@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.
- package/README.md +852 -645
- package/dist/components/accordion/accordion-root.svelte +61 -61
- package/dist/components/accordion/item/accordion-item-body.svelte +42 -42
- package/dist/components/accordion/item/accordion-item-header.svelte +50 -50
- package/dist/components/accordion/item/accordion-item-indicator.svelte +50 -50
- package/dist/components/accordion/item/accordion-item-root.svelte +65 -65
- package/dist/components/alert/alert-actions.svelte +43 -42
- package/dist/components/alert/alert-close-button.svelte +70 -72
- package/dist/components/alert/alert-content.svelte +43 -42
- package/dist/components/alert/alert-description.svelte +42 -41
- package/dist/components/alert/alert-icon.svelte +47 -46
- package/dist/components/alert/alert-root.svelte +103 -102
- package/dist/components/alert/alert-title.svelte +42 -41
- package/dist/components/alert/alert.stories.svelte +384 -23
- package/dist/components/alert/alert.stories.svelte.d.ts +2 -5
- package/dist/components/atom/html-atom.svelte +207 -201
- package/dist/components/atom/html-atom.svelte.d.ts +1 -1
- package/dist/components/atom/snippet-renderer.svelte +5 -0
- package/dist/components/atom/snippet-renderer.svelte.d.ts +5 -0
- package/dist/components/avatar/avatar.stories.svelte.d.ts +1 -1
- package/dist/components/badge/badge.stories.svelte.d.ts +1 -1
- package/dist/components/breadcrumb/breadcrumb.stories.svelte.d.ts +1 -1
- package/dist/components/button/button.stories.svelte +17 -14
- package/dist/components/calendar/atoms.d.ts +5 -0
- package/dist/components/calendar/atoms.js +5 -0
- package/dist/components/calendar/bond.svelte.d.ts +72 -0
- package/dist/components/calendar/bond.svelte.js +132 -0
- package/dist/components/calendar/calendar-body.svelte +107 -0
- package/dist/components/calendar/calendar-body.svelte.d.ts +8 -0
- package/dist/components/calendar/calendar-day.svelte +96 -0
- package/dist/components/calendar/calendar-day.svelte.d.ts +4 -0
- package/dist/components/calendar/calendar-header.svelte +29 -0
- package/dist/components/calendar/calendar-header.svelte.d.ts +6 -0
- package/dist/components/calendar/calendar-root.svelte +206 -0
- package/dist/components/calendar/calendar-root.svelte.d.ts +8 -0
- package/dist/components/calendar/calendar-week-day.svelte +34 -0
- package/dist/components/calendar/calendar-week-day.svelte.d.ts +9 -0
- package/dist/components/calendar/calendar.css +26 -0
- package/dist/components/calendar/calendar.stories.svelte +31 -0
- package/dist/components/calendar/calendar.stories.svelte.d.ts +26 -0
- package/dist/components/calendar/index.d.ts +4 -0
- package/dist/components/calendar/index.js +4 -0
- package/dist/components/calendar/runes.svelte.d.ts +3 -0
- package/dist/components/calendar/runes.svelte.js +25 -0
- package/dist/components/calendar/types.d.ts +62 -0
- package/dist/components/calendar/types.js +1 -0
- package/dist/components/card/card-body.svelte +39 -39
- package/dist/components/card/card-description.svelte +41 -41
- package/dist/components/card/card-footer.svelte +41 -41
- package/dist/components/card/card-header.svelte +41 -41
- package/dist/components/card/card-media.svelte +41 -41
- package/dist/components/card/card-root.svelte +91 -91
- package/dist/components/card/card-subtitle.svelte +41 -41
- package/dist/components/card/card-title.svelte +45 -45
- package/dist/components/collapsible/collapsible-body.svelte +39 -39
- package/dist/components/collapsible/collapsible-header.svelte +39 -39
- package/dist/components/collapsible/collapsible-indicator.svelte +50 -50
- package/dist/components/collapsible/collapsible-root.svelte +66 -66
- package/dist/components/combobox/combobox-root.svelte +65 -65
- package/dist/components/container/container.stories.svelte.d.ts +1 -1
- package/dist/components/contextmenu/contextmenu-trigger.svelte.d.ts +1 -1
- package/dist/components/datagrid/bond.svelte.d.ts +2 -2
- package/dist/components/datagrid/datagrid-body.svelte +37 -37
- package/dist/components/datagrid/datagrid-checkbox.svelte +101 -101
- package/dist/components/datagrid/datagrid-footer.svelte +34 -34
- package/dist/components/datagrid/datagrid-header.svelte +49 -49
- package/dist/components/datagrid/datagrid-root.svelte +2 -2
- package/dist/components/datagrid/datagrid.css +5 -47
- package/dist/components/datagrid/td/datagrid-td.svelte +66 -66
- package/dist/components/datagrid/th/datagrid-th.svelte +106 -106
- package/dist/components/datagrid/tr/datagrid-tr.svelte +88 -88
- package/dist/components/datagrid/types.d.ts +1 -1
- package/dist/components/date-picker/atoms.d.ts +3 -0
- package/dist/components/date-picker/atoms.js +3 -0
- package/dist/components/date-picker/bond.svelte.d.ts +67 -0
- package/dist/components/date-picker/bond.svelte.js +174 -0
- package/dist/components/date-picker/date-picker-calendar.svelte +67 -0
- package/dist/components/date-picker/date-picker-calendar.svelte.d.ts +4 -0
- package/dist/components/date-picker/date-picker-header.svelte +100 -0
- package/dist/components/date-picker/date-picker-header.svelte.d.ts +4 -0
- package/dist/components/date-picker/date-picker-months.svelte +142 -0
- package/dist/components/date-picker/date-picker-months.svelte.d.ts +4 -0
- package/dist/components/date-picker/date-picker-root.svelte +95 -0
- package/dist/components/date-picker/date-picker-root.svelte.d.ts +4 -0
- package/dist/components/date-picker/date-picker-years.svelte +205 -0
- package/dist/components/date-picker/date-picker-years.svelte.d.ts +4 -0
- package/dist/components/date-picker/date-picker.stories.svelte +42 -0
- package/dist/components/date-picker/date-picker.stories.svelte.d.ts +3 -0
- package/dist/components/date-picker/index.d.ts +3 -0
- package/dist/components/date-picker/index.js +3 -0
- package/dist/components/date-picker/types.d.ts +53 -0
- package/dist/components/date-picker/types.js +1 -0
- package/dist/components/dialog/dialog-body.svelte +39 -39
- package/dist/components/dialog/dialog-close-button.svelte +58 -58
- package/dist/components/dialog/dialog-content.svelte +1 -1
- package/dist/components/dialog/dialog-description.svelte +40 -40
- package/dist/components/dialog/dialog-footer.svelte +39 -39
- package/dist/components/dialog/dialog-header.svelte +39 -39
- package/dist/components/dialog/dialog-root.svelte +110 -110
- package/dist/components/dialog/dialog-title.svelte +41 -41
- package/dist/components/drawer/drawer-backdrop.svelte +38 -38
- package/dist/components/drawer/drawer-body.svelte +42 -42
- package/dist/components/drawer/drawer-content.svelte +42 -42
- package/dist/components/drawer/drawer-description.svelte +44 -44
- package/dist/components/drawer/drawer-footer.svelte +41 -41
- package/dist/components/drawer/drawer-header.svelte +43 -43
- package/dist/components/drawer/drawer-root.svelte +93 -93
- package/dist/components/drawer/drawer-title.svelte +44 -44
- package/dist/components/dropdown/dropdown-query.svelte +54 -54
- package/dist/components/dropdown/dropdown-root.svelte +59 -59
- package/dist/components/dropdown/dropdown-trigger.svelte +41 -41
- package/dist/components/dropdown/dropdown-value.svelte +60 -60
- package/dist/components/element/types.d.ts +1 -1
- package/dist/components/form/bond.svelte.d.ts +1 -1
- package/dist/components/form/field/field-control.svelte +48 -48
- package/dist/components/form/field/field-label.svelte +24 -24
- package/dist/components/form/field/field-root.svelte +59 -59
- package/dist/components/icon/icon.svelte +44 -44
- package/dist/components/image/image.stories.svelte.d.ts +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +4 -0
- package/dist/components/input/input-control.svelte +103 -103
- package/dist/components/label/label.svelte +25 -25
- package/dist/components/lazy/index.d.ts +1 -0
- package/dist/components/lazy/index.js +1 -0
- package/dist/components/lazy/lazy.stories.svelte +35 -0
- package/dist/components/lazy/lazy.stories.svelte.d.ts +19 -0
- package/dist/components/lazy/lazy.svelte +28 -0
- package/dist/components/lazy/lazy.svelte.d.ts +5 -0
- package/dist/components/lazy/types.d.ts +10 -0
- package/dist/components/lazy/types.js +1 -0
- package/dist/components/menu/menu-list.svelte +40 -39
- package/dist/components/menu/menu-list.svelte.d.ts +1 -0
- package/dist/components/popover/popover-arrow.svelte +111 -111
- package/dist/components/popover/popover-content.svelte +178 -139
- package/dist/components/popover/popover-root.svelte +16 -17
- package/dist/components/popover/popover.stories.svelte +0 -15
- package/dist/components/portal/portal-root.svelte +83 -83
- package/dist/components/portal/teleport.svelte +50 -50
- package/dist/components/qr-code/index.d.ts +2 -0
- package/dist/components/qr-code/index.js +2 -0
- package/dist/components/qr-code/qr-code.stories.svelte +27 -0
- package/dist/components/qr-code/qr-code.stories.svelte.d.ts +26 -0
- package/dist/components/qr-code/qr-code.svelte +75 -0
- package/dist/components/qr-code/qr-code.svelte.d.ts +4 -0
- package/dist/components/qr-code/types.d.ts +14 -0
- package/dist/components/qr-code/types.js +1 -0
- package/dist/components/radio/radio.svelte +109 -109
- package/dist/components/radio/types.svelte.d.ts +1 -1
- package/dist/components/scrollable/scrollable-container.svelte +82 -82
- package/dist/components/scrollable/scrollable-content.svelte +41 -41
- package/dist/components/scrollable/scrollable-root.svelte +100 -100
- package/dist/components/scrollable/scrollable-thumb.svelte +75 -75
- package/dist/components/scrollable/scrollable-track.svelte +59 -59
- package/dist/components/scrollable/scrollable.stories.svelte.d.ts +1 -1
- package/dist/components/sidebar/bond.svelte.d.ts +0 -5
- package/dist/components/sidebar/bond.svelte.js +1 -12
- package/dist/components/sidebar/sidebar-content.svelte +39 -39
- package/dist/components/sidebar/sidebar-content.svelte.d.ts +2 -2
- package/dist/components/sidebar/sidebar-root.svelte +41 -68
- package/dist/components/sidebar/sidebar-root.svelte.d.ts +2 -2
- package/dist/components/sidebar/sidebar.stories.svelte +54 -52
- package/dist/components/sidebar/types.d.ts +6 -6
- package/dist/components/tabs/tab/tab-body.svelte +52 -52
- package/dist/components/tabs/tab/tab-description.svelte +41 -41
- package/dist/components/tabs/tab/tab-header.svelte +71 -71
- package/dist/components/tabs/tab/tab-root.svelte +86 -86
- package/dist/components/toast/toast-description.svelte +38 -38
- package/dist/components/toast/toast-root.svelte +61 -61
- package/dist/components/toast/toast-title.svelte +35 -35
- package/dist/components/tree/tree-body.svelte +39 -39
- package/dist/components/tree/tree-header.svelte +54 -54
- package/dist/components/tree/tree-indicator.svelte +40 -40
- package/dist/components/tree/tree-root.svelte +65 -65
- package/dist/components/virtual/virtual-root.svelte +239 -239
- package/dist/context/preset.svelte.d.ts +1 -1
- package/dist/icons/icon-arrow-down.svelte.d.ts +1 -1
- package/dist/icons/icon-checkmark.svelte.d.ts +1 -1
- package/dist/icons/icon-close.svelte.d.ts +1 -1
- package/dist/icons/icon-more-vert.svelte.d.ts +1 -1
- package/dist/runes/container.svelte.d.ts +2 -2
- package/dist/shared/bond.svelte.d.ts +1 -1
- package/dist/utils/state.d.ts +1 -1
- package/dist/utils/state.js +2 -1
- package/llm/variants.md +650 -103
- 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
|
-
|
|
199
|
-
import { defineVariants } from '@svelte-atoms/core/utils';
|
|
198
|
+
## Basic Usage
|
|
200
199
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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: '
|
|
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
|
-
|
|
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
|
-
|
|
269
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
357
|
-
|
|
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
|
|
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:
|
|
524
|
+
### Example 4: Alert Component with Compound Variants
|
|
472
525
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
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 {
|
|
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
|
-
|
|
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 {...
|
|
557
|
-
{@render children?.(
|
|
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
|
-
|
|
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.
|
|
708
|
+
### 2. Pass Variants Function to Components
|
|
662
709
|
|
|
663
|
-
|
|
710
|
+
Always pass the variant function (not the result) to `HtmlAtom`:
|
|
664
711
|
|
|
665
712
|
```svelte
|
|
666
713
|
<script>
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
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
|
-
|
|
681
|
-
const variantProps = buttonVariants(bond, { variant, size });
|
|
731
|
+
let { variant, size, class: klass = '', ...props } = $props();
|
|
682
732
|
</script>
|
|
683
733
|
|
|
684
|
-
<HtmlAtom class={[
|
|
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.
|