zabi-components 5.0.11 → 5.0.13
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/dist/atoms/Badge.svelte +18 -15
- package/dist/atoms/Button.svelte +41 -13
- package/dist/atoms/Card.svelte +31 -7
- package/dist/atoms/Card.svelte.d.ts +1 -0
- package/dist/atoms/Checkbox.svelte +64 -22
- package/dist/atoms/Input.svelte +61 -10
- package/dist/atoms/Input.svelte.d.ts +1 -0
- package/dist/atoms/Select.svelte +165 -34
- package/dist/atoms/Select.svelte.d.ts +2 -0
- package/dist/atoms/ThemeToggle.svelte +75 -12
- package/dist/atoms/ThemeToggle.svelte.d.ts +2 -1
- package/dist/atoms/Toggle.svelte +5 -5
- package/dist/molecules/Dropdown.svelte +44 -106
- package/dist/molecules/ImageUpload.svelte +15 -5
- package/dist/molecules/Modal.svelte +23 -19
- package/dist/molecules/SlideUp.svelte +37 -31
- package/dist/organisms/Navigation.svelte +80 -18
- package/dist/organisms/Navigation.svelte.d.ts +9 -5
- package/dist/zabi-components.css +166 -0
- package/package.json +1 -1
package/dist/atoms/Badge.svelte
CHANGED
|
@@ -39,21 +39,24 @@
|
|
|
39
39
|
? "px-4 py-2 text-base"
|
|
40
40
|
: "px-3 py-1 text-sm"; // default md
|
|
41
41
|
|
|
42
|
-
// Variant classes - using semantic color system
|
|
42
|
+
// Variant classes - using semantic color system with improved WCAG contrast
|
|
43
|
+
// Using colored backgrounds with white text for better contrast ratios (4.5:1+)
|
|
44
|
+
// Using darker shades for warning and energetic to ensure WCAG AA compliance
|
|
45
|
+
// Note: Using text-white instead of text-inverse to ensure light text in both light and dark modes
|
|
43
46
|
const variantClass =
|
|
44
47
|
variant === "success"
|
|
45
|
-
? "bg-
|
|
48
|
+
? "bg-[var(--color-success)] border-[var(--color-success)] text-white"
|
|
46
49
|
: variant === "warning"
|
|
47
|
-
? "bg-
|
|
50
|
+
? "bg-[var(--color-warning-weak)] border-[var(--color-warning-weak)] text-white"
|
|
48
51
|
: variant === "error"
|
|
49
|
-
? "bg-
|
|
52
|
+
? "bg-[var(--color-error)] border-[var(--color-error)] text-white"
|
|
50
53
|
: variant === "info"
|
|
51
|
-
? "bg-
|
|
54
|
+
? "bg-[var(--color-info)] border-[var(--color-info)] text-white"
|
|
52
55
|
: variant === "neutral"
|
|
53
|
-
? "bg-
|
|
56
|
+
? "bg-[var(--color-neutral)] border-[var(--color-neutral)] text-white"
|
|
54
57
|
: variant === "energetic"
|
|
55
|
-
? "bg-
|
|
56
|
-
: "bg-
|
|
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
|
|
57
60
|
|
|
58
61
|
return `${baseClasses} ${sizeClass} ${variantClass}`.trim();
|
|
59
62
|
});
|
|
@@ -72,19 +75,19 @@
|
|
|
72
75
|
<span class={classes()}>
|
|
73
76
|
{#if showIcon}
|
|
74
77
|
{#if variant === "success"}
|
|
75
|
-
<Check size={iconSize()} class={iconSpacingClass()} />
|
|
78
|
+
<Check size={iconSize()} class="{iconSpacingClass()} text-white" />
|
|
76
79
|
{:else if variant === "warning"}
|
|
77
|
-
<AlertTriangle size={iconSize()} class={iconSpacingClass()} />
|
|
80
|
+
<AlertTriangle size={iconSize()} class="{iconSpacingClass()} text-white" />
|
|
78
81
|
{:else if variant === "error"}
|
|
79
|
-
<X size={iconSize()} class={iconSpacingClass()} />
|
|
82
|
+
<X size={iconSize()} class="{iconSpacingClass()} text-white" />
|
|
80
83
|
{:else if variant === "info"}
|
|
81
|
-
<Info size={iconSize()} class={iconSpacingClass()} />
|
|
84
|
+
<Info size={iconSize()} class="{iconSpacingClass()} text-white" />
|
|
82
85
|
{:else if variant === "neutral"}
|
|
83
|
-
<Info size={iconSize()} class={iconSpacingClass()} />
|
|
86
|
+
<Info size={iconSize()} class="{iconSpacingClass()} text-white" />
|
|
84
87
|
{:else if variant === "energetic"}
|
|
85
|
-
<Info size={iconSize()} class={iconSpacingClass()} />
|
|
88
|
+
<Info size={iconSize()} class="{iconSpacingClass()} text-white" />
|
|
86
89
|
{:else}
|
|
87
|
-
<Info size={iconSize()} class={iconSpacingClass()} />
|
|
90
|
+
<Info size={iconSize()} class="{iconSpacingClass()} text-white" />
|
|
88
91
|
{/if}
|
|
89
92
|
{/if}
|
|
90
93
|
{text}
|
package/dist/atoms/Button.svelte
CHANGED
|
@@ -22,34 +22,62 @@
|
|
|
22
22
|
...restProps
|
|
23
23
|
}: Props = $props();
|
|
24
24
|
|
|
25
|
-
// Size classes
|
|
25
|
+
// Size classes matching M3 design specifications
|
|
26
26
|
const sizeClass = $derived(() => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
if (size === "sm") {
|
|
28
|
+
return {
|
|
29
|
+
padding: "px-4 py-2.5",
|
|
30
|
+
text: "text-sm",
|
|
31
|
+
font: "font-medium",
|
|
32
|
+
leading: "leading-5",
|
|
33
|
+
tracking: "tracking-[0.1px]",
|
|
34
|
+
radius: "rounded-lg",
|
|
35
|
+
gap: "gap-2"
|
|
36
|
+
};
|
|
37
|
+
} else if (size === "lg") {
|
|
38
|
+
return {
|
|
39
|
+
padding: "px-12 py-8",
|
|
40
|
+
text: "text-2xl",
|
|
41
|
+
font: "font-normal",
|
|
42
|
+
leading: "leading-8",
|
|
43
|
+
tracking: "tracking-normal",
|
|
44
|
+
radius: "rounded-2xl",
|
|
45
|
+
gap: "gap-3"
|
|
46
|
+
};
|
|
47
|
+
} else {
|
|
48
|
+
// default md
|
|
49
|
+
return {
|
|
50
|
+
padding: "px-6 py-4",
|
|
51
|
+
text: "text-base",
|
|
52
|
+
font: "font-medium",
|
|
53
|
+
leading: "leading-6",
|
|
54
|
+
tracking: "tracking-[0.15px]",
|
|
55
|
+
radius: "rounded-lg",
|
|
56
|
+
gap: "gap-2"
|
|
57
|
+
};
|
|
58
|
+
}
|
|
32
59
|
});
|
|
33
60
|
|
|
34
61
|
// Variant classes using semantic action colors
|
|
35
62
|
const variantClass = $derived(() => {
|
|
36
63
|
return variant === "primary"
|
|
37
|
-
? "bg-action-primary text-inverse focus:ring-2 focus:ring-brand-500 focus:ring-offset-2"
|
|
64
|
+
? "bg-action-primary text-inverse hover:bg-action-primary-hover active:bg-action-primary-active focus:ring-2 focus:ring-brand-500 focus:ring-offset-2"
|
|
38
65
|
: variant === "secondary"
|
|
39
|
-
? "
|
|
66
|
+
? "bg-brand-100 text-brand-800 hover:bg-brand-200 active:bg-brand-300 focus:ring-2 focus:ring-brand-500 focus:ring-offset-2"
|
|
40
67
|
: variant === "danger"
|
|
41
|
-
? "bg-action-danger text-inverse focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
|
|
68
|
+
? "bg-action-danger text-inverse hover:bg-action-danger-hover active:bg-action-danger-active focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
|
|
42
69
|
: variant === "ghost"
|
|
43
70
|
? "bg-transparent text-headline hover:bg-surface-hover active:bg-surface-active focus:ring-2 focus:ring-stone-500 focus:ring-offset-2 disabled:text-disabled"
|
|
44
|
-
: "bg-action-primary text-inverse focus:ring-2 focus:ring-brand-500 focus:ring-offset-2"; // default primary
|
|
71
|
+
: "bg-action-primary text-inverse hover:bg-action-primary-hover active:bg-action-primary-active focus:ring-2 focus:ring-brand-500 focus:ring-offset-2"; // default primary
|
|
45
72
|
});
|
|
46
73
|
|
|
47
|
-
// Button classes
|
|
74
|
+
// Button classes matching M3 design pattern
|
|
48
75
|
const buttonClasses = $derived(() => {
|
|
76
|
+
const sizeStyles = sizeClass();
|
|
49
77
|
const baseClasses =
|
|
50
|
-
"inline-flex items-center justify-center
|
|
78
|
+
"inline-flex items-center justify-center transition-all duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none focus:outline-none";
|
|
51
79
|
|
|
52
|
-
return `${baseClasses} ${
|
|
80
|
+
return `${baseClasses} ${sizeStyles.padding} ${sizeStyles.text} ${sizeStyles.font} ${sizeStyles.leading} ${sizeStyles.tracking} ${sizeStyles.radius} ${sizeStyles.gap} ${variantClass()}`.trim();
|
|
53
81
|
});
|
|
54
82
|
</script>
|
|
55
83
|
|
package/dist/atoms/Card.svelte
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
title?: string;
|
|
6
|
+
description?: string;
|
|
6
7
|
image?: string;
|
|
7
8
|
onclick?: (event: MouseEvent) => void | Promise<void>;
|
|
8
9
|
size?: "sm" | "md" | "lg";
|
|
@@ -12,6 +13,7 @@
|
|
|
12
13
|
|
|
13
14
|
let {
|
|
14
15
|
title = "",
|
|
16
|
+
description = "",
|
|
15
17
|
image = "",
|
|
16
18
|
onclick,
|
|
17
19
|
size = "md",
|
|
@@ -21,23 +23,41 @@
|
|
|
21
23
|
}: Props = $props();
|
|
22
24
|
|
|
23
25
|
const sizeClass = $derived(() => {
|
|
24
|
-
return size === "sm" ? "p-
|
|
26
|
+
return size === "sm" ? "p-4" : size === "lg" ? "p-8" : "p-6"; // default md
|
|
25
27
|
});
|
|
26
28
|
|
|
27
29
|
const cardClasses = $derived(() => {
|
|
28
30
|
const baseClasses =
|
|
29
|
-
"rounded-lg transition-all duration-200 min-w-64 bg-surface-
|
|
31
|
+
"rounded-lg transition-all duration-200 min-w-64 bg-surface-elevated shadow-sm";
|
|
30
32
|
const interactiveClasses = onclick
|
|
31
|
-
? "cursor-pointer hover:shadow-
|
|
33
|
+
? "cursor-pointer hover:shadow-lg hover:bg-surface-hover"
|
|
32
34
|
: "";
|
|
33
35
|
const widthClasses = fullWidth ? "w-full" : "";
|
|
34
36
|
|
|
35
37
|
return `${baseClasses} ${interactiveClasses} ${widthClasses} ${sizeClass()}`.trim();
|
|
36
38
|
});
|
|
37
39
|
|
|
38
|
-
const titleClasses = $derived(
|
|
39
|
-
(
|
|
40
|
-
|
|
40
|
+
const titleClasses = $derived(() => {
|
|
41
|
+
if (size === "sm") {
|
|
42
|
+
return "text-lg font-medium mb-2 text-headline";
|
|
43
|
+
} else if (size === "lg") {
|
|
44
|
+
return "text-2xl font-medium mb-4 text-headline";
|
|
45
|
+
} else {
|
|
46
|
+
// default md
|
|
47
|
+
return "text-xl font-medium mb-3 text-headline";
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const descriptionClasses = $derived(() => {
|
|
52
|
+
if (size === "sm") {
|
|
53
|
+
return "text-xs text-description mb-3";
|
|
54
|
+
} else if (size === "lg") {
|
|
55
|
+
return "text-base text-description mb-5";
|
|
56
|
+
} else {
|
|
57
|
+
// default md
|
|
58
|
+
return "text-sm text-description mb-4";
|
|
59
|
+
}
|
|
60
|
+
});
|
|
41
61
|
</script>
|
|
42
62
|
|
|
43
63
|
<div class={cardClasses()} {onclick} {...restProps}>
|
|
@@ -45,7 +65,7 @@
|
|
|
45
65
|
<img
|
|
46
66
|
src={image}
|
|
47
67
|
alt={title}
|
|
48
|
-
class="w-full h-48 object-cover rounded-
|
|
68
|
+
class="w-full h-48 object-cover rounded-lg mb-4"
|
|
49
69
|
/>
|
|
50
70
|
{/if}
|
|
51
71
|
|
|
@@ -53,6 +73,10 @@
|
|
|
53
73
|
<h3 class={titleClasses()}>{title}</h3>
|
|
54
74
|
{/if}
|
|
55
75
|
|
|
76
|
+
{#if description}
|
|
77
|
+
<p class={descriptionClasses()}>{description}</p>
|
|
78
|
+
{/if}
|
|
79
|
+
|
|
56
80
|
{#if children}
|
|
57
81
|
{@render children()}
|
|
58
82
|
{/if}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { onMount } from "svelte";
|
|
3
2
|
// SSR-safe ID generation
|
|
4
3
|
function generateId(prefix: string = "id"): string {
|
|
5
4
|
if (typeof window !== "undefined") {
|
|
@@ -22,39 +21,82 @@
|
|
|
22
21
|
name = "",
|
|
23
22
|
disabled = false,
|
|
24
23
|
label = "",
|
|
24
|
+
onchange,
|
|
25
25
|
...restProps
|
|
26
26
|
}: Props = $props();
|
|
27
27
|
|
|
28
28
|
// Generate unique ID - SSR safe (call directly, not in $state)
|
|
29
29
|
const checkboxId = generateId("checkbox");
|
|
30
30
|
|
|
31
|
-
// Checkbox classes
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
// Checkbox container classes matching M3 design
|
|
32
|
+
const checkboxContainerClasses = $derived(() => {
|
|
33
|
+
const baseClasses = "relative inline-flex items-center justify-center w-5 h-5 rounded transition-all duration-200";
|
|
34
|
+
|
|
35
|
+
if (disabled) {
|
|
36
|
+
return `${baseClasses} opacity-50 cursor-not-allowed`;
|
|
37
|
+
}
|
|
38
|
+
return `${baseClasses} cursor-pointer`;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Checkbox border and background classes matching M3 design
|
|
42
|
+
const checkboxBoxClasses = $derived(() => {
|
|
43
|
+
if (checked) {
|
|
44
|
+
return disabled
|
|
45
|
+
? "border-0 bg-brand-300"
|
|
46
|
+
: "border-0 bg-brand-600";
|
|
47
|
+
}
|
|
48
|
+
return disabled
|
|
49
|
+
? "border-2 border-stone-400 bg-transparent"
|
|
50
|
+
: "border-2 border-stone-400 bg-transparent";
|
|
51
|
+
});
|
|
36
52
|
|
|
37
53
|
function handleChange(event: Event) {
|
|
54
|
+
if (disabled) return;
|
|
38
55
|
const target = event.target as HTMLInputElement;
|
|
39
56
|
checked = target.checked;
|
|
57
|
+
if (onchange) {
|
|
58
|
+
onchange(event);
|
|
59
|
+
}
|
|
40
60
|
}
|
|
41
61
|
</script>
|
|
42
62
|
|
|
43
63
|
<div class="flex items-center gap-2">
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
<label
|
|
65
|
+
for={checkboxId}
|
|
66
|
+
class="flex items-center gap-2 cursor-pointer {disabled ? 'opacity-50 cursor-not-allowed' : ''}"
|
|
67
|
+
>
|
|
68
|
+
<div class={checkboxContainerClasses()}>
|
|
69
|
+
<input
|
|
70
|
+
type="checkbox"
|
|
71
|
+
id={checkboxId}
|
|
72
|
+
{name}
|
|
73
|
+
{checked}
|
|
74
|
+
{disabled}
|
|
75
|
+
class="sr-only"
|
|
76
|
+
onchange={handleChange}
|
|
77
|
+
{...restProps}
|
|
78
|
+
/>
|
|
79
|
+
<div class="absolute inset-0 {checkboxBoxClasses()} rounded"></div>
|
|
80
|
+
{#if checked}
|
|
81
|
+
<svg
|
|
82
|
+
class="absolute w-3 h-3 text-white pointer-events-none z-10"
|
|
83
|
+
fill="none"
|
|
84
|
+
stroke="currentColor"
|
|
85
|
+
viewBox="0 0 24 24"
|
|
86
|
+
>
|
|
87
|
+
<path
|
|
88
|
+
stroke-linecap="round"
|
|
89
|
+
stroke-linejoin="round"
|
|
90
|
+
stroke-width="2.5"
|
|
91
|
+
d="M5 13l4 4L19 7"
|
|
92
|
+
/>
|
|
93
|
+
</svg>
|
|
94
|
+
{/if}
|
|
95
|
+
</div>
|
|
96
|
+
{#if label}
|
|
97
|
+
<span class="text-sm font-medium text-label">
|
|
98
|
+
{label}
|
|
99
|
+
</span>
|
|
100
|
+
{/if}
|
|
101
|
+
</label>
|
|
60
102
|
</div>
|
package/dist/atoms/Input.svelte
CHANGED
|
@@ -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") {
|
|
@@ -17,6 +19,7 @@
|
|
|
17
19
|
disabled?: boolean;
|
|
18
20
|
size?: "sm" | "md" | "lg";
|
|
19
21
|
variant?: "default" | "success" | "warning" | "error";
|
|
22
|
+
message?: string;
|
|
20
23
|
oninput?: (event: Event) => void;
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -29,6 +32,7 @@
|
|
|
29
32
|
disabled = false,
|
|
30
33
|
size = "md",
|
|
31
34
|
variant = "default",
|
|
35
|
+
message = "",
|
|
32
36
|
oninput,
|
|
33
37
|
...restProps
|
|
34
38
|
}: Props = $props();
|
|
@@ -36,13 +40,28 @@
|
|
|
36
40
|
// Generate unique ID - SSR safe (call directly, not in $state)
|
|
37
41
|
const inputId = generateId("input");
|
|
38
42
|
|
|
39
|
-
// Size classes
|
|
43
|
+
// Size classes matching M3 design specifications
|
|
40
44
|
const sizeClass = $derived(() => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
if (size === "sm") {
|
|
46
|
+
return {
|
|
47
|
+
padding: "px-4 py-2",
|
|
48
|
+
text: "text-sm",
|
|
49
|
+
leading: "leading-5"
|
|
50
|
+
};
|
|
51
|
+
} else if (size === "lg") {
|
|
52
|
+
return {
|
|
53
|
+
padding: "px-4 py-3",
|
|
54
|
+
text: "text-base",
|
|
55
|
+
leading: "leading-6"
|
|
56
|
+
};
|
|
57
|
+
} else {
|
|
58
|
+
// default md
|
|
59
|
+
return {
|
|
60
|
+
padding: "px-4 py-2.5",
|
|
61
|
+
text: "text-base",
|
|
62
|
+
leading: "leading-6"
|
|
63
|
+
};
|
|
64
|
+
}
|
|
46
65
|
});
|
|
47
66
|
|
|
48
67
|
// Variant classes using semantic colors
|
|
@@ -53,15 +72,16 @@
|
|
|
53
72
|
? "border-warning focus:border-warning focus:ring-warning"
|
|
54
73
|
: variant === "error"
|
|
55
74
|
? "border-error focus:border-error focus:ring-error"
|
|
56
|
-
: "border-
|
|
75
|
+
: "border-0 focus:ring-2 focus:ring-brand-500"; // default - no border
|
|
57
76
|
});
|
|
58
77
|
|
|
59
|
-
// Input classes
|
|
78
|
+
// Input classes matching M3 design
|
|
60
79
|
const inputClasses = $derived(() => {
|
|
80
|
+
const sizeStyles = sizeClass();
|
|
61
81
|
const baseClasses =
|
|
62
|
-
"w-full
|
|
82
|
+
"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";
|
|
63
83
|
|
|
64
|
-
return `${baseClasses} ${
|
|
84
|
+
return `${baseClasses} ${sizeStyles.padding} ${sizeStyles.text} ${sizeStyles.leading} ${variantClass()}`.trim();
|
|
65
85
|
});
|
|
66
86
|
|
|
67
87
|
// Label classes using semantic text colors
|
|
@@ -69,6 +89,26 @@
|
|
|
69
89
|
() => "block text-sm font-medium text-label mb-1",
|
|
70
90
|
);
|
|
71
91
|
|
|
92
|
+
// Message classes based on variant
|
|
93
|
+
const messageClasses = $derived(() => {
|
|
94
|
+
if (variant === "error") {
|
|
95
|
+
return "text-error text-sm mt-1 flex items-center gap-1.5";
|
|
96
|
+
} else if (variant === "success") {
|
|
97
|
+
return "text-success text-sm mt-1 flex items-center gap-1.5";
|
|
98
|
+
} else if (variant === "warning") {
|
|
99
|
+
return "text-warning text-sm mt-1 flex items-center gap-1.5";
|
|
100
|
+
}
|
|
101
|
+
return "text-description text-sm mt-1 flex items-center gap-1.5";
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Get icon component based on variant
|
|
105
|
+
const getIcon = $derived(() => {
|
|
106
|
+
if (variant === "error") return AlertCircle;
|
|
107
|
+
if (variant === "success") return CheckCircle;
|
|
108
|
+
if (variant === "warning") return AlertTriangle;
|
|
109
|
+
return null;
|
|
110
|
+
});
|
|
111
|
+
|
|
72
112
|
function handleInput(event: Event) {
|
|
73
113
|
const target = event.target as HTMLInputElement;
|
|
74
114
|
value = target.value;
|
|
@@ -93,6 +133,17 @@
|
|
|
93
133
|
{disabled}
|
|
94
134
|
class={inputClasses()}
|
|
95
135
|
oninput={handleInput}
|
|
136
|
+
aria-invalid={variant === "error" ? "true" : undefined}
|
|
137
|
+
aria-describedby={message ? `${inputId}-message` : undefined}
|
|
96
138
|
{...restProps}
|
|
97
139
|
/>
|
|
140
|
+
{#if message && variant !== "default"}
|
|
141
|
+
<p id={`${inputId}-message`} class={messageClasses()} role="alert">
|
|
142
|
+
{#if getIcon()}
|
|
143
|
+
{@const Icon = getIcon()}
|
|
144
|
+
<Icon size={14} class="shrink-0" />
|
|
145
|
+
{/if}
|
|
146
|
+
<span>{message}</span>
|
|
147
|
+
</p>
|
|
148
|
+
{/if}
|
|
98
149
|
</div>
|