zabi-components 5.0.13 → 5.0.15

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.
@@ -45,18 +45,18 @@
45
45
  // Note: Using text-white instead of text-inverse to ensure light text in both light and dark modes
46
46
  const variantClass =
47
47
  variant === "success"
48
- ? "bg-[var(--color-success)] border-[var(--color-success)] text-white"
48
+ ? "bg-success border-success text-white"
49
49
  : variant === "warning"
50
- ? "bg-[var(--color-warning-weak)] border-[var(--color-warning-weak)] text-white"
50
+ ? "bg-warning border-warning text-white"
51
51
  : variant === "error"
52
- ? "bg-[var(--color-error)] border-[var(--color-error)] text-white"
52
+ ? "bg-error border-error text-white"
53
53
  : variant === "info"
54
- ? "bg-[var(--color-info)] border-[var(--color-info)] text-white"
54
+ ? "bg-info border-info text-white"
55
55
  : variant === "neutral"
56
- ? "bg-[var(--color-neutral)] border-[var(--color-neutral)] text-white"
56
+ ? "bg-neutral border-neutral text-white"
57
57
  : variant === "energetic"
58
- ? "bg-[var(--color-energetic-weak)] border-[var(--color-energetic-weak)] text-white"
59
- : "bg-[var(--color-secondary)] border-[var(--color-secondary)] text-white"; // default
58
+ ? "bg-energetic border-energetic text-white"
59
+ : "bg-secondary border-secondary text-white"; // default
60
60
 
61
61
  return `${baseClasses} ${sizeClass} ${variantClass}`.trim();
62
62
  });
@@ -77,7 +77,10 @@
77
77
  {#if variant === "success"}
78
78
  <Check size={iconSize()} class="{iconSpacingClass()} text-white" />
79
79
  {:else if variant === "warning"}
80
- <AlertTriangle size={iconSize()} class="{iconSpacingClass()} text-white" />
80
+ <AlertTriangle
81
+ size={iconSize()}
82
+ class="{iconSpacingClass()} text-white"
83
+ />
81
84
  {:else if variant === "error"}
82
85
  <X size={iconSize()} class="{iconSpacingClass()} text-white" />
83
86
  {:else if variant === "info"}
@@ -36,6 +36,7 @@
36
36
  size = "md",
37
37
  variant = "default",
38
38
  message = "",
39
+ onchange,
39
40
  ...restProps
40
41
  }: Props = $props();
41
42
 
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { CheckCircle, AlertTriangle, AlertCircle } from "@lucide/svelte";
3
+
2
4
  // SSR-safe ID generation
3
5
  function generateId(prefix: string = "id"): string {
4
6
  if (typeof window !== "undefined") {
@@ -15,8 +17,8 @@
15
17
  placeholder?: string;
16
18
  disabled?: boolean;
17
19
  rows?: number;
18
- size?: "sm" | "md" | "lg";
19
20
  variant?: "default" | "success" | "warning" | "error";
21
+ message?: string;
20
22
  oninput?: (event: Event) => void;
21
23
  }
22
24
 
@@ -27,8 +29,8 @@
27
29
  placeholder = "",
28
30
  disabled = false,
29
31
  rows = 4,
30
- size = "md",
31
32
  variant = "default",
33
+ message = "",
32
34
  oninput,
33
35
  ...restProps
34
36
  }: Props = $props();
@@ -36,15 +38,6 @@
36
38
  // Generate unique ID - SSR safe (call directly, not in $state)
37
39
  const textareaId = generateId("textarea");
38
40
 
39
- // Size classes using full class names
40
- const sizeClass = $derived(() => {
41
- return size === "sm"
42
- ? "px-3 py-1.5 text-sm"
43
- : size === "lg"
44
- ? "px-5 py-3 text-base"
45
- : "px-4 py-2 text-sm"; // default md
46
- });
47
-
48
41
  // Variant classes using semantic colors
49
42
  const variantClass = $derived(() => {
50
43
  return variant === "success"
@@ -53,15 +46,15 @@
53
46
  ? "border-warning focus:border-warning focus:ring-warning"
54
47
  : variant === "error"
55
48
  ? "border-error focus:border-error focus:ring-error"
56
- : "border-border focus:border-focus focus:ring-focus"; // default
49
+ : "border-0 focus:ring-2 focus:ring-brand-500"; // default - no border
57
50
  });
58
51
 
59
- // Textarea classes using Badge pattern
52
+ // Textarea classes matching M3 design
60
53
  const textareaClasses = $derived(() => {
61
54
  const baseClasses =
62
- "w-full border rounded-md transition-colors duration-200 placeholder:text-input-placeholder focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-surface disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-surface-disabled resize-y";
55
+ "w-full bg-brand-100 rounded-lg transition-all duration-200 placeholder:text-description text-body focus:outline-none focus:ring-offset-0 disabled:opacity-50 disabled:cursor-not-allowed resize-y px-4 py-2.5 text-base leading-6";
63
56
 
64
- return `${baseClasses} ${sizeClass()} ${variantClass()}`.trim();
57
+ return `${baseClasses} ${variantClass()}`.trim();
65
58
  });
66
59
 
67
60
  // Label classes using semantic text colors
@@ -69,6 +62,26 @@
69
62
  () => "block text-sm font-medium text-label mb-1",
70
63
  );
71
64
 
65
+ // Message classes based on variant
66
+ const messageClasses = $derived(() => {
67
+ if (variant === "error") {
68
+ return "text-error text-sm mt-1 flex items-center gap-1.5";
69
+ } else if (variant === "success") {
70
+ return "text-success text-sm mt-1 flex items-center gap-1.5";
71
+ } else if (variant === "warning") {
72
+ return "text-warning text-sm mt-1 flex items-center gap-1.5";
73
+ }
74
+ return "text-description text-sm mt-1 flex items-center gap-1.5";
75
+ });
76
+
77
+ // Get icon component based on variant
78
+ const getIcon = $derived(() => {
79
+ if (variant === "error") return AlertCircle;
80
+ if (variant === "success") return CheckCircle;
81
+ if (variant === "warning") return AlertTriangle;
82
+ return null;
83
+ });
84
+
72
85
  function handleInput(event: Event) {
73
86
  const target = event.target as HTMLTextAreaElement;
74
87
  value = target.value;
@@ -84,7 +97,6 @@
84
97
  {#if label}
85
98
  <label for={textareaId} class={labelClasses()}>{label}</label>
86
99
  {/if}
87
-
88
100
  <textarea
89
101
  id={textareaId}
90
102
  {name}
@@ -94,6 +106,17 @@
94
106
  {rows}
95
107
  class={textareaClasses()}
96
108
  oninput={handleInput}
109
+ aria-invalid={variant === "error" ? "true" : undefined}
110
+ aria-describedby={message ? `${textareaId}-message` : undefined}
97
111
  {...restProps}
98
112
  ></textarea>
113
+ {#if message && variant !== "default"}
114
+ <p id={`${textareaId}-message`} class={messageClasses()} role="alert">
115
+ {#if getIcon()}
116
+ {@const Icon = getIcon()}
117
+ <Icon size={14} class="shrink-0" />
118
+ {/if}
119
+ <span>{message}</span>
120
+ </p>
121
+ {/if}
99
122
  </div>
@@ -5,8 +5,8 @@ interface Props {
5
5
  placeholder?: string;
6
6
  disabled?: boolean;
7
7
  rows?: number;
8
- size?: "sm" | "md" | "lg";
9
8
  variant?: "default" | "success" | "warning" | "error";
9
+ message?: string;
10
10
  oninput?: (event: Event) => void;
11
11
  }
12
12
  declare const Textarea: import("svelte").Component<Props, {}, "">;
@@ -52,7 +52,7 @@
52
52
  const baseClasses = "flex flex-col items-center justify-center overflow-clip relative rounded-[20px] shrink-0 transition-colors duration-200";
53
53
 
54
54
  if (isActive) {
55
- return `${baseClasses} bg-[var(--color-action-primary-subtle-hover)]`;
55
+ return `${baseClasses} bg-action-primary-subtle-hover`;
56
56
  }
57
57
  return `${baseClasses}`;
58
58
  }
@@ -0,0 +1,325 @@
1
+ /* ========================================
2
+ ZABI COMPONENTS COLOR SYSTEM
3
+ Standalone CSS Custom Properties
4
+ Works without Tailwind CSS processing
5
+ ======================================== */
6
+
7
+ :root {
8
+ /* Brand Color Scale */
9
+ --color-brand-50: #f7faff;
10
+ --color-brand-100: #edf2fb;
11
+ --color-brand-200: #dfe7fb;
12
+ --color-brand-300: #ccdbfd;
13
+ --color-brand-400: #abc4ff;
14
+ --color-brand-500: #8fa8ff;
15
+ --color-brand-600: #6e84fa;
16
+ --color-brand-700: #5366e2;
17
+ --color-brand-800: #3f4fc0;
18
+ --color-brand-900: #2f3c99;
19
+ --color-brand-950: #1f2866;
20
+
21
+ /* Citron Color Scale */
22
+ --color-citron-50: #f9faeb;
23
+ --color-citron-100: #f1f5cf;
24
+ --color-citron-200: #e4ecaa;
25
+ --color-citron-300: #d5e184;
26
+ --color-citron-400: #c7d460;
27
+ --color-citron-500: #bbbe64;
28
+ --color-citron-600: #a3a852;
29
+ --color-citron-700: #848a43;
30
+ --color-citron-800: #666c35;
31
+ --color-citron-900: #4d5229;
32
+ --color-citron-950: #323518;
33
+
34
+ /* Pine Color Scale */
35
+ --color-pine-50: #e9f6f2;
36
+ --color-pine-100: #d2ece4;
37
+ --color-pine-200: #a7d9c9;
38
+ --color-pine-300: #78c4ad;
39
+ --color-pine-400: #49ad91;
40
+ --color-pine-500: #0C5D43;
41
+ --color-pine-600: #0a513a;
42
+ --color-pine-700: #084532;
43
+ --color-pine-800: #063a2a;
44
+ --color-pine-900: #04231a;
45
+ --color-pine-950: #02160f;
46
+
47
+ /* Iris Color Scale */
48
+ --color-iris-50: #f4f4fa;
49
+ --color-iris-100: #e9e9f7;
50
+ --color-iris-200: #d6d6f0;
51
+ --color-iris-300: #bdbde6;
52
+ --color-iris-400: #a3a3d8;
53
+ --color-iris-500: #6969B3;
54
+ --color-iris-600: #58589e;
55
+ --color-iris-700: #474788;
56
+ --color-iris-800: #38386f;
57
+ --color-iris-900: #2a2a56;
58
+ --color-iris-950: #1b1b37;
59
+
60
+ /* Surface Colors - Tailwind stone palette */
61
+ --color-surface-level-0: #fafaf9;
62
+ --color-surface-level-0-hover: #f5f5f4;
63
+ --color-surface-level-1: #f5f5f4;
64
+ --color-surface-level-1-hover: #e7e5e4;
65
+ --color-surface-level-2: #e7e5e4;
66
+ --color-surface-level-2-hover: #d6d3d1;
67
+ --color-surface-elevated: #ffffff;
68
+ --color-surface-elevated-hover: #fafaf9;
69
+ --color-surface-hover: #f5f5f4;
70
+ --color-surface-active: #e7e5e4;
71
+ --color-surface-inverse: #1c1917;
72
+ --color-surface-disabled: #e7e5e4;
73
+ --color-surface-container-high: #ece6f0;
74
+
75
+ /* Background Colors */
76
+ --color-background: #ffffff;
77
+ --color-background-secondary: #fafaf9;
78
+ --color-background-tertiary: #f5f5f4;
79
+
80
+ /* Page Colors */
81
+ --color-page: #f5f5f4;
82
+ --color-page-secondary: #e7e5e4;
83
+
84
+ /* Card Colors */
85
+ --color-card: #ffffff;
86
+ --color-card-hover: #f5f5f4;
87
+ --color-card-active: #f5f5f4;
88
+ --color-card-elevated: #ffffff;
89
+
90
+ /* Text Colors */
91
+ --color-headline: #1c1917;
92
+ --color-body: #292524;
93
+ --color-description: #57534e;
94
+ --color-caption: #78716c;
95
+ --color-input-placeholder: #a8a29e;
96
+ --color-label: #44403c;
97
+ --color-link: #6e84fa;
98
+ --color-link-hover: #5366e2;
99
+ --color-success-text: #084532;
100
+ --color-warning-text: #b45309;
101
+ --color-neutral-text: #44403c;
102
+ --color-energetic-text: #848a43;
103
+ --color-error-text: #b91c1c;
104
+ --color-inverse: #ffffff;
105
+ --color-disabled: #a8a29e;
106
+
107
+ /* Border Colors */
108
+ --color-border: #e7e5e4;
109
+ --color-border-weak: #d6d3d1;
110
+ --color-border-medium: #a8a29e;
111
+ --color-border-strong: #78716c;
112
+
113
+ /* Focus Colors */
114
+ --color-focus: #8fa8ff;
115
+ --color-focus-weak: #6e84fa;
116
+ --color-focus-medium: #5366e2;
117
+ --color-focus-strong: #3f4fc0;
118
+
119
+ /* Primary Colors */
120
+ --color-primary: #6e84fa;
121
+ --color-primary-weak: #5366e2;
122
+ --color-primary-medium: #3f4fc0;
123
+ --color-primary-strong: #2f3c99;
124
+
125
+ /* Secondary Colors */
126
+ --color-secondary: #57534e;
127
+ --color-secondary-weak: #44403c;
128
+ --color-secondary-medium: #292524;
129
+ --color-secondary-strong: #1c1917;
130
+
131
+ /* Success Colors */
132
+ --color-success: #0a513a;
133
+ --color-success-weak: #084532;
134
+ --color-success-medium: #063a2a;
135
+ --color-success-strong: #04231a;
136
+
137
+ /* Warning Colors */
138
+ --color-warning: #f59e0b;
139
+ --color-warning-weak: #d97706;
140
+ --color-warning-medium: #fbbf24;
141
+ --color-warning-strong: #fcd34d;
142
+
143
+ /* Error Colors */
144
+ --color-error: #ef4444;
145
+ --color-error-weak: #dc2626;
146
+ --color-error-medium: #f87171;
147
+ --color-error-strong: #fca5a5;
148
+
149
+ /* Energetic Colors (Citron) */
150
+ --color-energetic: #bbbe64;
151
+ --color-energetic-weak: #a3a852;
152
+ --color-energetic-medium: #c7d460;
153
+ --color-energetic-strong: #d5e184;
154
+
155
+ /* Neutral Colors */
156
+ --color-neutral: #57534e;
157
+ --color-neutral-weak: #44403c;
158
+ --color-neutral-medium: #292524;
159
+ --color-neutral-strong: #1c1917;
160
+
161
+ /* Info Colors */
162
+ --color-info: #58589e;
163
+ --color-info-weak: #474788;
164
+ --color-info-medium: #38386f;
165
+ --color-info-strong: #2a2a56;
166
+ --color-info-text: var(--color-info);
167
+
168
+ /* Action Colors */
169
+ --color-action-primary: #6e84fa;
170
+ --color-action-primary-hover: #5366e2;
171
+ --color-action-primary-active: #3f4fc0;
172
+ --color-action-primary-disabled: #ccdbfd;
173
+ --color-action-primary-subtle: #f7faff;
174
+ --color-action-primary-subtle-hover: #edf2fb;
175
+
176
+ --color-action-secondary: #57534e;
177
+ --color-action-secondary-hover: #44403c;
178
+ --color-action-secondary-active: #292524;
179
+ --color-action-secondary-disabled: #d6d3d1;
180
+ --color-action-secondary-subtle: #f5f5f4;
181
+ --color-action-secondary-subtle-hover: #e7e5e4;
182
+
183
+ --color-action-danger: #dc2626;
184
+ --color-action-danger-hover: #b91c1c;
185
+ --color-action-danger-active: #991b1b;
186
+ --color-action-danger-disabled: #fca5a5;
187
+ --color-action-danger-subtle: #fef2f2;
188
+ --color-action-danger-subtle-hover: #fee2e2;
189
+ }
190
+
191
+ /* Dark Mode */
192
+ .dark {
193
+ /* Surface Colors - Dark mode variants */
194
+ --color-surface-level-0: #292524;
195
+ --color-surface-level-0-hover: #44403c;
196
+ --color-surface-level-1: #44403c;
197
+ --color-surface-level-1-hover: #57534e;
198
+ --color-surface-level-2: #57534e;
199
+ --color-surface-level-2-hover: #78716c;
200
+ --color-surface-elevated: #292524;
201
+ --color-surface-elevated-hover: #44403c;
202
+ --color-surface-hover: #44403c;
203
+ --color-surface-active: #57534e;
204
+ --color-surface-inverse: #f5f5f4;
205
+ --color-surface-disabled: #44403c;
206
+ --color-surface-container-high: #44403c;
207
+
208
+ /* Background Colors */
209
+ --color-background: #1c1917;
210
+ --color-background-secondary: #292524;
211
+ --color-background-tertiary: #44403c;
212
+
213
+ /* Page Colors */
214
+ --color-page: #292524;
215
+ --color-page-secondary: #292524;
216
+
217
+ /* Card Colors */
218
+ --color-card: #292524;
219
+ --color-card-hover: #44403c;
220
+ --color-card-active: #57534e;
221
+ --color-card-elevated: #292524;
222
+
223
+ /* Text Colors */
224
+ --color-headline: #f5f5f4;
225
+ --color-body: #e7e5e4;
226
+ --color-description: #d6d3d1;
227
+ --color-caption: #a8a29e;
228
+ --color-input-placeholder: #78716c;
229
+ --color-label: #e7e5e4;
230
+ --color-link: #abc4ff;
231
+ --color-link-hover: #ccdbfd;
232
+ --color-success-text: #49ad91;
233
+ --color-warning-text: #fbbf24;
234
+ --color-neutral-text: #a8a29e;
235
+ --color-energetic-text: #c7d460;
236
+ --color-error-text: #f87171;
237
+ --color-inverse: #1c1917;
238
+ --color-disabled: #78716c;
239
+
240
+ /* Border Colors */
241
+ --color-border: #57534e;
242
+ --color-border-weak: #78716c;
243
+ --color-border-medium: #a8a29e;
244
+ --color-border-strong: #d6d3d1;
245
+
246
+ /* Focus Colors */
247
+ --color-focus: #abc4ff;
248
+ --color-focus-weak: #8fa8ff;
249
+ --color-focus-medium: #6e84fa;
250
+ --color-focus-strong: #5366e2;
251
+ --color-focus-disabled: #6e84fa;
252
+
253
+ /* Primary Colors */
254
+ --color-primary: #6e84fa;
255
+ --color-primary-weak: #5366e2;
256
+ --color-primary-medium: #3f4fc0;
257
+ --color-primary-strong: #2f3c99;
258
+
259
+ /* Secondary Colors */
260
+ --color-secondary: #57534e;
261
+ --color-secondary-weak: #44403c;
262
+ --color-secondary-medium: #292524;
263
+ --color-secondary-strong: #1c1917;
264
+
265
+ /* Success Colors */
266
+ --color-success: #0C5D43;
267
+ --color-success-weak: #0a513a;
268
+ --color-success-medium: #49ad91;
269
+ --color-success-strong: #78c4ad;
270
+
271
+ /* Warning Colors */
272
+ --color-warning: #d97706;
273
+ --color-warning-weak: #b45309;
274
+ --color-warning-medium: #92400e;
275
+ --color-warning-strong: #78350f;
276
+
277
+ /* Error Colors */
278
+ --color-error: #dc2626;
279
+ --color-error-weak: #b91c1c;
280
+ --color-error-medium: #991b1b;
281
+ --color-error-strong: #7f1d1d;
282
+
283
+ /* Energetic Colors (Citron) */
284
+ --color-energetic: #a3a852;
285
+ --color-energetic-weak: #848a43;
286
+ --color-energetic-medium: #666c35;
287
+ --color-energetic-strong: #4d5229;
288
+
289
+ /* Neutral Colors */
290
+ --color-neutral: #57534e;
291
+ --color-neutral-weak: #78716c;
292
+ --color-neutral-medium: #a8a29e;
293
+ --color-neutral-strong: #d6d3d1;
294
+
295
+ /* Info Colors */
296
+ --color-info: #6969B3;
297
+ --color-info-weak: #58589e;
298
+ --color-info-active: #a3a3d8;
299
+ --color-info-medium: #a3a3d8;
300
+ --color-info-strong: #bdbde6;
301
+ --color-info-text: var(--color-info);
302
+
303
+ /* Action Colors - Dark mode variants */
304
+ --color-action-primary: #8fa8ff;
305
+ --color-action-primary-hover: #6e84fa;
306
+ --color-action-primary-active: #5366e2;
307
+ --color-action-primary-disabled: #5366e2;
308
+ --color-action-primary-subtle: #1f2866;
309
+ --color-action-primary-subtle-hover: #2f3c99;
310
+
311
+ --color-action-secondary: #78716c;
312
+ --color-action-secondary-hover: #57534e;
313
+ --color-action-secondary-active: #44403c;
314
+ --color-action-secondary-disabled: #44403c;
315
+ --color-action-secondary-subtle: #292524;
316
+ --color-action-secondary-subtle-hover: #44403c;
317
+
318
+ --color-action-danger: #ef4444;
319
+ --color-action-danger-hover: #dc2626;
320
+ --color-action-danger-active: #b91c1c;
321
+ --color-action-danger-disabled: #b91c1c;
322
+ --color-action-danger-subtle: #450a0a;
323
+ --color-action-danger-subtle-hover: #7f1d1d;
324
+ }
325
+