@marianmeres/stuic 3.0.0 → 3.0.2

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 (156) hide show
  1. package/dist/actions/index.d.ts +1 -0
  2. package/dist/actions/index.js +1 -0
  3. package/dist/actions/typeahead.svelte.d.ts +53 -0
  4. package/dist/actions/typeahead.svelte.js +328 -0
  5. package/dist/base.css +17 -0
  6. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +4 -3
  7. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +4 -3
  8. package/dist/components/AlertConfirmPrompt/Current.svelte +1 -2
  9. package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +0 -1
  10. package/dist/components/AlertConfirmPrompt/index.css +47 -43
  11. package/dist/components/AssetsPreview/AssetsPreview.svelte +0 -1
  12. package/dist/components/AssetsPreview/AssetsPreview.svelte.d.ts +0 -1
  13. package/dist/components/AssetsPreview/index.css +31 -29
  14. package/dist/components/Avatar/Avatar.svelte +0 -1
  15. package/dist/components/Avatar/Avatar.svelte.d.ts +0 -1
  16. package/dist/components/Avatar/index.css +87 -85
  17. package/dist/components/Backdrop/Backdrop.svelte +0 -1
  18. package/dist/components/Backdrop/Backdrop.svelte.d.ts +0 -1
  19. package/dist/components/Backdrop/index.css +15 -13
  20. package/dist/components/Button/Button.svelte +0 -1
  21. package/dist/components/Button/Button.svelte.d.ts +0 -1
  22. package/dist/components/Button/index.css +431 -429
  23. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte +0 -1
  24. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte.d.ts +0 -1
  25. package/dist/components/ButtonGroupRadio/index.css +123 -117
  26. package/dist/components/Collapsible/index.css +17 -15
  27. package/dist/components/CommandMenu/CommandMenu.svelte +7 -4
  28. package/dist/components/CommandMenu/CommandMenu.svelte.d.ts +0 -1
  29. package/dist/components/CommandMenu/index.css +27 -25
  30. package/dist/components/DismissibleMessage/DismissibleMessage.svelte +0 -2
  31. package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +0 -1
  32. package/dist/components/DismissibleMessage/index.css +116 -110
  33. package/dist/components/DropdownMenu/DropdownMenu.svelte +317 -74
  34. package/dist/components/DropdownMenu/DropdownMenu.svelte.d.ts +19 -1
  35. package/dist/components/DropdownMenu/index.css +236 -170
  36. package/dist/components/DropdownMenu/index.d.ts +1 -1
  37. package/dist/components/HoverExpandableWidth/HoverExpandableWidth.svelte +3 -1
  38. package/dist/components/HoverExpandableWidth/HoverExpandableWidth.svelte.d.ts +1 -0
  39. package/dist/components/Input/FieldInput.svelte +8 -0
  40. package/dist/components/Input/FieldInput.svelte.d.ts +2 -0
  41. package/dist/components/Input/FieldOptions.svelte +1 -1
  42. package/dist/components/Input/index.css +411 -398
  43. package/dist/components/KbdShortcut/KbdShortcut.svelte +4 -12
  44. package/dist/components/KbdShortcut/README.md +34 -0
  45. package/dist/components/KbdShortcut/index.css +55 -0
  46. package/dist/components/ListItemButton/ListItemButton.svelte +0 -1
  47. package/dist/components/ListItemButton/ListItemButton.svelte.d.ts +0 -1
  48. package/dist/components/ListItemButton/index.css +118 -116
  49. package/dist/components/Modal/Modal.svelte +0 -1
  50. package/dist/components/Modal/Modal.svelte.d.ts +0 -1
  51. package/dist/components/Modal/index.css +18 -16
  52. package/dist/components/ModalDialog/index.css +29 -27
  53. package/dist/components/Nav/Nav.svelte +732 -0
  54. package/dist/components/Nav/Nav.svelte.d.ts +110 -0
  55. package/dist/components/Nav/README.md +334 -0
  56. package/dist/components/Nav/index.css +318 -0
  57. package/dist/components/Nav/index.d.ts +1 -0
  58. package/dist/components/Nav/index.js +1 -0
  59. package/dist/components/Notifications/Notifications.svelte +2 -3
  60. package/dist/components/Notifications/Notifications.svelte.d.ts +0 -1
  61. package/dist/components/Notifications/index.css +158 -158
  62. package/dist/components/Notifications/notifications-stack.svelte.d.ts +4 -0
  63. package/dist/components/Notifications/notifications-stack.svelte.js +8 -0
  64. package/dist/components/Progress/Progress.svelte +4 -2
  65. package/dist/components/Progress/Progress.svelte.d.ts +1 -0
  66. package/dist/components/Progress/README.md +86 -15
  67. package/dist/components/Progress/_internal/Bar.svelte +4 -15
  68. package/dist/components/Progress/_internal/Bar.svelte.d.ts +1 -1
  69. package/dist/components/Progress/_internal/Circle.svelte +30 -2
  70. package/dist/components/Progress/_internal/Circle.svelte.d.ts +1 -0
  71. package/dist/components/Progress/index.css +47 -1
  72. package/dist/components/Skeleton/README.md +152 -0
  73. package/dist/components/Skeleton/Skeleton.svelte +6 -7
  74. package/dist/components/Skeleton/Skeleton.svelte.d.ts +0 -1
  75. package/dist/components/Skeleton/index.css +73 -43
  76. package/dist/components/Spinner/README.md +149 -37
  77. package/dist/components/Spinner/Spinner.svelte +14 -38
  78. package/dist/components/Spinner/Spinner.svelte.d.ts +2 -1
  79. package/dist/components/Spinner/SpinnerCircle.svelte +6 -34
  80. package/dist/components/Spinner/SpinnerCircle.svelte.d.ts +1 -0
  81. package/dist/components/Spinner/SpinnerCircleOscillate.svelte +10 -5
  82. package/dist/components/Spinner/SpinnerUnicode.svelte +3 -1
  83. package/dist/components/Spinner/SpinnerUnicode.svelte.d.ts +1 -0
  84. package/dist/components/Spinner/index.css +104 -0
  85. package/dist/components/Switch/README.md +34 -18
  86. package/dist/components/Switch/Switch.svelte +24 -46
  87. package/dist/components/Switch/Switch.svelte.d.ts +4 -2
  88. package/dist/components/Switch/index.css +120 -2
  89. package/dist/components/Switch/index.d.ts +1 -2
  90. package/dist/components/Switch/index.js +1 -2
  91. package/dist/components/TabbedMenu/README.md +28 -17
  92. package/dist/components/TabbedMenu/TabbedMenu.svelte +5 -46
  93. package/dist/components/TabbedMenu/TabbedMenu.svelte.d.ts +0 -1
  94. package/dist/components/TabbedMenu/index.css +85 -3
  95. package/dist/components/ThemePreview/ThemePreview.svelte +86 -33
  96. package/dist/components/ThemePreview/ThemePreview.svelte.d.ts +3 -1
  97. package/dist/components/ThemePreview/index.css +24 -8
  98. package/dist/components/TwCheck/README.md +32 -13
  99. package/dist/components/TwCheck/TwCheck.svelte +11 -9
  100. package/dist/components/TwCheck/TwCheck.svelte.d.ts +0 -1
  101. package/dist/components/TwCheck/index.css +14 -0
  102. package/dist/components/TypeaheadInput/TypeaheadInput.svelte +19 -187
  103. package/dist/components/TypeaheadInput/TypeaheadInput.svelte.d.ts +4 -2
  104. package/dist/icons/index.d.ts +1 -0
  105. package/dist/icons/index.js +1 -0
  106. package/dist/index.css +44 -39
  107. package/dist/index.d.ts +1 -0
  108. package/dist/index.js +1 -0
  109. package/dist/themes/blue-orange.css +246 -156
  110. package/dist/themes/blue-orange.js +24 -0
  111. package/dist/themes/cyan-red.css +246 -156
  112. package/dist/themes/cyan-red.js +24 -0
  113. package/dist/themes/cyan-slate.css +246 -156
  114. package/dist/themes/cyan-slate.js +25 -1
  115. package/dist/themes/emerald-pink.css +246 -156
  116. package/dist/themes/emerald-pink.js +25 -1
  117. package/dist/themes/fuchsia-emerald.css +246 -156
  118. package/dist/themes/fuchsia-emerald.js +25 -1
  119. package/dist/themes/gray.css +246 -156
  120. package/dist/themes/gray.js +24 -0
  121. package/dist/themes/indigo-amber.css +246 -156
  122. package/dist/themes/indigo-amber.js +26 -2
  123. package/dist/themes/neutral.css +246 -156
  124. package/dist/themes/neutral.js +24 -0
  125. package/dist/themes/pink-emerald.css +246 -156
  126. package/dist/themes/pink-emerald.js +25 -1
  127. package/dist/themes/pink-teal.css +253 -0
  128. package/dist/themes/pink-teal.d.ts +6 -0
  129. package/dist/themes/pink-teal.js +175 -0
  130. package/dist/themes/purple-yellow.css +246 -156
  131. package/dist/themes/purple-yellow.js +24 -0
  132. package/dist/themes/rainbow.css +246 -156
  133. package/dist/themes/rainbow.js +25 -1
  134. package/dist/themes/red-blue.css +246 -156
  135. package/dist/themes/red-blue.js +24 -0
  136. package/dist/themes/red-cyan.css +246 -156
  137. package/dist/themes/red-cyan.js +24 -0
  138. package/dist/themes/red-sky.css +253 -0
  139. package/dist/themes/red-sky.d.ts +6 -0
  140. package/dist/themes/red-sky.js +175 -0
  141. package/dist/themes/rose-teal.css +246 -156
  142. package/dist/themes/rose-teal.js +24 -0
  143. package/dist/themes/sky-amber.css +246 -156
  144. package/dist/themes/sky-amber.js +26 -2
  145. package/dist/themes/slate-cyan.css +246 -156
  146. package/dist/themes/slate-cyan.js +25 -1
  147. package/dist/themes/teal-rose.css +246 -156
  148. package/dist/themes/teal-rose.js +24 -0
  149. package/dist/themes/violet-lime.css +246 -156
  150. package/dist/themes/violet-lime.js +27 -3
  151. package/dist/utils/design-tokens.d.ts +1 -1
  152. package/dist/utils/design-tokens.js +44 -3
  153. package/dist/utils/storage-abstraction.js +1 -1
  154. package/package.json +11 -28
  155. package/dist/components/Switch/SwitchButton.svelte +0 -134
  156. package/dist/components/Switch/SwitchButton.svelte.d.ts +0 -21
@@ -132,6 +132,10 @@ export declare class NotificationsStack {
132
132
  success: (content: THC, n?: Partial<NotificationInput>) => this | undefined;
133
133
  /** Main api. */
134
134
  warn: (content: THC, n?: Partial<NotificationInput>) => this | undefined;
135
+ /** "warn" alias */
136
+ warning: (content: THC, n?: Partial<NotificationInput>) => this | undefined;
135
137
  /** Main api. */
136
138
  error: (content: THC, n?: Partial<NotificationInput>) => this | undefined;
139
+ /** "error" alias */
140
+ destructive: (content: THC, n?: Partial<NotificationInput>) => this | undefined;
137
141
  }
@@ -182,8 +182,16 @@ export class NotificationsStack {
182
182
  warn = (content, n) => {
183
183
  return this.#add({ ...(n || {}), type: "warn", content });
184
184
  };
185
+ /** "warn" alias */
186
+ warning = (content, n) => {
187
+ return this.#add({ ...(n || {}), type: "warn", content });
188
+ };
185
189
  /** Main api. */
186
190
  error = (content, n) => {
187
191
  return this.#add({ ...(n || {}), type: "error", content });
188
192
  };
193
+ /** "error" alias */
194
+ destructive = (content, n) => {
195
+ return this.#add({ ...(n || {}), type: "error", content });
196
+ };
189
197
  }
@@ -3,6 +3,7 @@
3
3
  type?: "bar" | "circle";
4
4
  progress?: number;
5
5
  class?: string;
6
+ style?: string;
6
7
  classBar?: string;
7
8
  styleBar?: string;
8
9
  }
@@ -16,13 +17,14 @@
16
17
  type = "bar",
17
18
  progress = 0,
18
19
  class: classProp,
20
+ style: styleProp,
19
21
  classBar,
20
22
  styleBar,
21
23
  }: Props = $props();
22
24
  </script>
23
25
 
24
26
  {#if type === "bar"}
25
- <Bar {progress} class={classProp} {classBar} {styleBar} />
27
+ <Bar {progress} class={classProp} style={styleProp} {classBar} {styleBar} />
26
28
  {:else if type === "circle"}
27
- <Circle {progress} class={classProp} />
29
+ <Circle {progress} class={classProp} style={styleProp} />
28
30
  {/if}
@@ -2,6 +2,7 @@ export interface Props {
2
2
  type?: "bar" | "circle";
3
3
  progress?: number;
4
4
  class?: string;
5
+ style?: string;
5
6
  classBar?: string;
6
7
  styleBar?: string;
7
8
  }
@@ -8,9 +8,10 @@ A progress indicator available as either a horizontal bar or circular display.
8
8
  |------|------|---------|-------------|
9
9
  | `type` | `"bar" \| "circle"` | `"bar"` | Display type |
10
10
  | `progress` | `number` | `0` | Progress value (0-100) |
11
- | `class` | `string` | - | CSS for container |
12
- | `classBar` | `string` | - | CSS for progress bar fill (bar type only) |
13
- | `styleBar` | `string` | - | Inline styles for bar fill |
11
+ | `class` | `string` | - | CSS classes for container |
12
+ | `style` | `string` | - | Inline styles for container (use for CSS variable overrides) |
13
+ | `classBar` | `string` | - | CSS classes for bar fill (bar type only) |
14
+ | `styleBar` | `string` | - | Inline styles for bar fill (bar type only) |
14
15
 
15
16
  ## Usage
16
17
 
@@ -18,7 +19,7 @@ A progress indicator available as either a horizontal bar or circular display.
18
19
 
19
20
  ```svelte
20
21
  <script lang="ts">
21
- import { Progress } from 'stuic';
22
+ import { Progress } from '@marianmeres/stuic';
22
23
 
23
24
  let progress = $state(0);
24
25
  </script>
@@ -29,7 +30,7 @@ A progress indicator available as either a horizontal bar or circular display.
29
30
  ### Circle Progress
30
31
 
31
32
  ```svelte
32
- <Progress type="circle" progress={75} class="size-16" />
33
+ <Progress type="circle" progress={75} />
33
34
  ```
34
35
 
35
36
  ### Animated Progress
@@ -51,36 +52,106 @@ A progress indicator available as either a horizontal bar or circular display.
51
52
  <button onclick={start}>Start</button>
52
53
  ```
53
54
 
54
- ### Custom Styling
55
+ ### Custom Sizing
55
56
 
56
57
  ```svelte
58
+ <!-- Taller bar -->
57
59
  <Progress
58
60
  progress={60}
59
- class="h-2 bg-gray-200 rounded-full"
60
- classBar="bg-blue-500 rounded-full"
61
+ style="--stuic-progress-height: 1rem;"
62
+ />
63
+
64
+ <!-- Larger circle -->
65
+ <Progress
66
+ type="circle"
67
+ progress={75}
68
+ style="--stuic-progress-circle-size: 6rem;"
69
+ />
70
+ ```
71
+
72
+ ### Custom Colors
73
+
74
+ ```svelte
75
+ <!-- Override accent color inline -->
76
+ <Progress
77
+ progress={80}
78
+ style="--stuic-progress-accent: var(--stuic-color-success);"
79
+ />
80
+
81
+ <!-- Using Tailwind classes -->
82
+ <Progress
83
+ progress={60}
84
+ classBar="bg-green-500"
61
85
  />
62
86
  ```
63
87
 
64
- ### With Transition
88
+ ### With Border Radius
65
89
 
66
90
  ```svelte
67
91
  <Progress
68
- progress={value}
69
- classBar="transition-all duration-300"
92
+ progress={50}
93
+ style="--stuic-progress-radius: var(--radius-full);"
70
94
  />
71
95
  ```
72
96
 
73
97
  ## CSS Variables
74
98
 
99
+ ### Component Tokens
100
+
101
+ Override globally in `:root` or locally via `style` prop:
102
+
75
103
  | Variable | Default | Description |
76
104
  |----------|---------|-------------|
77
- | `--stuic-progress-bg` | `--stuic-surface-interactive` | Track background |
78
- | `--stuic-progress-accent` | `--stuic-accent` | Progress bar fill color |
105
+ | `--stuic-progress-bg` | `--stuic-color-muted` | Track background color |
106
+ | `--stuic-progress-accent` | `--stuic-color-primary` | Progress fill color |
107
+ | `--stuic-progress-height` | `calc(var(--spacing) * 2)` | Bar height (0.5rem) |
108
+ | `--stuic-progress-radius` | `--radius-sm` | Border radius |
109
+ | `--stuic-progress-transition` | `100ms` | Animation duration |
110
+ | `--stuic-progress-circle-size` | `calc(var(--spacing) * 16)` | Circle dimensions (4rem) |
111
+ | `--stuic-progress-circle-stroke-width` | `10` | Circle stroke width (viewBox units) |
79
112
 
80
- ### Example Override
113
+ ### Example Overrides
81
114
 
82
115
  ```css
116
+ /* Global override */
83
117
  :root {
84
- --stuic-progress-accent: var(--color-green-500);
118
+ --stuic-progress-accent: var(--stuic-color-accent);
119
+ --stuic-progress-height: calc(var(--spacing) * 3);
120
+ --stuic-progress-radius: var(--radius-full);
85
121
  }
86
122
  ```
123
+
124
+ ```svelte
125
+ <!-- Local override -->
126
+ <Progress
127
+ progress={75}
128
+ style="--stuic-progress-accent: var(--stuic-color-success); --stuic-progress-height: 1rem;"
129
+ />
130
+ ```
131
+
132
+ ## Theming
133
+
134
+ The component uses theme color tokens:
135
+ - `--stuic-color-muted` for the track background
136
+ - `--stuic-color-primary` for the progress fill
137
+
138
+ These automatically adapt to light/dark mode when using a properly configured theme.
139
+
140
+ To show different states (success, warning, error), override the accent color:
141
+
142
+ ```svelte
143
+ <Progress
144
+ progress={100}
145
+ style="--stuic-progress-accent: var(--stuic-color-success);"
146
+ />
147
+
148
+ <Progress
149
+ progress={90}
150
+ style="--stuic-progress-accent: var(--stuic-color-warning);"
151
+ />
152
+
153
+ <Progress
154
+ progress={50}
155
+ style="--stuic-progress-accent: var(--stuic-color-destructive);"
156
+ />
157
+ ```
@@ -1,31 +1,20 @@
1
1
  <script lang="ts">
2
2
  import { twMerge } from "../../../utils/tw-merge.js";
3
3
 
4
- import "../index.css";
5
-
6
4
  interface Props {
7
5
  progress: number;
8
6
  class?: string;
7
+ style?: string;
9
8
  classBar?: string;
10
9
  styleBar?: string;
11
10
  }
12
11
 
13
- let { progress = 0, class: classProp, classBar, styleBar = "" }: Props = $props();
12
+ let { progress = 0, class: classProp, style: styleProp, classBar, styleBar = "" }: Props = $props();
14
13
  </script>
15
14
 
16
- <div
17
- class={twMerge(
18
- "stuic-progress-bar",
19
- "w-full h-2 bg-(--stuic-progress-bg) flex justify-start pointer-events-none",
20
- classProp
21
- )}
22
- >
15
+ <div class={twMerge("stuic-progress-bar", classProp)} style={styleProp}>
23
16
  <div
24
- class={twMerge(
25
- "bar",
26
- "w-full h-full bg-(--stuic-progress-accent) transition-[width] ease-linear duration-100",
27
- classBar
28
- )}
17
+ class={twMerge("bar", classBar)}
29
18
  style="width:{Math.min(100, Math.max(0, progress))}%; {styleBar}"
30
19
  ></div>
31
20
  </div>
@@ -1,7 +1,7 @@
1
- import "../index.css";
2
1
  interface Props {
3
2
  progress: number;
4
3
  class?: string;
4
+ style?: string;
5
5
  classBar?: string;
6
6
  styleBar?: string;
7
7
  }
@@ -1,10 +1,38 @@
1
1
  <script lang="ts">
2
+ import { svgCircle } from "../../../utils/svg-circle.js";
3
+ import { twMerge } from "../../../utils/tw-merge.js";
4
+
2
5
  interface Props {
3
6
  progress: number;
4
7
  class?: string;
8
+ style?: string;
5
9
  }
6
10
 
7
- let { progress = 0, class: classProp }: Props = $props();
11
+ let { progress = 0, class: classProp, style: styleProp }: Props = $props();
12
+
13
+ let container: HTMLDivElement;
14
+ let circleApi: ReturnType<typeof svgCircle> | null = null;
15
+
16
+ // Create SVG once when container is mounted
17
+ $effect(() => {
18
+ if (container && !circleApi) {
19
+ circleApi = svgCircle({
20
+ completeness: Math.min(100, Math.max(0, progress)) / 100,
21
+ strokeWidth: 10, // in viewBox units (100x100)
22
+ bgStrokeColor: "var(--stuic-progress-bg)",
23
+ circleStyle:
24
+ "stroke: var(--stuic-progress-accent); transition: stroke-dashoffset var(--stuic-progress-transition) linear;",
25
+ roundedEdges: true,
26
+ rotate: -90, // start from top
27
+ });
28
+ container.appendChild(circleApi.svg);
29
+ }
30
+ });
31
+
32
+ // Update progress reactively
33
+ $effect(() => {
34
+ circleApi?.setCompleteness(Math.min(100, Math.max(0, progress)) / 100);
35
+ });
8
36
  </script>
9
37
 
10
- todo
38
+ <div bind:this={container} class={twMerge("stuic-progress-circle", classProp)} style={styleProp}></div>
@@ -1,6 +1,7 @@
1
1
  interface Props {
2
2
  progress: number;
3
3
  class?: string;
4
+ style?: string;
4
5
  }
5
6
  declare const Circle: import("svelte").Component<Props, {}, "">;
6
7
  type Circle = ReturnType<typeof Circle>;
@@ -1,5 +1,51 @@
1
- /* Progress component tokens */
1
+ /* ============================================================================
2
+ PROGRESS COMPONENT TOKENS
3
+ Override globally: :root { --stuic-progress-height: 1rem; }
4
+ Override locally: <Progress style="--stuic-progress-accent: green;" />
5
+ ============================================================================ */
6
+
2
7
  :root {
8
+ /* Colors */
3
9
  --stuic-progress-bg: var(--stuic-color-muted);
4
10
  --stuic-progress-accent: var(--stuic-color-primary);
11
+
12
+ /* Bar dimensions */
13
+ --stuic-progress-height: calc(var(--spacing) * 2); /* 0.5rem */
14
+ --stuic-progress-radius: var(--radius-sm);
15
+ --stuic-progress-transition: 100ms;
16
+
17
+ /* Circle dimensions */
18
+ --stuic-progress-circle-size: calc(var(--spacing) * 16); /* 4rem */
19
+ --stuic-progress-circle-stroke-width: 10; /* in viewBox units (100x100) */
20
+ }
21
+
22
+ @layer components {
23
+ /* ============================================================================
24
+ BAR STYLES
25
+ ============================================================================ */
26
+
27
+ .stuic-progress-bar {
28
+ width: 100%;
29
+ height: var(--stuic-progress-height);
30
+ background: var(--stuic-progress-bg);
31
+ border-radius: var(--stuic-progress-radius);
32
+ overflow: hidden;
33
+ pointer-events: none;
34
+ }
35
+
36
+ .stuic-progress-bar > .bar {
37
+ height: 100%;
38
+ background: var(--stuic-progress-accent);
39
+ border-radius: inherit;
40
+ transition: width var(--stuic-progress-transition) linear;
41
+ }
42
+
43
+ /* ============================================================================
44
+ CIRCLE STYLES
45
+ ============================================================================ */
46
+
47
+ .stuic-progress-circle {
48
+ width: var(--stuic-progress-circle-size);
49
+ height: var(--stuic-progress-circle-size);
50
+ }
5
51
  }
@@ -0,0 +1,152 @@
1
+ # Skeleton
2
+
3
+ A loading placeholder component with shimmer and pulse animations. Automatically respects `prefers-reduced-motion` for accessibility.
4
+
5
+ ## Props
6
+
7
+ | Prop | Type | Default | Description |
8
+ |------|------|---------|-------------|
9
+ | `variant` | `"text" \| "circle" \| "rectangle"` | `"rectangle"` | Shape variant |
10
+ | `width` | `string` | - | Width (e.g., "100%", "200px") |
11
+ | `height` | `string` | CSS token | Height (e.g., "1rem", "40px") |
12
+ | `size` | `string` | - | Circle shorthand (sets both width & height) |
13
+ | `lines` | `number` | `1` | Number of text lines (text variant) |
14
+ | `gap` | `string` | CSS token | Gap between lines (text variant) |
15
+ | `lastLineWidth` | `string` | `"75%"` | Last line width (text variant) |
16
+ | `animation` | `"shimmer" \| "pulse" \| "none"` | `"shimmer"` | Animation style |
17
+ | `duration` | `string` | CSS token | Animation duration |
18
+ | `rounded` | `boolean \| string` | `true` | Border radius (boolean for default, string for custom) |
19
+ | `ariaLabel` | `string` | - | Accessibility label |
20
+ | `el` | `HTMLDivElement` | - | Bindable element reference |
21
+ | `class` | `string \| string[]` | - | CSS classes |
22
+
23
+ ## Usage
24
+
25
+ ### Basic
26
+
27
+ ```svelte
28
+ <script lang="ts">
29
+ import { Skeleton } from '@marianmeres/stuic';
30
+ </script>
31
+
32
+ <Skeleton width="100%" height="1rem" />
33
+ ```
34
+
35
+ ### Variants
36
+
37
+ ```svelte
38
+ <!-- Rectangle (default) -->
39
+ <Skeleton width="200px" height="100px" />
40
+
41
+ <!-- Circle -->
42
+ <Skeleton variant="circle" size="48px" />
43
+
44
+ <!-- Text block -->
45
+ <Skeleton variant="text" lines={3} />
46
+ ```
47
+
48
+ ### Animations
49
+
50
+ ```svelte
51
+ <Skeleton animation="shimmer" />
52
+ <Skeleton animation="pulse" />
53
+ <Skeleton animation="none" />
54
+ ```
55
+
56
+ ### Custom Duration
57
+
58
+ ```svelte
59
+ <Skeleton duration="2s" />
60
+
61
+ <!-- Or via CSS variable -->
62
+ <Skeleton style="--stuic-skeleton-duration: 2s;" />
63
+ ```
64
+
65
+ ### Card Skeleton Example
66
+
67
+ ```svelte
68
+ <div class="flex items-center gap-4 p-4">
69
+ <Skeleton variant="circle" size="48px" />
70
+ <div class="flex-1 space-y-2">
71
+ <Skeleton height="1rem" width="60%" />
72
+ <Skeleton height="0.75rem" width="80%" />
73
+ </div>
74
+ </div>
75
+ ```
76
+
77
+ ### List Skeleton Example
78
+
79
+ ```svelte
80
+ {#each Array(5) as _}
81
+ <div class="flex items-center gap-3 py-2">
82
+ <Skeleton variant="circle" size="32px" />
83
+ <Skeleton width="200px" />
84
+ </div>
85
+ {/each}
86
+ ```
87
+
88
+ ## CSS Variables
89
+
90
+ ### Component Tokens
91
+
92
+ Override globally in `:root` or locally via `style` prop:
93
+
94
+ | Variable | Default | Description |
95
+ |----------|---------|-------------|
96
+ | `--stuic-skeleton-bg` | `--stuic-color-muted` | Base background color |
97
+ | `--stuic-skeleton-bg-highlight` | `--stuic-color-muted-hover` | Shimmer highlight color |
98
+ | `--stuic-skeleton-height` | `1rem` | Default height for text lines |
99
+ | `--stuic-skeleton-gap` | `0.5rem` | Gap between text lines |
100
+ | `--stuic-skeleton-radius` | `--radius-sm` | Default border radius |
101
+ | `--stuic-skeleton-duration` | `1.5s` | Animation duration |
102
+ | `--stuic-skeleton-timing` | `ease-in-out` | Animation timing function |
103
+ | `--stuic-skeleton-pulse-opacity` | `0.4` | Pulse animation minimum opacity |
104
+
105
+ ### Customization Examples
106
+
107
+ ```css
108
+ /* Global override - different colors */
109
+ :root {
110
+ --stuic-skeleton-bg: var(--color-gray-200);
111
+ --stuic-skeleton-bg-highlight: var(--color-gray-300);
112
+ }
113
+
114
+ /* Global override - slower animation */
115
+ :root {
116
+ --stuic-skeleton-duration: 2s;
117
+ }
118
+
119
+ /* Global override - sharper corners */
120
+ :root {
121
+ --stuic-skeleton-radius: 0;
122
+ }
123
+ ```
124
+
125
+ ```svelte
126
+ <!-- Local override - faster animation -->
127
+ <Skeleton style="--stuic-skeleton-duration: 0.8s;" />
128
+
129
+ <!-- Local override - custom colors -->
130
+ <Skeleton style="--stuic-skeleton-bg: oklch(0.9 0.02 250);" />
131
+
132
+ <!-- Local override - no rounded corners -->
133
+ <Skeleton rounded={false} />
134
+
135
+ <!-- Local override - custom radius -->
136
+ <Skeleton rounded="1rem" />
137
+ ```
138
+
139
+ ## Accessibility
140
+
141
+ - Uses `role="status"` and `aria-busy="true"` by default
142
+ - Optional `ariaLabel` prop for custom screen reader text
143
+ - Automatically disables animations when `prefers-reduced-motion: reduce` is set
144
+
145
+ ## Theming
146
+
147
+ The Skeleton component uses theme tokens for colors:
148
+
149
+ - Background: `--stuic-color-muted`
150
+ - Highlight: `--stuic-color-muted-hover`
151
+
152
+ These automatically adapt to light/dark mode when using the STUIC theming system.
@@ -35,7 +35,6 @@
35
35
  </script>
36
36
 
37
37
  <script lang="ts">
38
- import "./index.css";
39
38
  import { twMerge } from "../../utils/tw-merge.js";
40
39
  import { prefersReducedMotion } from "../../utils/prefers-reduced-motion.svelte.js";
41
40
 
@@ -45,10 +44,10 @@
45
44
  height,
46
45
  size,
47
46
  lines = 1,
48
- gap = "0.5rem",
47
+ gap,
49
48
  lastLineWidth = "75%",
50
49
  animation = "shimmer",
51
- duration = "1.5s",
50
+ duration,
52
51
  rounded = true,
53
52
  ariaLabel,
54
53
  el = $bindable(),
@@ -67,7 +66,7 @@
67
66
  effectiveAnimation === "pulse" && "stuic-skeleton-pulse",
68
67
  effectiveAnimation === "none" && "bg-[var(--stuic-skeleton-bg)]",
69
68
  variant === "circle" && "stuic-skeleton-circle",
70
- rounded === true && variant !== "circle" && "rounded",
69
+ rounded === true && variant !== "circle" && "stuic-skeleton-rounded",
71
70
  classProp
72
71
  )
73
72
  );
@@ -102,9 +101,9 @@
102
101
  {@const isLast = i === lines - 1}
103
102
  <div
104
103
  class={baseClass}
105
- style="{baseStyle}; width: {isLast
106
- ? lastLineWidth
107
- : width || '100%'}; height: {height || '1rem'}"
104
+ style="{baseStyle}; width: {isLast ? lastLineWidth : width || '100%'}{height
105
+ ? `; height: ${height}`
106
+ : ''}"
108
107
  ></div>
109
108
  {/each}
110
109
  {#if ariaLabel}
@@ -27,7 +27,6 @@ export interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "children" |
27
27
  /** CSS class */
28
28
  class?: string | string[];
29
29
  }
30
- import "./index.css";
31
30
  declare const Skeleton: import("svelte").Component<Props, {}, "el">;
32
31
  type Skeleton = ReturnType<typeof Skeleton>;
33
32
  export default Skeleton;