@marianmeres/stuic 2.66.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +292 -4
  2. package/dist/README.md +41 -18
  3. package/dist/actions/popover/README.md +19 -0
  4. package/dist/actions/popover/index.css +6 -9
  5. package/dist/actions/popover/popover.svelte.js +2 -2
  6. package/dist/actions/tooltip/README.md +18 -0
  7. package/dist/actions/tooltip/index.css +5 -8
  8. package/dist/actions/tooltip/tooltip.svelte.js +1 -1
  9. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +9 -10
  10. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +3 -3
  11. package/dist/components/AlertConfirmPrompt/Current.svelte +15 -17
  12. package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +5 -3
  13. package/dist/components/AlertConfirmPrompt/acp-icons.js +5 -4
  14. package/dist/components/AlertConfirmPrompt/index.css +62 -0
  15. package/dist/components/AssetsPreview/AssetsPreview.svelte +92 -73
  16. package/dist/components/AssetsPreview/AssetsPreview.svelte.d.ts +1 -0
  17. package/dist/components/AssetsPreview/index.css +59 -0
  18. package/dist/components/Avatar/Avatar.svelte +32 -18
  19. package/dist/components/Avatar/Avatar.svelte.d.ts +1 -0
  20. package/dist/components/Avatar/README.md +166 -0
  21. package/dist/components/Avatar/index.css +128 -0
  22. package/dist/components/Backdrop/Backdrop.svelte +8 -2
  23. package/dist/components/Backdrop/Backdrop.svelte.d.ts +1 -0
  24. package/dist/components/Backdrop/README.md +71 -6
  25. package/dist/components/Backdrop/index.css +29 -0
  26. package/dist/components/Button/Button.svelte +117 -124
  27. package/dist/components/Button/Button.svelte.d.ts +35 -23
  28. package/dist/components/Button/README.md +87 -21
  29. package/dist/components/Button/index.css +473 -9
  30. package/dist/components/Button/index.d.ts +1 -1
  31. package/dist/components/Button/index.js +1 -1
  32. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte +7 -38
  33. package/dist/components/ButtonGroupRadio/README.md +82 -4
  34. package/dist/components/ButtonGroupRadio/index.css +152 -14
  35. package/dist/components/Collapsible/Collapsible.svelte +7 -7
  36. package/dist/components/Collapsible/Collapsible.svelte.d.ts +2 -2
  37. package/dist/components/Collapsible/README.md +34 -2
  38. package/dist/components/Collapsible/index.css +38 -0
  39. package/dist/components/CommandMenu/CommandMenu.svelte +13 -24
  40. package/dist/components/CommandMenu/README.md +39 -0
  41. package/dist/components/CommandMenu/index.css +45 -2
  42. package/dist/components/DismissibleMessage/DismissibleMessage.svelte +53 -50
  43. package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +6 -5
  44. package/dist/components/DismissibleMessage/README.md +93 -11
  45. package/dist/components/DismissibleMessage/index.css +122 -8
  46. package/dist/components/DismissibleMessage/index.d.ts +1 -1
  47. package/dist/components/DropdownMenu/DropdownMenu.svelte +14 -50
  48. package/dist/components/DropdownMenu/DropdownMenu.svelte.d.ts +6 -6
  49. package/dist/components/DropdownMenu/README.md +132 -0
  50. package/dist/components/DropdownMenu/index.css +231 -27
  51. package/dist/components/Input/FieldAssets.svelte +8 -5
  52. package/dist/components/Input/FieldCheckbox.svelte +7 -44
  53. package/dist/components/Input/FieldFile.svelte +1 -6
  54. package/dist/components/Input/FieldInput.svelte +1 -1
  55. package/dist/components/Input/FieldOptions.svelte +41 -38
  56. package/dist/components/Input/FieldRadios.svelte +7 -16
  57. package/dist/components/Input/FieldSelect.svelte +1 -1
  58. package/dist/components/Input/FieldSwitch.svelte +1 -5
  59. package/dist/components/Input/FieldTextarea.svelte +1 -1
  60. package/dist/components/Input/README.md +194 -0
  61. package/dist/components/Input/_internal/FieldRadioInternal.svelte +2 -40
  62. package/dist/components/Input/_internal/InputWrap.svelte +8 -48
  63. package/dist/components/Input/index.css +522 -127
  64. package/dist/components/ListItemButton/ListItemButton.svelte +37 -73
  65. package/dist/components/ListItemButton/ListItemButton.svelte.d.ts +1 -9
  66. package/dist/components/ListItemButton/README.md +100 -45
  67. package/dist/components/ListItemButton/index.css +175 -56
  68. package/dist/components/ListItemButton/index.d.ts +1 -1
  69. package/dist/components/ListItemButton/index.js +1 -1
  70. package/dist/components/Modal/Modal.svelte +2 -8
  71. package/dist/components/Modal/Modal.svelte.d.ts +1 -0
  72. package/dist/components/Modal/README.md +29 -0
  73. package/dist/components/Modal/index.css +36 -0
  74. package/dist/components/ModalDialog/ModalDialog.svelte +2 -21
  75. package/dist/components/ModalDialog/README.md +35 -0
  76. package/dist/components/ModalDialog/index.css +57 -0
  77. package/dist/components/Notifications/Notifications.svelte +44 -128
  78. package/dist/components/Notifications/Notifications.svelte.d.ts +9 -17
  79. package/dist/components/Notifications/README.md +186 -70
  80. package/dist/components/Notifications/index.css +212 -15
  81. package/dist/components/Progress/README.md +15 -0
  82. package/dist/components/Progress/_internal/Bar.svelte +2 -2
  83. package/dist/components/Progress/index.css +4 -4
  84. package/dist/components/Skeleton/Skeleton.svelte +3 -2
  85. package/dist/components/Skeleton/index.css +11 -14
  86. package/dist/components/Spinner/Spinner.svelte +2 -2
  87. package/dist/components/Spinner/SpinnerCircle.svelte +1 -1
  88. package/dist/components/Switch/README.md +15 -0
  89. package/dist/components/Switch/Switch.svelte +4 -7
  90. package/dist/components/Switch/Switch.svelte.d.ts +1 -1
  91. package/dist/components/Switch/SwitchButton.svelte +4 -5
  92. package/dist/components/Switch/index.css +3 -4
  93. package/dist/components/TabbedMenu/README.md +26 -21
  94. package/dist/components/TabbedMenu/TabbedMenu.svelte +5 -5
  95. package/dist/components/TabbedMenu/index.css +7 -22
  96. package/dist/components/ThemePreview/README.md +289 -0
  97. package/dist/components/ThemePreview/ThemePreview.svelte +341 -0
  98. package/dist/components/ThemePreview/ThemePreview.svelte.d.ts +33 -0
  99. package/dist/components/ThemePreview/index.css +493 -0
  100. package/dist/components/ThemePreview/index.d.ts +1 -0
  101. package/dist/components/ThemePreview/index.js +1 -0
  102. package/dist/components/TwCheck/TwCheck.svelte +4 -4
  103. package/dist/components/TwCheck/index.css +3 -2
  104. package/dist/components/TypeaheadInput/TypeaheadInput.svelte +1 -1
  105. package/dist/components/X/X.svelte +12 -5
  106. package/dist/components/X/X.svelte.d.ts +1 -0
  107. package/dist/icons/index.d.ts +1 -0
  108. package/dist/icons/index.js +1 -0
  109. package/dist/index.css +31 -16
  110. package/dist/index.d.ts +1 -0
  111. package/dist/index.js +1 -0
  112. package/dist/themes/blue-orange.css +163 -0
  113. package/dist/themes/blue-orange.d.ts +6 -0
  114. package/dist/themes/blue-orange.js +151 -0
  115. package/dist/themes/cyan-red.css +163 -0
  116. package/dist/themes/cyan-red.d.ts +6 -0
  117. package/dist/themes/cyan-red.js +151 -0
  118. package/dist/themes/cyan-slate.css +163 -0
  119. package/dist/themes/cyan-slate.d.ts +6 -0
  120. package/dist/themes/cyan-slate.js +151 -0
  121. package/dist/themes/emerald-pink.css +163 -0
  122. package/dist/themes/emerald-pink.d.ts +6 -0
  123. package/dist/themes/emerald-pink.js +151 -0
  124. package/dist/themes/fuchsia-emerald.css +163 -0
  125. package/dist/themes/fuchsia-emerald.d.ts +6 -0
  126. package/dist/themes/fuchsia-emerald.js +151 -0
  127. package/dist/themes/gray.css +163 -0
  128. package/dist/themes/gray.d.ts +6 -0
  129. package/dist/themes/gray.js +151 -0
  130. package/dist/themes/indigo-amber.css +163 -0
  131. package/dist/themes/indigo-amber.d.ts +6 -0
  132. package/dist/themes/indigo-amber.js +151 -0
  133. package/dist/themes/neutral.css +163 -0
  134. package/dist/themes/neutral.d.ts +6 -0
  135. package/dist/themes/neutral.js +151 -0
  136. package/dist/themes/pink-emerald.css +163 -0
  137. package/dist/themes/pink-emerald.d.ts +6 -0
  138. package/dist/themes/pink-emerald.js +151 -0
  139. package/dist/themes/purple-yellow.css +163 -0
  140. package/dist/themes/purple-yellow.d.ts +6 -0
  141. package/dist/themes/purple-yellow.js +151 -0
  142. package/dist/themes/rainbow.css +163 -0
  143. package/dist/themes/rainbow.d.ts +6 -0
  144. package/dist/themes/rainbow.js +156 -0
  145. package/dist/themes/red-blue.css +163 -0
  146. package/dist/themes/red-blue.d.ts +6 -0
  147. package/dist/themes/red-blue.js +151 -0
  148. package/dist/themes/red-cyan.css +163 -0
  149. package/dist/themes/red-cyan.d.ts +6 -0
  150. package/dist/themes/red-cyan.js +151 -0
  151. package/dist/themes/rose-teal.css +163 -0
  152. package/dist/themes/rose-teal.d.ts +6 -0
  153. package/dist/themes/rose-teal.js +151 -0
  154. package/dist/themes/sky-amber.css +163 -0
  155. package/dist/themes/sky-amber.d.ts +6 -0
  156. package/dist/themes/sky-amber.js +151 -0
  157. package/dist/themes/slate-cyan.css +163 -0
  158. package/dist/themes/slate-cyan.d.ts +6 -0
  159. package/dist/themes/slate-cyan.js +151 -0
  160. package/dist/themes/tailwind-color-pairs.md +31 -0
  161. package/dist/themes/teal-rose.css +163 -0
  162. package/dist/themes/teal-rose.d.ts +6 -0
  163. package/dist/themes/teal-rose.js +151 -0
  164. package/dist/themes/violet-lime.css +163 -0
  165. package/dist/themes/violet-lime.d.ts +6 -0
  166. package/dist/themes/violet-lime.js +151 -0
  167. package/dist/utils/design-tokens.d.ts +43 -0
  168. package/dist/utils/design-tokens.js +100 -0
  169. package/dist/utils/index.d.ts +1 -0
  170. package/dist/utils/index.js +1 -0
  171. package/package.json +22 -2
@@ -107,6 +107,21 @@ A toggle switch component with size variants, keyboard support, and optional asy
107
107
  <Switch checked={false} disabled />
108
108
  ```
109
109
 
110
+ ## CSS Variables
111
+
112
+ | Variable | Default | Description |
113
+ |----------|---------|-------------|
114
+ | `--stuic-switch-accent` | `--stuic-accent` | Active (checked) color |
115
+
116
+ ### Example Override
117
+
118
+ ```css
119
+ :root {
120
+ /* Green switches globally */
121
+ --stuic-switch-accent: var(--color-green-500);
122
+ }
123
+ ```
124
+
110
125
  ## Keyboard Support
111
126
 
112
127
  - **Space**: Toggle switch
@@ -9,7 +9,7 @@
9
9
  export interface Props extends Omit<HTMLLabelAttributes, "children" | "onchange"> {
10
10
  button?: HTMLButtonElement;
11
11
  checked?: boolean;
12
- size?: "xs" | "sm" | "md" | "lg" | "xl" | string;
12
+ size?: "sm" | "md" | "lg" | "xl" | string;
13
13
  /** Form field name for the hidden checkbox */
14
14
  name?: string;
15
15
  class?: string;
@@ -42,7 +42,7 @@
42
42
 
43
43
  let {
44
44
  button = $bindable(),
45
- size = "md",
45
+ size = "lg",
46
46
  name,
47
47
  class: classProp,
48
48
  dotClass,
@@ -62,7 +62,6 @@
62
62
 
63
63
  const _preset: any = {
64
64
  size: {
65
- xs: `h-4 w-7`,
66
65
  sm: `h-5 w-9`,
67
66
  md: `h-6 w-11`,
68
67
  lg: `h-7 w-13`,
@@ -70,7 +69,6 @@
70
69
  },
71
70
  dot: {
72
71
  size: {
73
- xs: `size-2 data-[checked=true]:translate-x-4`,
74
72
  sm: `size-3 data-[checked=true]:translate-x-5`,
75
73
  md: `size-4 data-[checked=true]:translate-x-6`,
76
74
  lg: `size-5 data-[checked=true]:translate-x-7`,
@@ -107,11 +105,10 @@
107
105
 
108
106
  bg-neutral-400 dark:bg-neutral-400
109
107
 
110
- data-[checked=true]:bg-switch-accent
111
- dark:data-[checked=true]:bg-switch-accent-dark
108
+ data-[checked=true]:bg-(--stuic-switch-accent)
112
109
 
113
110
  focus:outline-0
114
- focus:ring-switch-accent/20 focus:dark:ring-switch-accent-dark/20
111
+ focus:ring-(--stuic-switch-accent)/20
115
112
  focus:ring-4`,
116
113
  size,
117
114
  _preset.size[size],
@@ -4,7 +4,7 @@ import type { ValidateOptions, ValidationResult } from "../../actions/validate.s
4
4
  export interface Props extends Omit<HTMLLabelAttributes, "children" | "onchange"> {
5
5
  button?: HTMLButtonElement;
6
6
  checked?: boolean;
7
- size?: "xs" | "sm" | "md" | "lg" | "xl" | string;
7
+ size?: "sm" | "md" | "lg" | "xl" | string;
8
8
  /** Form field name for the hidden checkbox */
9
9
  name?: string;
10
10
  class?: string;
@@ -76,12 +76,11 @@
76
76
  disabled:!cursor-not-allowed disabled:!opacity-50 disabled:hover:brightness-100
77
77
 
78
78
  bg-neutral-400 dark:bg-neutral-400
79
-
80
- aria-[checked=true]:bg-switch-accent
81
- dark:aria-[checked=true]:bg-switch-accent-dark
82
-
79
+
80
+ aria-[checked=true]:bg-(--stuic-switch-accent)
81
+
83
82
  focus:outline-0
84
- focus:ring-switch-accent/20 focus:dark:ring-switch-accent-dark/20
83
+ focus:ring-(--stuic-switch-accent)/20
85
84
  focus:ring-4`,
86
85
  size,
87
86
  _preset.size[size],
@@ -1,5 +1,4 @@
1
- /* prettier-ignore */
2
- @theme inline {
3
- --color-switch-accent: var(--color-switch-accent, var(--color-red-600));
4
- --color-switch-accent-dark: var(--color-switch-accent-dark, var(--color-red-400));
1
+ /* Switch component tokens */
2
+ :root {
3
+ --stuic-switch-accent: var(--stuic-color-primary);
5
4
  }
@@ -51,30 +51,35 @@ interface TabbedMenuItem {
51
51
 
52
52
  ## CSS Variables
53
53
 
54
+ Customize the component's appearance using CSS custom properties:
55
+
56
+ | Variable | Default | Description |
57
+ |----------|---------|-------------|
58
+ | `--stuic-tabbed-menu-tab-bg` | `--stuic-surface-sunken` | Tab background |
59
+ | `--stuic-tabbed-menu-tab-text` | `--stuic-text-muted` | Tab text color |
60
+ | `--stuic-tabbed-menu-tab-bg-active` | `--stuic-surface` | Active tab background |
61
+ | `--stuic-tabbed-menu-tab-text-active` | `--stuic-text` | Active tab text color |
62
+ | `--stuic-tabbed-menu-border` | `--stuic-border` | Border color |
63
+
64
+ ### Example Override
65
+
54
66
  ```css
55
- /* Tab button */
56
- --color-tabbed-menu-tab-bg
57
- --color-tabbed-menu-tab-bg-dark
58
- --color-tabbed-menu-tab-text
59
- --color-tabbed-menu-tab-text-dark
60
-
61
- /* Active tab */
62
- --color-tabbed-menu-tab-active-bg
63
- --color-tabbed-menu-tab-active-bg-dark
64
- --color-tabbed-menu-tab-active-text
65
- --color-tabbed-menu-tab-active-text-dark
66
-
67
- /* Border */
68
- --color-tabbed-menu-border
69
- --color-tabbed-menu-border-dark
70
-
71
- /* Sizing */
72
- --tabbed-menu-border-radius: 0.5rem
73
- --tabbed-menu-padding-x: 1rem
74
- --tabbed-menu-padding-y: 0.5rem
75
- --tabbed-menu-gap: 0.25rem
67
+ :root {
68
+ --stuic-tabbed-menu-tab-bg-active: var(--color-indigo-100);
69
+ --stuic-tabbed-menu-tab-text-active: var(--color-indigo-900);
70
+ }
76
71
  ```
77
72
 
73
+ ### Legacy Variables (Backwards Compatibility)
74
+
75
+ The following legacy variable names still work as aliases:
76
+
77
+ | Legacy Name | New Name |
78
+ |-------------|----------|
79
+ | `--color-tabbed-menu-tab-bg` | `--stuic-tabbed-menu-tab-bg` |
80
+ | `--color-tabbed-menu-tab-active-bg` | `--stuic-tabbed-menu-tab-bg-active` |
81
+ | `--color-tabbed-menu-border` | `--stuic-tabbed-menu-border` |
82
+
78
83
  ## Keyboard Navigation
79
84
 
80
85
  - `ArrowRight` / `ArrowDown` - Move to next tab
@@ -69,9 +69,9 @@
69
69
  px-4 py-2
70
70
  rounded-t-md
71
71
  border border-b-0
72
- border-tabbed-menu-border dark:border-tabbed-menu-border-dark
73
- bg-tabbed-menu-tab-bg dark:bg-tabbed-menu-tab-bg-dark
74
- text-tabbed-menu-tab-text dark:text-tabbed-menu-tab-text-dark
72
+ border-(--stuic-tabbed-menu-border)
73
+ bg-(--stuic-tabbed-menu-tab-bg)
74
+ text-(--stuic-tabbed-menu-tab-text)
75
75
  cursor-pointer
76
76
  transition-colors duration-150
77
77
  hover:brightness-105
@@ -82,8 +82,8 @@
82
82
  // focus-visible:outline-2 focus-visible:outline-offset-2
83
83
 
84
84
  const CLS_BUTTON_ACTIVE = `
85
- bg-tabbed-menu-tab-active-bg dark:bg-tabbed-menu-tab-active-bg-dark
86
- text-tabbed-menu-tab-active-text dark:text-tabbed-menu-tab-active-text-dark
85
+ bg-(--stuic-tabbed-menu-tab-bg-active)
86
+ text-(--stuic-tabbed-menu-tab-text-active)
87
87
  font-medium
88
88
  `;
89
89
 
@@ -1,23 +1,8 @@
1
- /* prettier-ignore */
2
- @theme inline {
3
- /* Tab button background */
4
- --color-tabbed-menu-tab-bg: var(--color-tabbed-menu-tab-bg, var(--color-neutral-100));
5
- --color-tabbed-menu-tab-bg-dark: var(--color-tabbed-menu-tab-bg-dark, var(--color-neutral-700));
6
-
7
- /* Tab button text */
8
- --color-tabbed-menu-tab-text: var(--color-tabbed-menu-tab-text, var(--color-neutral-600));
9
- --color-tabbed-menu-tab-text-dark: var(--color-tabbed-menu-tab-text-dark, var(--color-neutral-300));
10
-
11
- /* Active tab background */
12
- --color-tabbed-menu-tab-active-bg: var(--color-tabbed-menu-tab-active-bg, var(--color-white));
13
- --color-tabbed-menu-tab-active-bg-dark: var(--color-tabbed-menu-tab-active-bg-dark, var(--color-neutral-800));
14
-
15
- /* Active tab text */
16
- --color-tabbed-menu-tab-active-text: var(--color-tabbed-menu-tab-active-text, var(--color-neutral-900));
17
- --color-tabbed-menu-tab-active-text-dark: var(--color-tabbed-menu-tab-active-text-dark, var(--color-white));
18
-
19
- /* Border */
20
- --color-tabbed-menu-border: var(--color-tabbed-menu-border, var(--color-neutral-300));
21
- --color-tabbed-menu-border-dark: var(--color-tabbed-menu-border-dark, var(--color-neutral-600));
22
-
1
+ /* TabbedMenu component tokens */
2
+ :root {
3
+ --stuic-tabbed-menu-tab-bg: var(--stuic-color-muted);
4
+ --stuic-tabbed-menu-tab-text: var(--stuic-color-muted-foreground);
5
+ --stuic-tabbed-menu-tab-bg-active: var(--stuic-color-surface);
6
+ --stuic-tabbed-menu-tab-text-active: var(--stuic-color-foreground);
7
+ --stuic-tabbed-menu-border: var(--stuic-color-border);
23
8
  }
@@ -0,0 +1,289 @@
1
+ # ThemePreview
2
+
3
+ A comprehensive theme preview component that serves two purposes:
4
+
5
+ 1. **Visual Preview** - Shows all design tokens in action as a mini webpage layout
6
+ 2. **Reference Implementation** - Demonstrates theming best practices for creating components
7
+
8
+ ## Usage
9
+
10
+ ```svelte
11
+ <script lang="ts">
12
+ import { ThemePreview } from '@marianmeres/stuic';
13
+ </script>
14
+
15
+ <ThemePreview />
16
+ ```
17
+
18
+ ### Compact Mode
19
+
20
+ ```svelte
21
+ <ThemePreview compact showLabels={false} />
22
+ ```
23
+
24
+ ### Custom Sections
25
+
26
+ ```svelte
27
+ <ThemePreview>
28
+ {#snippet header()}
29
+ <h1>My Custom Theme</h1>
30
+ {/snippet}
31
+
32
+ {#snippet sidebar()}
33
+ <nav>Custom navigation...</nav>
34
+ {/snippet}
35
+ </ThemePreview>
36
+ ```
37
+
38
+ ## Props
39
+
40
+ | Prop | Type | Default | Description |
41
+ |------|------|---------|-------------|
42
+ | `showLabels` | `boolean` | `true` | Show section labels |
43
+ | `compact` | `boolean` | `false` | Reduced spacing |
44
+ | `showAllVariants` | `boolean` | `true` | Show all button variants |
45
+ | `showInputs` | `boolean` | `true` | Show input examples |
46
+ | `class` | `string` | - | Additional CSS classes |
47
+ | `el` | `HTMLDivElement` | - | Bindable element reference |
48
+ | `header` | `Snippet` | - | Custom header content |
49
+ | `sidebar` | `Snippet` | - | Custom sidebar content |
50
+ | `footer` | `Snippet` | - | Custom footer content |
51
+
52
+ ## Component Tokens
53
+
54
+ Override to customize appearance:
55
+
56
+ ```css
57
+ :root {
58
+ --stuic-theme-preview-radius: var(--radius-lg);
59
+ --stuic-theme-preview-gap: 2rem;
60
+ --stuic-theme-preview-transition: 200ms;
61
+ --stuic-theme-preview-sidebar-width: 250px;
62
+ }
63
+ ```
64
+
65
+ ---
66
+
67
+ # Theming Best Practices
68
+
69
+ This component demonstrates the patterns used throughout stuic. Follow these when creating new components.
70
+
71
+ ## 1. Theme Token Reference
72
+
73
+ ### Intent Colors
74
+
75
+ Communicate **purpose** and **meaning**:
76
+
77
+ | Token | Purpose |
78
+ |-------|---------|
79
+ | `--stuic-color-primary` | Main actions ("do this") |
80
+ | `--stuic-color-accent` | Highlights ("notice this") |
81
+ | `--stuic-color-destructive` | Dangerous/irreversible actions |
82
+ | `--stuic-color-warning` | Caution states |
83
+ | `--stuic-color-success` | Positive outcomes |
84
+ | `--stuic-color-info` | Neutral information |
85
+
86
+ Each intent has states and foregrounds:
87
+ - `--stuic-color-{intent}` - base color
88
+ - `--stuic-color-{intent}-hover` - hover state
89
+ - `--stuic-color-{intent}-active` - active/pressed state
90
+ - `--stuic-color-{intent}-foreground` - text on base
91
+ - `--stuic-color-{intent}-foreground-hover`
92
+ - `--stuic-color-{intent}-foreground-active`
93
+
94
+ ### Role Colors
95
+
96
+ Define **position** in the visual hierarchy:
97
+
98
+ | Token | Purpose |
99
+ |-------|---------|
100
+ | `--stuic-color-background` | Page background |
101
+ | `--stuic-color-foreground` | Primary text |
102
+ | `--stuic-color-surface` | Card/panel backgrounds |
103
+ | `--stuic-color-surface-foreground` | Text on surfaces |
104
+ | `--stuic-color-muted` | Subtle backgrounds |
105
+ | `--stuic-color-muted-foreground` | Secondary text |
106
+ | `--stuic-color-border` | Border color |
107
+ | `--stuic-color-input` | Input field backgrounds |
108
+ | `--stuic-color-ring` | Focus ring color |
109
+
110
+ ## 2. Internal Variable Pattern
111
+
112
+ The core theming technique in stuic separates **what colors to use** (intent) from **how to apply them** (variant).
113
+
114
+ ### Step 1: Intent Sets the Palette
115
+
116
+ ```css
117
+ .my-component[data-intent="primary"] {
118
+ --_color: var(--stuic-color-primary);
119
+ --_color-hover: var(--stuic-color-primary-hover);
120
+ --_color-active: var(--stuic-color-primary-active);
121
+ --_fg: var(--stuic-color-primary-foreground);
122
+ --_fg-hover: var(--stuic-color-primary-foreground-hover);
123
+ --_fg-active: var(--stuic-color-primary-foreground-active);
124
+ }
125
+ ```
126
+
127
+ ### Step 2: Variant Determines Application
128
+
129
+ ```css
130
+ /* Solid: filled background */
131
+ .my-component[data-variant="solid"] {
132
+ --_bg: var(--_color);
133
+ --_text: var(--_fg);
134
+ --_border: var(--_color);
135
+ }
136
+
137
+ /* Outline: transparent, colored border */
138
+ .my-component[data-variant="outline"] {
139
+ --_bg: transparent;
140
+ --_bg-hover: color-mix(in srgb, var(--_color) 10%, transparent);
141
+ --_text: var(--_color);
142
+ --_border: var(--_color);
143
+ }
144
+ ```
145
+
146
+ ### Step 3: Base Styles Consume Variables
147
+
148
+ ```css
149
+ .my-component {
150
+ background: var(--_bg);
151
+ color: var(--_text);
152
+ border-color: var(--_border);
153
+ }
154
+
155
+ .my-component:hover {
156
+ background: var(--_bg-hover);
157
+ color: var(--_text-hover);
158
+ border-color: var(--_border-hover);
159
+ }
160
+ ```
161
+
162
+ This pattern allows any intent + variant combination to work automatically.
163
+
164
+ ## 3. Foreground Pairing Convention
165
+
166
+ When using a background color, always use its paired foreground for text:
167
+
168
+ ```css
169
+ .card {
170
+ background: var(--stuic-color-surface);
171
+ color: var(--stuic-color-surface-foreground);
172
+ }
173
+
174
+ .muted-section {
175
+ background: var(--stuic-color-muted);
176
+ color: var(--stuic-color-muted-foreground);
177
+ }
178
+ ```
179
+
180
+ ## 4. Component Tokens
181
+
182
+ Define component-level tokens in `:root` for easy customization:
183
+
184
+ ```css
185
+ :root {
186
+ --stuic-my-component-radius: var(--radius-md);
187
+ --stuic-my-component-padding: 1rem;
188
+ --stuic-my-component-transition: 150ms;
189
+ }
190
+
191
+ .my-component {
192
+ border-radius: var(--stuic-my-component-radius);
193
+ padding: var(--stuic-my-component-padding);
194
+ transition: all var(--stuic-my-component-transition);
195
+ }
196
+ ```
197
+
198
+ Users can override globally or locally:
199
+ ```css
200
+ /* Global override */
201
+ :root {
202
+ --stuic-my-component-radius: 0;
203
+ }
204
+ ```
205
+
206
+ ```svelte
207
+ <!-- Local override -->
208
+ <MyComponent style="--stuic-my-component-radius: 999px;" />
209
+ ```
210
+
211
+ ## 5. State Handling
212
+
213
+ Always define hover and active states using theme tokens:
214
+
215
+ ```css
216
+ .element {
217
+ background: var(--stuic-color-surface);
218
+ }
219
+
220
+ .element:hover {
221
+ background: var(--stuic-color-surface-hover);
222
+ }
223
+
224
+ .element:active {
225
+ background: var(--stuic-color-surface-active);
226
+ }
227
+
228
+ .element:focus-visible {
229
+ outline: 3px solid var(--stuic-color-ring);
230
+ outline-offset: 2px;
231
+ }
232
+ ```
233
+
234
+ ## 6. Dark Mode
235
+
236
+ Themes handle dark mode via `:root.dark` selector. When using theme tokens properly, components don't need explicit dark mode styles - the theme handles everything.
237
+
238
+ ```css
239
+ /* Theme defines both modes */
240
+ :root {
241
+ --stuic-color-background: var(--color-white);
242
+ --stuic-color-foreground: var(--color-neutral-900);
243
+ }
244
+
245
+ :root.dark {
246
+ --stuic-color-background: var(--color-neutral-950);
247
+ --stuic-color-foreground: var(--color-neutral-100);
248
+ }
249
+
250
+ /* Component just uses tokens - works in both modes */
251
+ .my-component {
252
+ background: var(--stuic-color-background);
253
+ color: var(--stuic-color-foreground);
254
+ }
255
+ ```
256
+
257
+ ## 7. Accessibility
258
+
259
+ - Use `--stuic-color-ring` for focus indicators
260
+ - Ensure sufficient contrast between background and foreground pairs
261
+ - Respect reduced motion preferences:
262
+
263
+ ```css
264
+ @media (prefers-reduced-motion: reduce) {
265
+ .my-component {
266
+ transition: none;
267
+ }
268
+ }
269
+ ```
270
+
271
+ ## 8. Data Attributes
272
+
273
+ Use data attributes for styling variants instead of classes:
274
+
275
+ ```svelte
276
+ <button
277
+ data-intent={intent}
278
+ data-variant={variant}
279
+ data-size={size}
280
+ >
281
+ ```
282
+
283
+ ```css
284
+ .button[data-intent="primary"] { ... }
285
+ .button[data-variant="outline"] { ... }
286
+ .button[data-size="lg"] { ... }
287
+ ```
288
+
289
+ This keeps the class attribute clean for user customization via `class` prop.