@svelte-atoms/core 1.0.0-alpha.25 → 1.0.0-alpha.27
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 +645 -645
- package/dist/components/accordion/accordion-root.svelte +61 -79
- package/dist/components/accordion/accordion-root.svelte.d.ts +2 -15
- package/dist/components/accordion/index.d.ts +2 -1
- package/dist/components/accordion/index.js +2 -1
- package/dist/components/accordion/item/accordion-item-body.svelte +42 -52
- package/dist/components/accordion/item/accordion-item-body.svelte.d.ts +2 -8
- package/dist/components/accordion/item/accordion-item-header.svelte +50 -56
- package/dist/components/accordion/item/accordion-item-header.svelte.d.ts +3 -20
- package/dist/components/accordion/item/accordion-item-indicator.svelte +50 -59
- package/dist/components/accordion/item/accordion-item-indicator.svelte.d.ts +2 -8
- package/dist/components/accordion/item/accordion-item-root.svelte +65 -79
- package/dist/components/accordion/item/accordion-item-root.svelte.d.ts +2 -12
- package/dist/components/accordion/item/index.d.ts +1 -0
- package/dist/components/accordion/item/types.d.ts +52 -0
- package/dist/components/accordion/item/types.js +1 -0
- package/dist/components/accordion/types.d.ts +21 -0
- package/dist/components/accordion/types.js +1 -0
- package/dist/components/alert/alert-actions.svelte +42 -52
- package/dist/components/alert/alert-actions.svelte.d.ts +3 -30
- package/dist/components/alert/alert-close-button.svelte +72 -79
- package/dist/components/alert/alert-close-button.svelte.d.ts +8 -35
- package/dist/components/alert/alert-content.svelte +42 -52
- package/dist/components/alert/alert-content.svelte.d.ts +3 -30
- package/dist/components/alert/alert-description.svelte +41 -51
- package/dist/components/alert/alert-description.svelte.d.ts +7 -10
- package/dist/components/alert/alert-icon.svelte +46 -56
- package/dist/components/alert/alert-icon.svelte.d.ts +2 -8
- package/dist/components/alert/alert-root.svelte +102 -118
- package/dist/components/alert/alert-root.svelte.d.ts +2 -13
- package/dist/components/alert/alert-title.svelte +41 -51
- package/dist/components/alert/alert-title.svelte.d.ts +2 -8
- package/dist/components/alert/index.d.ts +1 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/alert/types.d.ts +85 -0
- package/dist/components/alert/types.js +1 -0
- package/dist/components/atom/html-atom.svelte +201 -217
- package/dist/components/atom/html-atom.svelte.d.ts +2 -22
- package/dist/components/atom/types.d.ts +7 -2
- package/dist/components/avatar/types.d.ts +7 -2
- package/dist/components/badge/badge.svelte +1 -1
- package/dist/components/badge/types.d.ts +7 -2
- package/dist/components/breadcrumb/breadcrumb-item.svelte +1 -1
- package/dist/components/breadcrumb/breadcrumb-root.svelte +1 -1
- package/dist/components/breadcrumb/breadcrumb-separator.svelte +1 -1
- package/dist/components/button/button.stories.svelte +57 -57
- package/dist/components/button/button.svelte +1 -1
- package/dist/components/button/button.svelte.d.ts +4 -1
- package/dist/components/button/index.d.ts +1 -0
- package/dist/components/button/index.js +1 -0
- package/dist/components/button/types.d.ts +8 -3
- package/dist/components/card/card-body.svelte +39 -45
- package/dist/components/card/card-body.svelte.d.ts +7 -4
- package/dist/components/card/card-description.svelte +41 -48
- package/dist/components/card/card-description.svelte.d.ts +7 -7
- package/dist/components/card/card-footer.svelte +41 -48
- package/dist/components/card/card-footer.svelte.d.ts +7 -4
- package/dist/components/card/card-header.svelte +41 -48
- package/dist/components/card/card-header.svelte.d.ts +7 -4
- package/dist/components/card/card-media.svelte +41 -48
- package/dist/components/card/card-media.svelte.d.ts +7 -4
- package/dist/components/card/card-root.svelte +91 -91
- package/dist/components/card/card-root.svelte.d.ts +1 -1
- package/dist/components/card/card-subtitle.svelte +41 -48
- package/dist/components/card/card-subtitle.svelte.d.ts +12 -9
- package/dist/components/card/card-title.svelte +45 -48
- package/dist/components/card/card-title.svelte.d.ts +12 -9
- package/dist/components/card/index.d.ts +1 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/card/types.d.ts +57 -2
- package/dist/components/checkbox/checkbox.svelte +39 -28
- package/dist/components/checkbox/types.d.ts +7 -2
- package/dist/components/collapsible/collapsible-body.svelte +39 -52
- package/dist/components/collapsible/collapsible-body.svelte.d.ts +2 -9
- package/dist/components/collapsible/collapsible-header.svelte +39 -52
- package/dist/components/collapsible/collapsible-header.svelte.d.ts +2 -9
- package/dist/components/collapsible/collapsible-indicator.svelte +50 -65
- package/dist/components/collapsible/collapsible-indicator.svelte.d.ts +3 -10
- package/dist/components/collapsible/collapsible-root.svelte +66 -85
- package/dist/components/collapsible/collapsible-root.svelte.d.ts +2 -14
- package/dist/components/collapsible/index.d.ts +1 -0
- package/dist/components/collapsible/index.js +1 -0
- package/dist/components/collapsible/types.d.ts +54 -0
- package/dist/components/collapsible/types.js +1 -0
- package/dist/components/combobox/atoms.d.ts +5 -1
- package/dist/components/combobox/atoms.js +5 -1
- package/dist/components/combobox/{combobox-input.svelte → combobox-control.svelte} +3 -3
- package/dist/components/combobox/{combobox-input.svelte.d.ts → combobox-control.svelte.d.ts} +3 -3
- package/dist/components/combobox/combobox-root.svelte +65 -68
- package/dist/components/combobox/combobox-root.svelte.d.ts +5 -18
- package/dist/components/combobox/combobox-trigger.svelte +1 -1
- package/dist/components/combobox/compobox-item.svelte +1 -1
- package/dist/components/combobox/index.d.ts +1 -0
- package/dist/components/combobox/index.js +1 -0
- package/dist/components/combobox/types.d.ts +25 -0
- package/dist/components/combobox/types.js +1 -0
- package/dist/components/container/container.svelte +1 -1
- package/dist/components/container/types.d.ts +7 -2
- package/dist/components/contextmenu/types.d.ts +8 -0
- package/dist/components/contextmenu/types.js +1 -0
- package/dist/components/datagrid/datagrid-body.svelte +37 -44
- package/dist/components/datagrid/datagrid-body.svelte.d.ts +17 -20
- package/dist/components/datagrid/datagrid-checkbox.svelte +101 -108
- package/dist/components/datagrid/datagrid-checkbox.svelte.d.ts +4 -6
- package/dist/components/datagrid/datagrid-footer.svelte +34 -34
- package/dist/components/datagrid/datagrid-footer.svelte.d.ts +1 -1
- package/dist/components/datagrid/datagrid-header.svelte +49 -49
- package/dist/components/datagrid/datagrid-header.svelte.d.ts +1 -1
- package/dist/components/datagrid/datagrid-root.svelte +59 -59
- package/dist/components/datagrid/datagrid-root.svelte.d.ts +1 -1
- package/dist/components/datagrid/datagrid.stories.svelte +75 -75
- package/dist/components/datagrid/td/datagrid-td.svelte +66 -80
- package/dist/components/datagrid/td/datagrid-td.svelte.d.ts +7 -16
- package/dist/components/datagrid/th/datagrid-th-sort-icon.svelte +1 -1
- package/dist/components/datagrid/th/datagrid-th.svelte +106 -127
- package/dist/components/datagrid/th/datagrid-th.svelte.d.ts +2 -20
- package/dist/components/datagrid/tr/bond.svelte.d.ts +3 -1
- package/dist/components/datagrid/tr/bond.svelte.js +4 -2
- package/dist/components/datagrid/tr/datagrid-tr.svelte +88 -103
- package/dist/components/datagrid/tr/datagrid-tr.svelte.d.ts +2 -18
- package/dist/components/datagrid/types.d.ts +85 -37
- package/dist/components/dialog/dialog-body.svelte +39 -45
- package/dist/components/dialog/dialog-body.svelte.d.ts +2 -2
- package/dist/components/dialog/dialog-close-button.svelte +58 -61
- package/dist/components/dialog/dialog-close-button.svelte.d.ts +7 -7
- package/dist/components/dialog/dialog-content.svelte +62 -71
- package/dist/components/dialog/dialog-content.svelte.d.ts +2 -2
- package/dist/components/dialog/dialog-description.svelte +40 -46
- package/dist/components/dialog/dialog-description.svelte.d.ts +2 -2
- package/dist/components/dialog/dialog-footer.svelte +39 -45
- package/dist/components/dialog/dialog-footer.svelte.d.ts +2 -2
- package/dist/components/dialog/dialog-header.svelte +39 -45
- package/dist/components/dialog/dialog-header.svelte.d.ts +2 -2
- package/dist/components/dialog/dialog-root.svelte +110 -120
- package/dist/components/dialog/dialog-root.svelte.d.ts +2 -10
- package/dist/components/dialog/dialog-title.svelte +41 -47
- package/dist/components/dialog/dialog-title.svelte.d.ts +7 -7
- package/dist/components/dialog/index.d.ts +1 -0
- package/dist/components/dialog/index.js +1 -0
- package/dist/components/dialog/types.d.ts +67 -0
- package/dist/components/dialog/types.js +1 -0
- package/dist/components/divider/types.d.ts +10 -0
- package/dist/components/divider/types.js +1 -0
- package/dist/components/drawer/drawer-backdrop.svelte +38 -47
- package/dist/components/drawer/drawer-backdrop.svelte.d.ts +3 -26
- package/dist/components/drawer/drawer-body.svelte +42 -56
- package/dist/components/drawer/drawer-body.svelte.d.ts +3 -16
- package/dist/components/drawer/drawer-content.svelte +42 -55
- package/dist/components/drawer/drawer-content.svelte.d.ts +3 -14
- package/dist/components/drawer/drawer-description.svelte +44 -57
- package/dist/components/drawer/drawer-description.svelte.d.ts +3 -14
- package/dist/components/drawer/drawer-footer.svelte +41 -54
- package/dist/components/drawer/drawer-footer.svelte.d.ts +3 -14
- package/dist/components/drawer/drawer-header.svelte +43 -56
- package/dist/components/drawer/drawer-header.svelte.d.ts +3 -14
- package/dist/components/drawer/drawer-root.svelte +93 -113
- package/dist/components/drawer/drawer-root.svelte.d.ts +3 -31
- package/dist/components/drawer/drawer-title.svelte +44 -57
- package/dist/components/drawer/drawer-title.svelte.d.ts +3 -14
- package/dist/components/drawer/index.d.ts +1 -0
- package/dist/components/drawer/index.js +1 -0
- package/dist/components/drawer/types.d.ts +86 -0
- package/dist/components/drawer/types.js +1 -0
- package/dist/components/dropdown/dropdown-placeholder.svelte +1 -1
- package/dist/components/dropdown/dropdown-query.svelte +54 -53
- package/dist/components/dropdown/dropdown-query.svelte.d.ts +11 -10
- package/dist/components/dropdown/dropdown-root.svelte +59 -59
- package/dist/components/dropdown/dropdown-trigger.svelte +41 -52
- package/dist/components/dropdown/dropdown-trigger.svelte.d.ts +1 -8
- package/dist/components/dropdown/dropdown-value.svelte +60 -62
- package/dist/components/dropdown/index.d.ts +1 -0
- package/dist/components/dropdown/index.js +1 -0
- package/dist/components/dropdown/item/bond.svelte.d.ts +4 -0
- package/dist/components/dropdown/item/bond.svelte.js +9 -0
- package/dist/components/dropdown/item/dropdown-item.svelte +10 -6
- package/dist/components/dropdown/types.d.ts +37 -0
- package/dist/components/dropdown/types.js +1 -0
- package/dist/components/element/html-element.svelte.d.ts +2 -14
- package/dist/components/element/svg-element.svelte.d.ts +2 -14
- package/dist/components/element/types.d.ts +14 -7
- package/dist/components/form/field/bond.svelte.d.ts +8 -0
- package/dist/components/form/field/bond.svelte.js +13 -1
- package/dist/components/form/field/field-control.svelte +48 -58
- package/dist/components/form/field/field-control.svelte.d.ts +5 -19
- package/dist/components/form/field/field-label.svelte +24 -31
- package/dist/components/form/field/field-label.svelte.d.ts +1 -2
- package/dist/components/form/field/field-root.svelte +59 -88
- package/dist/components/form/field/field-root.svelte.d.ts +5 -20
- package/dist/components/form/form.stories.svelte +3 -3
- package/dist/components/form/index.d.ts +1 -0
- package/dist/components/form/index.js +1 -0
- package/dist/components/form/types.d.ts +76 -0
- package/dist/components/form/types.js +1 -0
- package/dist/components/icon/icon.svelte +44 -55
- package/dist/components/icon/icon.svelte.d.ts +4 -29
- package/dist/components/icon/types.d.ts +11 -7
- package/dist/components/input/atoms.d.ts +5 -1
- package/dist/components/input/atoms.js +5 -1
- package/dist/components/input/index.d.ts +1 -0
- package/dist/components/input/index.js +1 -0
- package/dist/components/input/{input-value.svelte → input-control.svelte} +14 -24
- package/dist/components/input/input-control.svelte.d.ts +26 -0
- package/dist/components/input/input-icon.svelte +1 -1
- package/dist/components/input/input-icon.svelte.d.ts +1 -1
- package/dist/components/input/input-placeholder.svelte +54 -56
- package/dist/components/input/input-placeholder.svelte.d.ts +2 -19
- package/dist/components/input/input-root.svelte +5 -12
- package/dist/components/input/input-root.svelte.d.ts +3 -20
- package/dist/components/input/input.stories.svelte +2 -2
- package/dist/components/input/types.d.ts +33 -0
- package/dist/components/input/types.js +1 -0
- package/dist/components/label/index.d.ts +1 -0
- package/dist/components/label/index.js +1 -0
- package/dist/components/label/label.svelte +25 -41
- package/dist/components/label/label.svelte.d.ts +3 -27
- package/dist/components/label/types.d.ts +11 -0
- package/dist/components/label/types.js +1 -0
- package/dist/components/layer/layer-inner.svelte.d.ts +2 -19
- package/dist/components/layer/layer-root.svelte.d.ts +2 -19
- package/dist/components/layer/types.d.ts +11 -0
- package/dist/components/layer/types.js +1 -0
- package/dist/components/link/types.d.ts +8 -0
- package/dist/components/link/types.js +1 -0
- package/dist/components/list/list-group.svelte +1 -1
- package/dist/components/list/list-item.svelte +1 -1
- package/dist/components/list/list-root.svelte +6 -1
- package/dist/components/list/list-title.svelte +1 -1
- package/dist/components/list/types.d.ts +8 -0
- package/dist/components/list/types.js +1 -0
- package/dist/components/menu/index.d.ts +1 -0
- package/dist/components/menu/index.js +1 -0
- package/dist/components/menu/menu-list.svelte +1 -1
- package/dist/components/menu/types.d.ts +15 -0
- package/dist/components/menu/types.js +1 -0
- package/dist/components/popover/bond.svelte.d.ts +2 -0
- package/dist/components/popover/bond.svelte.js +1 -1
- package/dist/components/popover/index.d.ts +1 -0
- package/dist/components/popover/index.js +1 -0
- package/dist/components/popover/popover-arrow.svelte +111 -117
- package/dist/components/popover/popover-arrow.svelte.d.ts +3 -20
- package/dist/components/popover/popover-content.svelte +139 -147
- package/dist/components/popover/popover-content.svelte.d.ts +3 -17
- package/dist/components/popover/popover-indicator.svelte +1 -1
- package/dist/components/popover/popover-root.svelte +4 -18
- package/dist/components/popover/popover-root.svelte.d.ts +1 -15
- package/dist/components/popover/popover-trigger.svelte +3 -12
- package/dist/components/popover/popover-trigger.svelte.d.ts +2 -8
- package/dist/components/popover/types.d.ts +61 -0
- package/dist/components/popover/types.js +1 -0
- package/dist/components/portal/active-portal.svelte +8 -2
- package/dist/components/portal/active-portal.svelte.d.ts +2 -2
- package/dist/components/portal/index.d.ts +1 -0
- package/dist/components/portal/index.js +1 -0
- package/dist/components/portal/portal-inner.svelte +1 -1
- package/dist/components/portal/portal-inner.svelte.d.ts +2 -19
- package/dist/components/portal/portal-root.svelte +83 -88
- package/dist/components/portal/portal-root.svelte.d.ts +2 -22
- package/dist/components/portal/teleport.svelte +50 -49
- package/dist/components/portal/teleport.svelte.d.ts +5 -23
- package/dist/components/portal/types.d.ts +39 -0
- package/dist/components/portal/types.js +1 -0
- package/dist/components/radio/radio-group.stories.svelte +4 -4
- package/dist/components/radio/radio.svelte +109 -109
- package/dist/components/radio/radio.svelte.d.ts +14 -36
- package/dist/components/root/root.css +24 -66
- package/dist/components/root/root.svelte +121 -121
- package/dist/components/root/types.d.ts +8 -0
- package/dist/components/root/types.js +1 -0
- package/dist/components/scrollable/index.d.ts +1 -0
- package/dist/components/scrollable/index.js +1 -0
- package/dist/components/scrollable/scrollable-container.svelte +82 -89
- package/dist/components/scrollable/scrollable-container.svelte.d.ts +2 -6
- package/dist/components/scrollable/scrollable-content.svelte +41 -51
- package/dist/components/scrollable/scrollable-content.svelte.d.ts +1 -6
- package/dist/components/scrollable/scrollable-root.svelte +100 -120
- package/dist/components/scrollable/scrollable-root.svelte.d.ts +3 -19
- package/dist/components/scrollable/scrollable-thumb.svelte +75 -86
- package/dist/components/scrollable/scrollable-thumb.svelte.d.ts +1 -7
- package/dist/components/scrollable/scrollable-track.svelte +59 -70
- package/dist/components/scrollable/scrollable-track.svelte.d.ts +1 -7
- package/dist/components/scrollable/types.d.ts +62 -0
- package/dist/components/scrollable/types.js +1 -0
- package/dist/components/sidebar/index.d.ts +1 -0
- package/dist/components/sidebar/index.js +1 -0
- package/dist/components/sidebar/sidebar-content.svelte +2 -16
- package/dist/components/sidebar/sidebar-content.svelte.d.ts +2 -9
- package/dist/components/sidebar/sidebar-root.svelte +4 -23
- package/dist/components/sidebar/sidebar-root.svelte.d.ts +2 -13
- package/dist/components/sidebar/types.d.ts +30 -0
- package/dist/components/sidebar/types.js +1 -0
- package/dist/components/stack/stack-item.svelte +5 -1
- package/dist/components/stack/stack-root.svelte +5 -1
- package/dist/components/stack/stack-root.svelte.d.ts +2 -19
- package/dist/components/stack/types.d.ts +12 -0
- package/dist/components/stack/types.js +1 -0
- package/dist/components/tabs/index.d.ts +1 -0
- package/dist/components/tabs/index.js +1 -0
- package/dist/components/tabs/tab/tab-body.svelte +52 -61
- package/dist/components/tabs/tab/tab-body.svelte.d.ts +2 -8
- package/dist/components/tabs/tab/tab-description.svelte +41 -50
- package/dist/components/tabs/tab/tab-description.svelte.d.ts +2 -8
- package/dist/components/tabs/tab/tab-header.svelte +71 -81
- package/dist/components/tabs/tab/tab-header.svelte.d.ts +2 -11
- package/dist/components/tabs/tab/tab-root.svelte +86 -81
- package/dist/components/tabs/tabs-body.svelte +1 -1
- package/dist/components/tabs/tabs-header.svelte +1 -1
- package/dist/components/tabs/tabs-root.svelte +1 -1
- package/dist/components/tabs/types.d.ts +55 -0
- package/dist/components/tabs/types.js +1 -0
- package/dist/components/textarea/index.d.ts +1 -0
- package/dist/components/textarea/index.js +1 -0
- package/dist/components/textarea/textarea-input.svelte +2 -1
- package/dist/components/textarea/types.d.ts +28 -0
- package/dist/components/textarea/types.js +1 -0
- package/dist/components/toast/index.d.ts +1 -0
- package/dist/components/toast/index.js +1 -0
- package/dist/components/toast/toast-description.svelte +38 -44
- package/dist/components/toast/toast-description.svelte.d.ts +8 -34
- package/dist/components/toast/toast-root.svelte +61 -74
- package/dist/components/toast/toast-root.svelte.d.ts +4 -43
- package/dist/components/toast/toast-title.svelte +35 -43
- package/dist/components/toast/toast-title.svelte.d.ts +2 -34
- package/dist/components/toast/types.d.ts +40 -0
- package/dist/components/toast/types.js +1 -0
- package/dist/components/tooltip/types.d.ts +13 -0
- package/dist/components/tooltip/types.js +1 -0
- package/dist/components/tree/index.d.ts +1 -0
- package/dist/components/tree/index.js +1 -0
- package/dist/components/tree/tree-body.svelte +39 -50
- package/dist/components/tree/tree-body.svelte.d.ts +2 -10
- package/dist/components/tree/tree-header.svelte +54 -66
- package/dist/components/tree/tree-header.svelte.d.ts +3 -29
- package/dist/components/tree/tree-indicator.svelte +40 -50
- package/dist/components/tree/tree-indicator.svelte.d.ts +3 -9
- package/dist/components/tree/tree-root.svelte +65 -80
- package/dist/components/tree/tree-root.svelte.d.ts +2 -12
- package/dist/components/tree/types.d.ts +59 -0
- package/dist/components/tree/types.js +1 -0
- package/dist/components/virtual/types.d.ts +23 -0
- package/dist/components/virtual/types.js +1 -0
- package/dist/components/virtual/virtual-root.svelte +239 -258
- package/dist/components/virtual/virtual-root.svelte.d.ts +1 -18
- package/dist/context/preset.svelte.d.ts +1 -1
- package/llm/composition.md +395 -395
- package/llm/crafting.md +838 -838
- package/llm/motion.md +970 -970
- package/llm/philosophy.md +23 -23
- package/llm/preset-variant-integration.md +516 -516
- package/llm/preset.md +383 -383
- package/llm/styling.md +216 -216
- package/llm/usage.md +46 -46
- package/llm/variants.md +712 -712
- package/package.json +437 -437
- package/dist/components/input/input-value.svelte.d.ts +0 -19
|
@@ -1,516 +1,516 @@
|
|
|
1
|
-
# Preset-Variant Integration
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
The variant system is deeply integrated with the preset system in @svelte-atoms/core, providing a powerful theming architecture that combines:
|
|
6
|
-
|
|
7
|
-
- **Global variants** via presets (app-level theming)
|
|
8
|
-
- **Local variants** via component props (component-level customization)
|
|
9
|
-
- **Intelligent merging** that respects the hierarchy
|
|
10
|
-
|
|
11
|
-
## Architecture
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
┌─────────────────────────────────────────────────────┐
|
|
15
|
-
│ Theme Layer (Preset System) │
|
|
16
|
-
│ │
|
|
17
|
-
│ setPreset({ │
|
|
18
|
-
│ button: () => ({ │
|
|
19
|
-
│ class: 'font-medium', // Base styling │
|
|
20
|
-
│ variants: { // Global variant defs │
|
|
21
|
-
│ base: 'rounded-md', │
|
|
22
|
-
│ variants: { │
|
|
23
|
-
│ variant: { primary: '...', secondary: '...' }│
|
|
24
|
-
│ size: { sm: '...', md: '...', lg: '...' } │
|
|
25
|
-
│ } │
|
|
26
|
-
│ } │
|
|
27
|
-
│ }) │
|
|
28
|
-
│ }) │
|
|
29
|
-
└─────────────────────────────────────────────────────┘
|
|
30
|
-
↓
|
|
31
|
-
[MERGE STRATEGY]
|
|
32
|
-
↓
|
|
33
|
-
┌─────────────────────────────────────────────────────┐
|
|
34
|
-
│ Component Layer (Local Variants) │
|
|
35
|
-
│ │
|
|
36
|
-
│ <HtmlAtom │
|
|
37
|
-
│ preset="button" │
|
|
38
|
-
│ variants={localVariants} // Overrides/extends │
|
|
39
|
-
│ variant="primary" │
|
|
40
|
-
│ size="lg" │
|
|
41
|
-
│ /> │
|
|
42
|
-
└─────────────────────────────────────────────────────┘
|
|
43
|
-
↓
|
|
44
|
-
[RESOLUTION]
|
|
45
|
-
↓
|
|
46
|
-
┌─────────────────────────────────────────────────────┐
|
|
47
|
-
│ Final Output │
|
|
48
|
-
│ │
|
|
49
|
-
│ class: merged classes from preset + local + props │
|
|
50
|
-
│ attributes: aria-*, data-*, role, etc. │
|
|
51
|
-
└─────────────────────────────────────────────────────┘
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Merge Strategy
|
|
55
|
-
|
|
56
|
-
### 1. Variant Definition Merging
|
|
57
|
-
|
|
58
|
-
When both preset and component define variants, they merge as follows:
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
{
|
|
62
|
-
base: localVariants.base ?? presetVariants.base,
|
|
63
|
-
|
|
64
|
-
variants: merge(
|
|
65
|
-
presetVariants.variants ?? {},
|
|
66
|
-
localVariants.variants ?? {}
|
|
67
|
-
),
|
|
68
|
-
|
|
69
|
-
compoundVariants: [
|
|
70
|
-
...(presetVariants.compoundVariants ?? []),
|
|
71
|
-
...(localVariants.compoundVariants ?? [])
|
|
72
|
-
],
|
|
73
|
-
|
|
74
|
-
defaultVariants: merge(
|
|
75
|
-
presetVariants.defaultVariants ?? {},
|
|
76
|
-
localVariants.defaultVariants ?? {}
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
**Rules:**
|
|
82
|
-
|
|
83
|
-
- Local `base` overrides preset `base`
|
|
84
|
-
- Local variants **merge** with preset variants (not replace)
|
|
85
|
-
- Compound variants from both are **concatenated**
|
|
86
|
-
- Default variants **merge** (local overrides preset)
|
|
87
|
-
|
|
88
|
-
### 2. Class Resolution Order
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
-
Final Class = [
|
|
92
|
-
preset.class, // 1. Preset base class
|
|
93
|
-
preset.variants.base, // 2. Preset variant base
|
|
94
|
-
mergedVariants.base, // 3. Merged variant base (local overrides)
|
|
95
|
-
variantClasses, // 4. Resolved variant classes
|
|
96
|
-
compoundClasses, // 5. Compound variant classes
|
|
97
|
-
component.class // 6. Component class prop (highest priority)
|
|
98
|
-
]
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### 3. Props Merging
|
|
102
|
-
|
|
103
|
-
```typescript
|
|
104
|
-
{
|
|
105
|
-
...preset (excluding: class, base, as, variants),
|
|
106
|
-
...variantAttributes (aria-*, data-*, role, etc.),
|
|
107
|
-
...componentProps (user-provided props - highest priority)
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Usage Patterns
|
|
112
|
-
|
|
113
|
-
### Pattern 1: Pure Preset (No Local Variants)
|
|
114
|
-
|
|
115
|
-
**Best for:** Consistent components that don't need customization
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
// Theme.svelte
|
|
119
|
-
setPreset({
|
|
120
|
-
badge: () => ({
|
|
121
|
-
variants: {
|
|
122
|
-
base: 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold',
|
|
123
|
-
variants: {
|
|
124
|
-
variant: {
|
|
125
|
-
default: 'bg-primary text-primary-foreground',
|
|
126
|
-
secondary: 'bg-secondary text-secondary-foreground',
|
|
127
|
-
destructive: 'bg-destructive text-destructive-foreground',
|
|
128
|
-
outline: 'border border-input'
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
defaultVariants: {
|
|
132
|
-
variant: 'default'
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
})
|
|
136
|
-
});
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
```svelte
|
|
140
|
-
<!-- Badge.svelte -->
|
|
141
|
-
<HtmlAtom preset="badge" {variant} {...props}>
|
|
142
|
-
{@render children?.()}
|
|
143
|
-
</HtmlAtom>
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
**Result:** Uses 100% preset variants, no local customization
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
### Pattern 2: Preset + Local Extension
|
|
151
|
-
|
|
152
|
-
**Best for:** Components that need additional variants beyond theme
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
// Theme.svelte
|
|
156
|
-
setPreset({
|
|
157
|
-
button: () => ({
|
|
158
|
-
variants: {
|
|
159
|
-
base: 'rounded-md font-medium',
|
|
160
|
-
variants: {
|
|
161
|
-
variant: {
|
|
162
|
-
default: 'bg-primary text-primary-foreground',
|
|
163
|
-
secondary: 'bg-secondary text-secondary-foreground'
|
|
164
|
-
},
|
|
165
|
-
size: {
|
|
166
|
-
sm: 'h-8 px-3',
|
|
167
|
-
md: 'h-10 px-4',
|
|
168
|
-
lg: 'h-12 px-6'
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
defaultVariants: {
|
|
172
|
-
variant: 'default',
|
|
173
|
-
size: 'md'
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
})
|
|
177
|
-
});
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
```svelte
|
|
181
|
-
<!-- IconButton.svelte -->
|
|
182
|
-
<script>
|
|
183
|
-
import { defineVariants } from '@svelte-atoms/core/utils';
|
|
184
|
-
|
|
185
|
-
// Extend preset with icon-specific variants
|
|
186
|
-
const iconVariants = defineVariants({
|
|
187
|
-
variants: {
|
|
188
|
-
// Add new variant key not in preset
|
|
189
|
-
iconPosition: {
|
|
190
|
-
left: 'flex-row',
|
|
191
|
-
right: 'flex-row-reverse',
|
|
192
|
-
top: 'flex-col',
|
|
193
|
-
bottom: 'flex-col-reverse'
|
|
194
|
-
}
|
|
195
|
-
},
|
|
196
|
-
defaultVariants: {
|
|
197
|
-
iconPosition: 'left'
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
</script>
|
|
201
|
-
|
|
202
|
-
<HtmlAtom preset="button" variants={iconVariants} {variant} {size} {iconPosition} {...props}>
|
|
203
|
-
{@render children?.()}
|
|
204
|
-
</HtmlAtom>
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
**Result:** Gets `variant` and `size` from preset, adds `iconPosition` locally
|
|
208
|
-
|
|
209
|
-
---
|
|
210
|
-
|
|
211
|
-
### Pattern 3: Preset Override
|
|
212
|
-
|
|
213
|
-
**Best for:** Special cases that need to completely override preset variants
|
|
214
|
-
|
|
215
|
-
```typescript
|
|
216
|
-
// Theme.svelte
|
|
217
|
-
setPreset({
|
|
218
|
-
button: () => ({
|
|
219
|
-
variants: {
|
|
220
|
-
base: 'rounded-md',
|
|
221
|
-
variants: {
|
|
222
|
-
variant: {
|
|
223
|
-
default: 'bg-primary text-primary-foreground',
|
|
224
|
-
destructive: 'bg-destructive text-destructive-foreground'
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
})
|
|
229
|
-
});
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
```svelte
|
|
233
|
-
<!-- GradientButton.svelte -->
|
|
234
|
-
<script>
|
|
235
|
-
import { defineVariants } from '@svelte-atoms/core/utils';
|
|
236
|
-
|
|
237
|
-
// Override preset variants completely
|
|
238
|
-
const gradientVariants = defineVariants({
|
|
239
|
-
base: 'rounded-full', // Overrides preset base
|
|
240
|
-
variants: {
|
|
241
|
-
variant: {
|
|
242
|
-
// Overrides preset variants
|
|
243
|
-
purple: 'bg-gradient-to-r from-purple-500 to-pink-500',
|
|
244
|
-
blue: 'bg-gradient-to-r from-blue-500 to-cyan-500',
|
|
245
|
-
green: 'bg-gradient-to-r from-green-500 to-emerald-500'
|
|
246
|
-
}
|
|
247
|
-
},
|
|
248
|
-
defaultVariants: {
|
|
249
|
-
variant: 'purple'
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
</script>
|
|
253
|
-
|
|
254
|
-
<HtmlAtom preset="button" variants={gradientVariants} {variant} {...props}>
|
|
255
|
-
{@render children?.()}
|
|
256
|
-
</HtmlAtom>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
**Result:** Local variants completely replace preset variants for matching keys
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
### Pattern 4: Pure Local (No Preset)
|
|
264
|
-
|
|
265
|
-
**Best for:** One-off components that don't need global theming
|
|
266
|
-
|
|
267
|
-
```svelte
|
|
268
|
-
<script>
|
|
269
|
-
import { defineVariants } from '@svelte-atoms/core/utils';
|
|
270
|
-
|
|
271
|
-
const customVariants = defineVariants({
|
|
272
|
-
base: 'custom-base-class',
|
|
273
|
-
variants: {
|
|
274
|
-
custom: {
|
|
275
|
-
a: 'class-a',
|
|
276
|
-
b: 'class-b'
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
</script>
|
|
281
|
-
|
|
282
|
-
<HtmlAtom variants={customVariants} custom="a" {...props}>
|
|
283
|
-
{@render children?.()}
|
|
284
|
-
</HtmlAtom>
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
**Result:** No preset used, 100% local variant definition
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
### Pattern 5: Dynamic Variants with Bond
|
|
292
|
-
|
|
293
|
-
**Best for:** Reactive variants that change based on component state
|
|
294
|
-
|
|
295
|
-
```typescript
|
|
296
|
-
// Theme.svelte
|
|
297
|
-
setPreset({
|
|
298
|
-
accordion: () => ({
|
|
299
|
-
variants: {
|
|
300
|
-
base: 'border rounded-md',
|
|
301
|
-
variants: {
|
|
302
|
-
state: {
|
|
303
|
-
// Function receives bond for reactive styling
|
|
304
|
-
open: (bond) => ({
|
|
305
|
-
class: bond?.state?.isOpen ? 'bg-accent' : 'bg-background',
|
|
306
|
-
'aria-expanded': bond?.state?.isOpen,
|
|
307
|
-
'data-state': bond?.state?.isOpen ? 'open' : 'closed'
|
|
308
|
-
})
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
})
|
|
313
|
-
});
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
```svelte
|
|
317
|
-
<!-- Accordion.svelte -->
|
|
318
|
-
<script>
|
|
319
|
-
import { AccordionBond } from './bond.svelte';
|
|
320
|
-
|
|
321
|
-
const bond = new AccordionBond(state).share();
|
|
322
|
-
</script>
|
|
323
|
-
|
|
324
|
-
<HtmlAtom preset="accordion" {bond} state="open" {...props}>
|
|
325
|
-
{@render children?.({ accordion: bond })}
|
|
326
|
-
</HtmlAtom>
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
**Result:** Variants reactively update when `bond.state.isOpen` changes
|
|
330
|
-
|
|
331
|
-
## Advanced Features
|
|
332
|
-
|
|
333
|
-
### 1. Nested Preset Keys
|
|
334
|
-
|
|
335
|
-
Organize related components with dot notation:
|
|
336
|
-
|
|
337
|
-
```typescript
|
|
338
|
-
setPreset({
|
|
339
|
-
card: () => ({
|
|
340
|
-
/* ... */
|
|
341
|
-
}),
|
|
342
|
-
'card.header': () => ({
|
|
343
|
-
/* ... */
|
|
344
|
-
}),
|
|
345
|
-
'card.body': () => ({
|
|
346
|
-
/* ... */
|
|
347
|
-
}),
|
|
348
|
-
'card.footer': () => ({
|
|
349
|
-
/* ... */
|
|
350
|
-
})
|
|
351
|
-
});
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
```svelte
|
|
355
|
-
<HtmlAtom preset="card.header" />
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
### 2. Compound Variants
|
|
359
|
-
|
|
360
|
-
Apply classes when multiple conditions match:
|
|
361
|
-
|
|
362
|
-
```typescript
|
|
363
|
-
setPreset({
|
|
364
|
-
button: () => ({
|
|
365
|
-
variants: {
|
|
366
|
-
variants: {
|
|
367
|
-
variant: { default: '...', destructive: '...' },
|
|
368
|
-
size: { sm: '...', lg: '...' }
|
|
369
|
-
},
|
|
370
|
-
compoundVariants: [
|
|
371
|
-
{
|
|
372
|
-
variant: 'destructive',
|
|
373
|
-
size: 'lg',
|
|
374
|
-
class: 'font-bold uppercase', // Applied ONLY when both match
|
|
375
|
-
'aria-label': 'Warning'
|
|
376
|
-
}
|
|
377
|
-
]
|
|
378
|
-
}
|
|
379
|
-
})
|
|
380
|
-
});
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
### 3. Variant Attributes
|
|
384
|
-
|
|
385
|
-
Variants can return more than just classes:
|
|
386
|
-
|
|
387
|
-
```typescript
|
|
388
|
-
variants: {
|
|
389
|
-
variant: {
|
|
390
|
-
destructive: {
|
|
391
|
-
class: 'bg-destructive text-destructive-foreground',
|
|
392
|
-
role: 'alert',
|
|
393
|
-
'aria-label': 'Destructive action',
|
|
394
|
-
'data-variant': 'destructive'
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
### 4. Preset Class + Variant Base
|
|
401
|
-
|
|
402
|
-
Use both for layered styling:
|
|
403
|
-
|
|
404
|
-
```typescript
|
|
405
|
-
setPreset({
|
|
406
|
-
button: () => ({
|
|
407
|
-
class: 'inline-flex items-center justify-center', // Always applied
|
|
408
|
-
variants: {
|
|
409
|
-
base: 'rounded-md transition-colors', // Variant base (can be overridden)
|
|
410
|
-
variants: {
|
|
411
|
-
/* ... */
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
})
|
|
415
|
-
});
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
**Final class order:**
|
|
419
|
-
|
|
420
|
-
1. `preset.class`
|
|
421
|
-
2. `preset.variants.base`
|
|
422
|
-
3. Local variant base (if overriding)
|
|
423
|
-
4. Variant classes
|
|
424
|
-
5. Component class prop
|
|
425
|
-
|
|
426
|
-
## Migration from Old System
|
|
427
|
-
|
|
428
|
-
### Before (Old Function-based)
|
|
429
|
-
|
|
430
|
-
```svelte
|
|
431
|
-
<script>
|
|
432
|
-
const variants = (bond, props) => {
|
|
433
|
-
const { variant, size } = props;
|
|
434
|
-
const classes = [];
|
|
435
|
-
|
|
436
|
-
if (variant === 'primary') classes.push('bg-blue-500');
|
|
437
|
-
if (size === 'sm') classes.push('px-2 py-1');
|
|
438
|
-
|
|
439
|
-
return { class: classes.join(' ') };
|
|
440
|
-
};
|
|
441
|
-
</script>
|
|
442
|
-
|
|
443
|
-
<HtmlAtom {variants} {variant} {size} />
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
### After (New Variant System)
|
|
447
|
-
|
|
448
|
-
```typescript
|
|
449
|
-
// In preset (recommended)
|
|
450
|
-
setPreset({
|
|
451
|
-
button: () => ({
|
|
452
|
-
variants: {
|
|
453
|
-
variants: {
|
|
454
|
-
variant: {
|
|
455
|
-
primary: 'bg-blue-500'
|
|
456
|
-
},
|
|
457
|
-
size: {
|
|
458
|
-
sm: 'px-2 py-1'
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
})
|
|
463
|
-
});
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
```svelte
|
|
467
|
-
<HtmlAtom preset="button" {variant} {size} />
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
**OR** local only:
|
|
471
|
-
|
|
472
|
-
```svelte
|
|
473
|
-
<script>
|
|
474
|
-
import { defineVariants } from '@svelte-atoms/core/utils';
|
|
475
|
-
|
|
476
|
-
const buttonVariants = defineVariants({
|
|
477
|
-
variants: {
|
|
478
|
-
variant: { primary: 'bg-blue-500' },
|
|
479
|
-
size: { sm: 'px-2 py-1' }
|
|
480
|
-
}
|
|
481
|
-
});
|
|
482
|
-
</script>
|
|
483
|
-
|
|
484
|
-
<HtmlAtom variants={buttonVariants} {variant} {size} />
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
## Best Practices
|
|
488
|
-
|
|
489
|
-
### ✅ DO
|
|
490
|
-
|
|
491
|
-
1. **Use presets for global variants** that should be consistent across the app
|
|
492
|
-
2. **Use local variants** to extend or override for special cases
|
|
493
|
-
3. **Use `class` prop in preset** for base styling that always applies
|
|
494
|
-
4. **Use `variants.base`** for styling that can be overridden locally
|
|
495
|
-
5. **Return attributes from variants** (aria-_, data-_, role) for accessibility
|
|
496
|
-
|
|
497
|
-
### ❌ DON'T
|
|
498
|
-
|
|
499
|
-
1. **Don't duplicate variants** in both preset and local unless overriding
|
|
500
|
-
2. **Don't use `base` prop for CSS classes** (conflicts with component/snippet prop)
|
|
501
|
-
3. **Don't over-nest presets** - keep hierarchy shallow
|
|
502
|
-
4. **Don't forget default variants** - they make components easier to use
|
|
503
|
-
|
|
504
|
-
## Summary
|
|
505
|
-
|
|
506
|
-
The preset-variant integration provides:
|
|
507
|
-
|
|
508
|
-
✅ **Global theming** via preset system
|
|
509
|
-
✅ **Local customization** via component variants
|
|
510
|
-
✅ **Intelligent merging** that respects hierarchy
|
|
511
|
-
✅ **Type safety** with TypeScript
|
|
512
|
-
✅ **Reactive variants** with bond state access
|
|
513
|
-
✅ **Attribute support** beyond just classes
|
|
514
|
-
✅ **Backward compatible** with function-based variants
|
|
515
|
-
|
|
516
|
-
This architecture gives you the flexibility of both global consistency and local control.
|
|
1
|
+
# Preset-Variant Integration
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The variant system is deeply integrated with the preset system in @svelte-atoms/core, providing a powerful theming architecture that combines:
|
|
6
|
+
|
|
7
|
+
- **Global variants** via presets (app-level theming)
|
|
8
|
+
- **Local variants** via component props (component-level customization)
|
|
9
|
+
- **Intelligent merging** that respects the hierarchy
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
┌─────────────────────────────────────────────────────┐
|
|
15
|
+
│ Theme Layer (Preset System) │
|
|
16
|
+
│ │
|
|
17
|
+
│ setPreset({ │
|
|
18
|
+
│ button: () => ({ │
|
|
19
|
+
│ class: 'font-medium', // Base styling │
|
|
20
|
+
│ variants: { // Global variant defs │
|
|
21
|
+
│ base: 'rounded-md', │
|
|
22
|
+
│ variants: { │
|
|
23
|
+
│ variant: { primary: '...', secondary: '...' }│
|
|
24
|
+
│ size: { sm: '...', md: '...', lg: '...' } │
|
|
25
|
+
│ } │
|
|
26
|
+
│ } │
|
|
27
|
+
│ }) │
|
|
28
|
+
│ }) │
|
|
29
|
+
└─────────────────────────────────────────────────────┘
|
|
30
|
+
↓
|
|
31
|
+
[MERGE STRATEGY]
|
|
32
|
+
↓
|
|
33
|
+
┌─────────────────────────────────────────────────────┐
|
|
34
|
+
│ Component Layer (Local Variants) │
|
|
35
|
+
│ │
|
|
36
|
+
│ <HtmlAtom │
|
|
37
|
+
│ preset="button" │
|
|
38
|
+
│ variants={localVariants} // Overrides/extends │
|
|
39
|
+
│ variant="primary" │
|
|
40
|
+
│ size="lg" │
|
|
41
|
+
│ /> │
|
|
42
|
+
└─────────────────────────────────────────────────────┘
|
|
43
|
+
↓
|
|
44
|
+
[RESOLUTION]
|
|
45
|
+
↓
|
|
46
|
+
┌─────────────────────────────────────────────────────┐
|
|
47
|
+
│ Final Output │
|
|
48
|
+
│ │
|
|
49
|
+
│ class: merged classes from preset + local + props │
|
|
50
|
+
│ attributes: aria-*, data-*, role, etc. │
|
|
51
|
+
└─────────────────────────────────────────────────────┘
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Merge Strategy
|
|
55
|
+
|
|
56
|
+
### 1. Variant Definition Merging
|
|
57
|
+
|
|
58
|
+
When both preset and component define variants, they merge as follows:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
{
|
|
62
|
+
base: localVariants.base ?? presetVariants.base,
|
|
63
|
+
|
|
64
|
+
variants: merge(
|
|
65
|
+
presetVariants.variants ?? {},
|
|
66
|
+
localVariants.variants ?? {}
|
|
67
|
+
),
|
|
68
|
+
|
|
69
|
+
compoundVariants: [
|
|
70
|
+
...(presetVariants.compoundVariants ?? []),
|
|
71
|
+
...(localVariants.compoundVariants ?? [])
|
|
72
|
+
],
|
|
73
|
+
|
|
74
|
+
defaultVariants: merge(
|
|
75
|
+
presetVariants.defaultVariants ?? {},
|
|
76
|
+
localVariants.defaultVariants ?? {}
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Rules:**
|
|
82
|
+
|
|
83
|
+
- Local `base` overrides preset `base`
|
|
84
|
+
- Local variants **merge** with preset variants (not replace)
|
|
85
|
+
- Compound variants from both are **concatenated**
|
|
86
|
+
- Default variants **merge** (local overrides preset)
|
|
87
|
+
|
|
88
|
+
### 2. Class Resolution Order
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
Final Class = [
|
|
92
|
+
preset.class, // 1. Preset base class
|
|
93
|
+
preset.variants.base, // 2. Preset variant base
|
|
94
|
+
mergedVariants.base, // 3. Merged variant base (local overrides)
|
|
95
|
+
variantClasses, // 4. Resolved variant classes
|
|
96
|
+
compoundClasses, // 5. Compound variant classes
|
|
97
|
+
component.class // 6. Component class prop (highest priority)
|
|
98
|
+
]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 3. Props Merging
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
{
|
|
105
|
+
...preset (excluding: class, base, as, variants),
|
|
106
|
+
...variantAttributes (aria-*, data-*, role, etc.),
|
|
107
|
+
...componentProps (user-provided props - highest priority)
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Usage Patterns
|
|
112
|
+
|
|
113
|
+
### Pattern 1: Pure Preset (No Local Variants)
|
|
114
|
+
|
|
115
|
+
**Best for:** Consistent components that don't need customization
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// Theme.svelte
|
|
119
|
+
setPreset({
|
|
120
|
+
badge: () => ({
|
|
121
|
+
variants: {
|
|
122
|
+
base: 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold',
|
|
123
|
+
variants: {
|
|
124
|
+
variant: {
|
|
125
|
+
default: 'bg-primary text-primary-foreground',
|
|
126
|
+
secondary: 'bg-secondary text-secondary-foreground',
|
|
127
|
+
destructive: 'bg-destructive text-destructive-foreground',
|
|
128
|
+
outline: 'border border-input'
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
defaultVariants: {
|
|
132
|
+
variant: 'default'
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
```svelte
|
|
140
|
+
<!-- Badge.svelte -->
|
|
141
|
+
<HtmlAtom preset="badge" {variant} {...props}>
|
|
142
|
+
{@render children?.()}
|
|
143
|
+
</HtmlAtom>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Result:** Uses 100% preset variants, no local customization
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
### Pattern 2: Preset + Local Extension
|
|
151
|
+
|
|
152
|
+
**Best for:** Components that need additional variants beyond theme
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// Theme.svelte
|
|
156
|
+
setPreset({
|
|
157
|
+
button: () => ({
|
|
158
|
+
variants: {
|
|
159
|
+
base: 'rounded-md font-medium',
|
|
160
|
+
variants: {
|
|
161
|
+
variant: {
|
|
162
|
+
default: 'bg-primary text-primary-foreground',
|
|
163
|
+
secondary: 'bg-secondary text-secondary-foreground'
|
|
164
|
+
},
|
|
165
|
+
size: {
|
|
166
|
+
sm: 'h-8 px-3',
|
|
167
|
+
md: 'h-10 px-4',
|
|
168
|
+
lg: 'h-12 px-6'
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
defaultVariants: {
|
|
172
|
+
variant: 'default',
|
|
173
|
+
size: 'md'
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
```svelte
|
|
181
|
+
<!-- IconButton.svelte -->
|
|
182
|
+
<script>
|
|
183
|
+
import { defineVariants } from '@svelte-atoms/core/utils';
|
|
184
|
+
|
|
185
|
+
// Extend preset with icon-specific variants
|
|
186
|
+
const iconVariants = defineVariants({
|
|
187
|
+
variants: {
|
|
188
|
+
// Add new variant key not in preset
|
|
189
|
+
iconPosition: {
|
|
190
|
+
left: 'flex-row',
|
|
191
|
+
right: 'flex-row-reverse',
|
|
192
|
+
top: 'flex-col',
|
|
193
|
+
bottom: 'flex-col-reverse'
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
defaultVariants: {
|
|
197
|
+
iconPosition: 'left'
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
</script>
|
|
201
|
+
|
|
202
|
+
<HtmlAtom preset="button" variants={iconVariants} {variant} {size} {iconPosition} {...props}>
|
|
203
|
+
{@render children?.()}
|
|
204
|
+
</HtmlAtom>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Result:** Gets `variant` and `size` from preset, adds `iconPosition` locally
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### Pattern 3: Preset Override
|
|
212
|
+
|
|
213
|
+
**Best for:** Special cases that need to completely override preset variants
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
// Theme.svelte
|
|
217
|
+
setPreset({
|
|
218
|
+
button: () => ({
|
|
219
|
+
variants: {
|
|
220
|
+
base: 'rounded-md',
|
|
221
|
+
variants: {
|
|
222
|
+
variant: {
|
|
223
|
+
default: 'bg-primary text-primary-foreground',
|
|
224
|
+
destructive: 'bg-destructive text-destructive-foreground'
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
```svelte
|
|
233
|
+
<!-- GradientButton.svelte -->
|
|
234
|
+
<script>
|
|
235
|
+
import { defineVariants } from '@svelte-atoms/core/utils';
|
|
236
|
+
|
|
237
|
+
// Override preset variants completely
|
|
238
|
+
const gradientVariants = defineVariants({
|
|
239
|
+
base: 'rounded-full', // Overrides preset base
|
|
240
|
+
variants: {
|
|
241
|
+
variant: {
|
|
242
|
+
// Overrides preset variants
|
|
243
|
+
purple: 'bg-gradient-to-r from-purple-500 to-pink-500',
|
|
244
|
+
blue: 'bg-gradient-to-r from-blue-500 to-cyan-500',
|
|
245
|
+
green: 'bg-gradient-to-r from-green-500 to-emerald-500'
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
defaultVariants: {
|
|
249
|
+
variant: 'purple'
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
</script>
|
|
253
|
+
|
|
254
|
+
<HtmlAtom preset="button" variants={gradientVariants} {variant} {...props}>
|
|
255
|
+
{@render children?.()}
|
|
256
|
+
</HtmlAtom>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Result:** Local variants completely replace preset variants for matching keys
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
### Pattern 4: Pure Local (No Preset)
|
|
264
|
+
|
|
265
|
+
**Best for:** One-off components that don't need global theming
|
|
266
|
+
|
|
267
|
+
```svelte
|
|
268
|
+
<script>
|
|
269
|
+
import { defineVariants } from '@svelte-atoms/core/utils';
|
|
270
|
+
|
|
271
|
+
const customVariants = defineVariants({
|
|
272
|
+
base: 'custom-base-class',
|
|
273
|
+
variants: {
|
|
274
|
+
custom: {
|
|
275
|
+
a: 'class-a',
|
|
276
|
+
b: 'class-b'
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
</script>
|
|
281
|
+
|
|
282
|
+
<HtmlAtom variants={customVariants} custom="a" {...props}>
|
|
283
|
+
{@render children?.()}
|
|
284
|
+
</HtmlAtom>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Result:** No preset used, 100% local variant definition
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### Pattern 5: Dynamic Variants with Bond
|
|
292
|
+
|
|
293
|
+
**Best for:** Reactive variants that change based on component state
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
// Theme.svelte
|
|
297
|
+
setPreset({
|
|
298
|
+
accordion: () => ({
|
|
299
|
+
variants: {
|
|
300
|
+
base: 'border rounded-md',
|
|
301
|
+
variants: {
|
|
302
|
+
state: {
|
|
303
|
+
// Function receives bond for reactive styling
|
|
304
|
+
open: (bond) => ({
|
|
305
|
+
class: bond?.state?.isOpen ? 'bg-accent' : 'bg-background',
|
|
306
|
+
'aria-expanded': bond?.state?.isOpen,
|
|
307
|
+
'data-state': bond?.state?.isOpen ? 'open' : 'closed'
|
|
308
|
+
})
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
})
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
```svelte
|
|
317
|
+
<!-- Accordion.svelte -->
|
|
318
|
+
<script>
|
|
319
|
+
import { AccordionBond } from './bond.svelte';
|
|
320
|
+
|
|
321
|
+
const bond = new AccordionBond(state).share();
|
|
322
|
+
</script>
|
|
323
|
+
|
|
324
|
+
<HtmlAtom preset="accordion" {bond} state="open" {...props}>
|
|
325
|
+
{@render children?.({ accordion: bond })}
|
|
326
|
+
</HtmlAtom>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Result:** Variants reactively update when `bond.state.isOpen` changes
|
|
330
|
+
|
|
331
|
+
## Advanced Features
|
|
332
|
+
|
|
333
|
+
### 1. Nested Preset Keys
|
|
334
|
+
|
|
335
|
+
Organize related components with dot notation:
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
setPreset({
|
|
339
|
+
card: () => ({
|
|
340
|
+
/* ... */
|
|
341
|
+
}),
|
|
342
|
+
'card.header': () => ({
|
|
343
|
+
/* ... */
|
|
344
|
+
}),
|
|
345
|
+
'card.body': () => ({
|
|
346
|
+
/* ... */
|
|
347
|
+
}),
|
|
348
|
+
'card.footer': () => ({
|
|
349
|
+
/* ... */
|
|
350
|
+
})
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
```svelte
|
|
355
|
+
<HtmlAtom preset="card.header" />
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### 2. Compound Variants
|
|
359
|
+
|
|
360
|
+
Apply classes when multiple conditions match:
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
setPreset({
|
|
364
|
+
button: () => ({
|
|
365
|
+
variants: {
|
|
366
|
+
variants: {
|
|
367
|
+
variant: { default: '...', destructive: '...' },
|
|
368
|
+
size: { sm: '...', lg: '...' }
|
|
369
|
+
},
|
|
370
|
+
compoundVariants: [
|
|
371
|
+
{
|
|
372
|
+
variant: 'destructive',
|
|
373
|
+
size: 'lg',
|
|
374
|
+
class: 'font-bold uppercase', // Applied ONLY when both match
|
|
375
|
+
'aria-label': 'Warning'
|
|
376
|
+
}
|
|
377
|
+
]
|
|
378
|
+
}
|
|
379
|
+
})
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### 3. Variant Attributes
|
|
384
|
+
|
|
385
|
+
Variants can return more than just classes:
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
variants: {
|
|
389
|
+
variant: {
|
|
390
|
+
destructive: {
|
|
391
|
+
class: 'bg-destructive text-destructive-foreground',
|
|
392
|
+
role: 'alert',
|
|
393
|
+
'aria-label': 'Destructive action',
|
|
394
|
+
'data-variant': 'destructive'
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### 4. Preset Class + Variant Base
|
|
401
|
+
|
|
402
|
+
Use both for layered styling:
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
setPreset({
|
|
406
|
+
button: () => ({
|
|
407
|
+
class: 'inline-flex items-center justify-center', // Always applied
|
|
408
|
+
variants: {
|
|
409
|
+
base: 'rounded-md transition-colors', // Variant base (can be overridden)
|
|
410
|
+
variants: {
|
|
411
|
+
/* ... */
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
})
|
|
415
|
+
});
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**Final class order:**
|
|
419
|
+
|
|
420
|
+
1. `preset.class`
|
|
421
|
+
2. `preset.variants.base`
|
|
422
|
+
3. Local variant base (if overriding)
|
|
423
|
+
4. Variant classes
|
|
424
|
+
5. Component class prop
|
|
425
|
+
|
|
426
|
+
## Migration from Old System
|
|
427
|
+
|
|
428
|
+
### Before (Old Function-based)
|
|
429
|
+
|
|
430
|
+
```svelte
|
|
431
|
+
<script>
|
|
432
|
+
const variants = (bond, props) => {
|
|
433
|
+
const { variant, size } = props;
|
|
434
|
+
const classes = [];
|
|
435
|
+
|
|
436
|
+
if (variant === 'primary') classes.push('bg-blue-500');
|
|
437
|
+
if (size === 'sm') classes.push('px-2 py-1');
|
|
438
|
+
|
|
439
|
+
return { class: classes.join(' ') };
|
|
440
|
+
};
|
|
441
|
+
</script>
|
|
442
|
+
|
|
443
|
+
<HtmlAtom {variants} {variant} {size} />
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### After (New Variant System)
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
// In preset (recommended)
|
|
450
|
+
setPreset({
|
|
451
|
+
button: () => ({
|
|
452
|
+
variants: {
|
|
453
|
+
variants: {
|
|
454
|
+
variant: {
|
|
455
|
+
primary: 'bg-blue-500'
|
|
456
|
+
},
|
|
457
|
+
size: {
|
|
458
|
+
sm: 'px-2 py-1'
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
});
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
```svelte
|
|
467
|
+
<HtmlAtom preset="button" {variant} {size} />
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**OR** local only:
|
|
471
|
+
|
|
472
|
+
```svelte
|
|
473
|
+
<script>
|
|
474
|
+
import { defineVariants } from '@svelte-atoms/core/utils';
|
|
475
|
+
|
|
476
|
+
const buttonVariants = defineVariants({
|
|
477
|
+
variants: {
|
|
478
|
+
variant: { primary: 'bg-blue-500' },
|
|
479
|
+
size: { sm: 'px-2 py-1' }
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
</script>
|
|
483
|
+
|
|
484
|
+
<HtmlAtom variants={buttonVariants} {variant} {size} />
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
## Best Practices
|
|
488
|
+
|
|
489
|
+
### ✅ DO
|
|
490
|
+
|
|
491
|
+
1. **Use presets for global variants** that should be consistent across the app
|
|
492
|
+
2. **Use local variants** to extend or override for special cases
|
|
493
|
+
3. **Use `class` prop in preset** for base styling that always applies
|
|
494
|
+
4. **Use `variants.base`** for styling that can be overridden locally
|
|
495
|
+
5. **Return attributes from variants** (aria-_, data-_, role) for accessibility
|
|
496
|
+
|
|
497
|
+
### ❌ DON'T
|
|
498
|
+
|
|
499
|
+
1. **Don't duplicate variants** in both preset and local unless overriding
|
|
500
|
+
2. **Don't use `base` prop for CSS classes** (conflicts with component/snippet prop)
|
|
501
|
+
3. **Don't over-nest presets** - keep hierarchy shallow
|
|
502
|
+
4. **Don't forget default variants** - they make components easier to use
|
|
503
|
+
|
|
504
|
+
## Summary
|
|
505
|
+
|
|
506
|
+
The preset-variant integration provides:
|
|
507
|
+
|
|
508
|
+
✅ **Global theming** via preset system
|
|
509
|
+
✅ **Local customization** via component variants
|
|
510
|
+
✅ **Intelligent merging** that respects hierarchy
|
|
511
|
+
✅ **Type safety** with TypeScript
|
|
512
|
+
✅ **Reactive variants** with bond state access
|
|
513
|
+
✅ **Attribute support** beyond just classes
|
|
514
|
+
✅ **Backward compatible** with function-based variants
|
|
515
|
+
|
|
516
|
+
This architecture gives you the flexibility of both global consistency and local control.
|