@imaginario27/air-ui-ds 1.0.22 → 1.1.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.
- package/components/accordions/AccordionItem.vue +1 -1
- package/components/alerts/Alert.vue +19 -22
- package/components/badges/Badge.vue +32 -25
- package/components/badges/IconBadge.vue +7 -7
- package/components/badges/IconTextBadge.vue +2 -2
- package/components/breadcrumbs/Breadcrumbs.vue +92 -27
- package/components/buttons/ActionButton.vue +34 -68
- package/components/buttons/ActionIconButton.vue +11 -39
- package/components/buttons/AlertButton.vue +8 -13
- package/components/buttons/AlertIconButton.vue +6 -7
- package/components/buttons/CopyButton.vue +4 -4
- package/components/buttons/options/OptionButton.vue +2 -2
- package/components/buttons/toggle/ToggleButton.vue +8 -10
- package/components/cards/specific/ContactDetailsCard.vue +4 -8
- package/components/cards/specific/FeatureCard.vue +2 -2
- package/components/cards/specific/HelpTopicCard.vue +4 -4
- package/components/cards/specific/subscription/SubscriptionPlanCard.vue +6 -6
- package/components/cards/specific/subscription/UniqueSubscriptionPlanCard.vue +1 -1
- package/components/collapsibles/Collapsible.vue +1 -1
- package/components/content/ContentItem.vue +2 -2
- package/components/content/ContentItemImage.vue +12 -14
- package/components/dropdowns/DropdownMenuItem.vue +10 -10
- package/components/dropdowns/DropdownSelect.vue +5 -16
- package/components/dropdowns/DropdownSelectItem.vue +13 -23
- package/components/empty-states/EmptyState.vue +21 -27
- package/components/features/Feature.vue +11 -48
- package/components/forms/fields/ButtonField.vue +2 -9
- package/components/forms/fields/CheckboxField.vue +9 -8
- package/components/forms/fields/DataField.vue +1 -1
- package/components/forms/fields/FileUploadField.vue +6 -6
- package/components/forms/fields/InputField.vue +17 -28
- package/components/forms/fields/RepeaterField.vue +2 -2
- package/components/forms/fields/SearchField.vue +7 -10
- package/components/forms/fields/SliderField.vue +16 -19
- package/components/forms/fields/SwitchField.vue +12 -34
- package/components/forms/fields/TextareaField.vue +7 -5
- package/components/forms/fields/radio/RadioButtonField.vue +6 -7
- package/components/icons/ContainedIcon.vue +18 -15
- package/components/icons/Icon.vue +73 -0
- package/components/layouts/ErrorDisplay.vue +3 -3
- package/components/layouts/headers/CompactHeader.vue +4 -4
- package/components/layouts/headers/ContentPageHeader.vue +1 -1
- package/components/lists/List.vue +1 -1
- package/components/lists/ListItem.vue +11 -14
- package/components/loaders/LoadingScreen.vue +3 -3
- package/components/modals/DangerModalDialog.vue +4 -4
- package/components/modals/InfoModalDialog.vue +3 -3
- package/components/modals/ModalDialog.vue +1 -1
- package/components/modals/SuccessModalDialog.vue +2 -2
- package/components/navigation/links/NavLink.vue +10 -10
- package/components/navigation/nav-sidebar/BottomUserNavBar.vue +3 -3
- package/components/navigation/nav-sidebar/NavSidebar.vue +9 -9
- package/components/navigation/nav-sidebar/NavSidebarMenuItem.vue +7 -9
- package/components/navigation/nav-sidebar/NavSidebarMenuSectionTitle.vue +4 -5
- package/components/pagination/ButtonPagination.vue +6 -10
- package/components/pagination/SimplePagination.vue +2 -2
- package/components/password/SecurePasswordCondition.vue +5 -6
- package/components/rating/InteractiveRating.vue +6 -6
- package/components/rating/Rating.vue +6 -6
- package/components/rating/RatingItem.vue +12 -13
- package/components/steppers/CircleStepper.vue +11 -13
- package/components/steppers/Step.vue +2 -2
- package/components/steppers/StepIndicator.vue +29 -28
- package/components/steppers/TabStepper.vue +1 -1
- package/components/steppers/vertical-stepper/VerticalStep.vue +2 -2
- package/components/steppers/vertical-stepper/VerticalStepper.vue +1 -1
- package/components/tabs/Tab.vue +4 -9
- package/models/enums/dropdowns.ts +1 -0
- package/models/enums/icons.ts +19 -0
- package/models/types/buttons.ts +1 -1
- package/models/types/icons.ts +6 -0
- package/models/types/selects.ts +1 -2
- package/nuxt.config.ts +8 -1
- package/package.json +2 -2
- package/components/navigation/nav-menu/NavFooterMenu.vue +0 -90
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<!-- This button does not have click event because the toggle is being controlled by the accordeon header div-->
|
|
9
9
|
<ActionIconButton
|
|
10
|
-
:icon="isOpen ? '
|
|
10
|
+
:icon="isOpen ? 'mdi:minus' : 'mdi:plus'"
|
|
11
11
|
:styleType="ButtonStyleType.NEUTRAL_TRANSPARENT"
|
|
12
12
|
:size="ButtonSize.MD"
|
|
13
13
|
/>
|
|
@@ -10,12 +10,11 @@
|
|
|
10
10
|
]"
|
|
11
11
|
>
|
|
12
12
|
<template v-if="description">
|
|
13
|
-
<
|
|
14
|
-
:
|
|
15
|
-
|
|
16
|
-
preserveAspectRatio="xMidYMid meet"
|
|
17
|
-
:class="['min-w-[20px]', iconColorClass]"
|
|
13
|
+
<Icon
|
|
14
|
+
:name="iconType"
|
|
15
|
+
:iconClass="iconColorClass"
|
|
18
16
|
/>
|
|
17
|
+
|
|
19
18
|
<div
|
|
20
19
|
:class="[
|
|
21
20
|
'w-full flex flex-col gap-2',
|
|
@@ -50,11 +49,9 @@
|
|
|
50
49
|
<template v-else>
|
|
51
50
|
<div class="w-full flex gap-3">
|
|
52
51
|
<div class="w-full flex gap-3 pt-1.5">
|
|
53
|
-
<
|
|
54
|
-
:
|
|
55
|
-
|
|
56
|
-
preserveAspectRatio="xMidYMid meet"
|
|
57
|
-
:class="['min-w-[20px]', iconColorClass]"
|
|
52
|
+
<Icon
|
|
53
|
+
:name="iconType"
|
|
54
|
+
:iconClass="iconColorClass"
|
|
58
55
|
/>
|
|
59
56
|
<span :class="['text-sm font-semibold', textColorClass]">
|
|
60
57
|
{{ title }}
|
|
@@ -83,7 +80,7 @@
|
|
|
83
80
|
<AlertIconButton
|
|
84
81
|
v-if="hasCloseButton"
|
|
85
82
|
:type
|
|
86
|
-
icon="
|
|
83
|
+
icon="mdi:close"
|
|
87
84
|
@click="$emit('close')"
|
|
88
85
|
/>
|
|
89
86
|
</div>
|
|
@@ -99,7 +96,7 @@ const props = defineProps({
|
|
|
99
96
|
default: AlertType.WARNING,
|
|
100
97
|
validator: (value: AlertType) => Object.values(AlertType).includes(value),
|
|
101
98
|
},
|
|
102
|
-
icon: String as PropType<
|
|
99
|
+
icon: String as PropType<string>,
|
|
103
100
|
title: {
|
|
104
101
|
type: String as PropType<string>,
|
|
105
102
|
default: 'Title',
|
|
@@ -129,7 +126,7 @@ const containerClass = computed(() => {
|
|
|
129
126
|
const textColorClass = computed(() => {
|
|
130
127
|
const variant = {
|
|
131
128
|
[AlertType.WARNING]: 'text-text-warning-on-bg',
|
|
132
|
-
[AlertType.DANGER]: 'text-
|
|
129
|
+
[AlertType.DANGER]: 'text-icon-danger',
|
|
133
130
|
[AlertType.SUCCESS]: 'text-text-success',
|
|
134
131
|
[AlertType.INFO]: 'text-text-info',
|
|
135
132
|
}
|
|
@@ -138,22 +135,22 @@ const textColorClass = computed(() => {
|
|
|
138
135
|
|
|
139
136
|
const iconColorClass = computed(() => {
|
|
140
137
|
const variant = {
|
|
141
|
-
[AlertType.WARNING]: 'text-icon-warning-on-bg',
|
|
142
|
-
[AlertType.DANGER]: 'text-icon-danger',
|
|
143
|
-
[AlertType.SUCCESS]: 'text-icon-success',
|
|
138
|
+
[AlertType.WARNING]: '!text-icon-warning-on-bg',
|
|
139
|
+
[AlertType.DANGER]: '!text-icon-danger',
|
|
140
|
+
[AlertType.SUCCESS]: '!text-icon-success',
|
|
144
141
|
[AlertType.INFO]: 'text-icon-info',
|
|
145
142
|
}
|
|
146
|
-
return variant[props.type as AlertType] || 'text-icon-warning-on-bg'
|
|
143
|
+
return variant[props.type as AlertType] || '!text-icon-warning-on-bg'
|
|
147
144
|
})
|
|
148
145
|
|
|
149
146
|
const iconType = computed(() => {
|
|
150
147
|
const variant = {
|
|
151
|
-
[AlertType.WARNING]: '
|
|
152
|
-
[AlertType.DANGER]: '
|
|
153
|
-
[AlertType.SUCCESS]: '
|
|
154
|
-
[AlertType.INFO]: '
|
|
148
|
+
[AlertType.WARNING]: 'mdi:alert-outline',
|
|
149
|
+
[AlertType.DANGER]: 'mdi:close-octagon-outline',
|
|
150
|
+
[AlertType.SUCCESS]: 'mdi:check-circle-outline',
|
|
151
|
+
[AlertType.INFO]: 'mdi:information-outline',
|
|
155
152
|
}
|
|
156
|
-
return variant[props.type as AlertType] as
|
|
153
|
+
return variant[props.type as AlertType] as string || 'mdi:alert-outline'
|
|
157
154
|
})
|
|
158
155
|
|
|
159
156
|
</script>
|
|
@@ -17,29 +17,36 @@
|
|
|
17
17
|
/>
|
|
18
18
|
|
|
19
19
|
<!-- Icon -->
|
|
20
|
-
<
|
|
20
|
+
<Icon
|
|
21
21
|
v-if="showIcon"
|
|
22
|
-
:
|
|
23
|
-
size="
|
|
24
|
-
|
|
25
|
-
:class="iconColorClass"
|
|
22
|
+
:name="icon"
|
|
23
|
+
:size="IconSize.XS"
|
|
24
|
+
:iconClass="iconColorClass"
|
|
26
25
|
/>
|
|
27
26
|
|
|
28
27
|
<!-- Text -->
|
|
29
28
|
<span :class="textClass">{{ text }}</span>
|
|
30
29
|
|
|
31
30
|
<!-- Close button -->
|
|
32
|
-
<
|
|
31
|
+
<div
|
|
33
32
|
v-if="closeable"
|
|
34
|
-
|
|
35
|
-
@click="emitClose"
|
|
33
|
+
class="ml-1 h-[24px] flex items-center"
|
|
36
34
|
>
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
<button
|
|
36
|
+
class="flex items-center justify-center h-full w-[20px]"
|
|
37
|
+
:class="[
|
|
38
|
+
textClass,
|
|
39
|
+
'hover:opacity-75 focus:outline-none',
|
|
40
|
+
]"
|
|
41
|
+
@click="emitClose"
|
|
42
|
+
>
|
|
43
|
+
<Icon
|
|
44
|
+
name="mdi:close"
|
|
45
|
+
:size="IconSize.SM"
|
|
46
|
+
:iconClass="iconColorClass"
|
|
47
|
+
/>
|
|
48
|
+
</button>
|
|
49
|
+
</div>
|
|
43
50
|
</div>
|
|
44
51
|
</template>
|
|
45
52
|
|
|
@@ -82,8 +89,8 @@ const props = defineProps({
|
|
|
82
89
|
default: 'Badge',
|
|
83
90
|
},
|
|
84
91
|
icon: {
|
|
85
|
-
type: String as PropType<
|
|
86
|
-
default: '
|
|
92
|
+
type: String as PropType<string>,
|
|
93
|
+
default: 'mdi:help',
|
|
87
94
|
},
|
|
88
95
|
})
|
|
89
96
|
|
|
@@ -172,19 +179,19 @@ const textClass = computed(() => {
|
|
|
172
179
|
})
|
|
173
180
|
|
|
174
181
|
const iconColorClass = computed(() => {
|
|
175
|
-
if (props.styleType === BadgeStyle.FILLED) return "text-text-neutral-on-filled"
|
|
182
|
+
if (props.styleType === BadgeStyle.FILLED) return "!text-text-neutral-on-filled"
|
|
176
183
|
|
|
177
184
|
const iconVariant: Record<ColorAccent, string> = {
|
|
178
|
-
[ColorAccent.NEUTRAL]: "text-icon-neutral-subtle",
|
|
179
|
-
[ColorAccent.SUCCESS]: "text-icon-success",
|
|
180
|
-
[ColorAccent.WARNING]: props.isTransparent ? "text-icon-warning" : "text-icon-warning-on-bg",
|
|
181
|
-
[ColorAccent.DANGER]: "text-icon-danger",
|
|
182
|
-
[ColorAccent.INFO]: "text-icon-info",
|
|
183
|
-
[ColorAccent.PRIMARY_BRAND]: "text-icon-primary-brand-default",
|
|
184
|
-
[ColorAccent.SECONDARY_BRAND]: "text-icon-secondary-brand-default",
|
|
185
|
+
[ColorAccent.NEUTRAL]: "!text-icon-neutral-subtle",
|
|
186
|
+
[ColorAccent.SUCCESS]: "!text-icon-success",
|
|
187
|
+
[ColorAccent.WARNING]: props.isTransparent ? "!text-icon-warning" : "!text-icon-warning-on-bg",
|
|
188
|
+
[ColorAccent.DANGER]: "!text-icon-danger",
|
|
189
|
+
[ColorAccent.INFO]: "!text-icon-info",
|
|
190
|
+
[ColorAccent.PRIMARY_BRAND]: "!text-icon-primary-brand-default",
|
|
191
|
+
[ColorAccent.SECONDARY_BRAND]: "!text-icon-secondary-brand-default",
|
|
185
192
|
}
|
|
186
193
|
|
|
187
|
-
return iconVariant[props.color as ColorAccent] || "text-icon-secondary"
|
|
194
|
+
return iconVariant[props.color as ColorAccent] || "!text-icon-secondary"
|
|
188
195
|
})
|
|
189
196
|
|
|
190
197
|
const dotColorClass = computed(() => {
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
colorClass
|
|
6
6
|
]"
|
|
7
7
|
>
|
|
8
|
-
<
|
|
9
|
-
v-if="icon"
|
|
10
|
-
:icon
|
|
11
|
-
size="
|
|
12
|
-
:
|
|
8
|
+
<Icon
|
|
9
|
+
v-if="icon"
|
|
10
|
+
:name="icon"
|
|
11
|
+
:size="IconSize.SM"
|
|
12
|
+
:iconClass="iconColorClass"
|
|
13
13
|
/>
|
|
14
14
|
</div>
|
|
15
15
|
</template>
|
|
@@ -23,8 +23,8 @@ const props = defineProps({
|
|
|
23
23
|
validator: (value: ColorAccent) => Object.values(ColorAccent).includes(value),
|
|
24
24
|
},
|
|
25
25
|
icon: {
|
|
26
|
-
type: String as PropType<
|
|
27
|
-
default: '
|
|
26
|
+
type: String as PropType<string>,
|
|
27
|
+
default: 'mdi:help',
|
|
28
28
|
},
|
|
29
29
|
})
|
|
30
30
|
|
|
@@ -1,54 +1,119 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<nav aria-label="breadcrumb">
|
|
3
|
-
<ul
|
|
3
|
+
<ul
|
|
4
|
+
:class="[
|
|
5
|
+
'flex items-center space-x-2 text-icon-neutral-subtler',
|
|
6
|
+
]"
|
|
7
|
+
>
|
|
4
8
|
<!-- Home Link -->
|
|
5
|
-
<li>
|
|
9
|
+
<li v-if="showHome">
|
|
6
10
|
<NuxtLink to="/" class="flex items-center space-x-1">
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
<Icon
|
|
12
|
+
:name="homeIcon"
|
|
13
|
+
:iconClass="[
|
|
14
|
+
'text-icon-neutral-subtler hover:text-icon-neutral-on-monochrome-hover-bg',
|
|
15
|
+
homeIconClass,
|
|
16
|
+
]"
|
|
12
17
|
/>
|
|
13
18
|
</NuxtLink>
|
|
14
19
|
</li>
|
|
15
20
|
|
|
16
|
-
<!-- Dynamic Breadcrumbs
|
|
17
|
-
<li
|
|
21
|
+
<!-- Dynamic Breadcrumbs -->
|
|
22
|
+
<li
|
|
23
|
+
v-for="(crumb, index) in displayedBreadcrumbs"
|
|
24
|
+
:key="index"
|
|
25
|
+
class="flex items-center space-x-2"
|
|
26
|
+
>
|
|
18
27
|
<!-- Chevron Separator -->
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
<Icon
|
|
29
|
+
v-if="index > 0 || showHome"
|
|
30
|
+
:name="separatorIcon"
|
|
31
|
+
:iconClass="[
|
|
32
|
+
'text-icon-neutral-subtler',
|
|
33
|
+
separatorClass,
|
|
34
|
+
]"
|
|
24
35
|
/>
|
|
25
36
|
|
|
26
|
-
<!-- Breadcrumb
|
|
27
|
-
<
|
|
28
|
-
:
|
|
29
|
-
|
|
37
|
+
<!-- Breadcrumb (active or not) -->
|
|
38
|
+
<component
|
|
39
|
+
:is="crumb.isCurrent ? 'span' : NuxtLink"
|
|
40
|
+
:to="!crumb.isCurrent ? crumb.to : undefined"
|
|
41
|
+
:class="[
|
|
42
|
+
'text-sm',
|
|
43
|
+
crumb.isCurrent
|
|
44
|
+
? currentCrumbClass || 'text-text-default'
|
|
45
|
+
: 'text-text-neutral-subtler hover:text-text-neutral-on-monochrome-hover-bg',
|
|
46
|
+
crumbClass,
|
|
47
|
+
]"
|
|
30
48
|
>
|
|
31
49
|
{{ crumb.label }}
|
|
32
|
-
</
|
|
50
|
+
</component>
|
|
33
51
|
</li>
|
|
34
52
|
</ul>
|
|
35
53
|
</nav>
|
|
36
54
|
</template>
|
|
55
|
+
|
|
37
56
|
<script setup lang="ts">
|
|
57
|
+
// Imports
|
|
58
|
+
import { NuxtLink } from '#components'
|
|
59
|
+
|
|
60
|
+
// Props
|
|
61
|
+
const props = defineProps({
|
|
62
|
+
showHome: {
|
|
63
|
+
type: Boolean as PropType<boolean>,
|
|
64
|
+
default: true,
|
|
65
|
+
},
|
|
66
|
+
homeIcon: {
|
|
67
|
+
type: String as PropType<string>,
|
|
68
|
+
default: 'mdi:home-outline',
|
|
69
|
+
},
|
|
70
|
+
separatorIcon: {
|
|
71
|
+
type: String as PropType<string>,
|
|
72
|
+
default: 'mdi:chevron-right',
|
|
73
|
+
},
|
|
74
|
+
includeCurrent: {
|
|
75
|
+
type: Boolean as PropType<boolean>,
|
|
76
|
+
default: false,
|
|
77
|
+
},
|
|
78
|
+
homeIconClass: {
|
|
79
|
+
type: String as PropType<string>,
|
|
80
|
+
default: '',
|
|
81
|
+
},
|
|
82
|
+
separatorClass: {
|
|
83
|
+
type: String as PropType<string>,
|
|
84
|
+
default: '',
|
|
85
|
+
},
|
|
86
|
+
crumbClass: {
|
|
87
|
+
type: String as PropType<string>,
|
|
88
|
+
default: '',
|
|
89
|
+
},
|
|
90
|
+
currentCrumbClass: {
|
|
91
|
+
type: String as PropType<string>,
|
|
92
|
+
default: '',
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
|
|
38
96
|
// Route
|
|
39
97
|
const route = useRoute()
|
|
40
98
|
|
|
41
|
-
// Generate breadcrumbs from route
|
|
42
|
-
const
|
|
43
|
-
const pathSegments = route.path.split('/').filter(Boolean)
|
|
44
|
-
|
|
45
|
-
if (pathSegments.length <= 1) return [] // Stop at Home if only 1 segment
|
|
99
|
+
// Generate all breadcrumbs from route segments
|
|
100
|
+
const allCrumbs = computed(() => {
|
|
101
|
+
const pathSegments = route.path.split('/').filter(Boolean)
|
|
46
102
|
|
|
47
|
-
return pathSegments.
|
|
103
|
+
return pathSegments.map((segment, index) => {
|
|
48
104
|
return {
|
|
49
|
-
label: segment
|
|
50
|
-
|
|
105
|
+
label: segment
|
|
106
|
+
.replace(/-/g, ' ')
|
|
107
|
+
.replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
108
|
+
to: '/' + pathSegments.slice(0, index + 1).join('/'),
|
|
109
|
+
isCurrent: index === pathSegments.length - 1,
|
|
51
110
|
}
|
|
52
111
|
})
|
|
53
112
|
})
|
|
113
|
+
|
|
114
|
+
// Filter crumbs based on `includeCurrent`
|
|
115
|
+
const displayedBreadcrumbs = computed(() => {
|
|
116
|
+
if (props.includeCurrent) return allCrumbs.value
|
|
117
|
+
return allCrumbs.value.slice(0, -1)
|
|
118
|
+
})
|
|
54
119
|
</script>
|
|
@@ -27,10 +27,9 @@
|
|
|
27
27
|
<!-- Loading State -->
|
|
28
28
|
<template v-if="isLoading">
|
|
29
29
|
<div class="animate-spin">
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
:class="iconSizeClass"
|
|
30
|
+
<Icon
|
|
31
|
+
name="mdi:loading"
|
|
32
|
+
:iconClass="iconSizeClass"
|
|
34
33
|
/>
|
|
35
34
|
</div>
|
|
36
35
|
|
|
@@ -43,21 +42,15 @@
|
|
|
43
42
|
<template v-else>
|
|
44
43
|
<!-- Left icon -->
|
|
45
44
|
<template v-if="iconPosition === IconPosition.LEFT">
|
|
46
|
-
<
|
|
47
|
-
v-if="icon
|
|
48
|
-
:icon
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
<Icon
|
|
46
|
+
v-if="icon"
|
|
47
|
+
:name="icon"
|
|
48
|
+
:iconClass="[
|
|
49
|
+
iconSizeClass,
|
|
50
|
+
iconColorClass,
|
|
51
|
+
iconClass ? iconClass : ''
|
|
52
|
+
]"
|
|
51
53
|
/>
|
|
52
|
-
<span
|
|
53
|
-
v-else-if="svgIcon"
|
|
54
|
-
:class="[iconSizeClass, iconClass ]"
|
|
55
|
-
>
|
|
56
|
-
<SVGImage
|
|
57
|
-
:src="svgIcon"
|
|
58
|
-
:color="resolvedSvgIconColor"
|
|
59
|
-
/>
|
|
60
|
-
</span>
|
|
61
54
|
</template>
|
|
62
55
|
|
|
63
56
|
<span :class="[ 'font-semibold', textSizeClass, textClass ]">
|
|
@@ -66,21 +59,15 @@
|
|
|
66
59
|
|
|
67
60
|
<!-- Right icon -->
|
|
68
61
|
<template v-if="iconPosition === IconPosition.RIGHT">
|
|
69
|
-
<
|
|
62
|
+
<Icon
|
|
70
63
|
v-if="icon"
|
|
71
|
-
:
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
:name="icon"
|
|
65
|
+
:iconClass="[
|
|
66
|
+
iconSizeClass,
|
|
67
|
+
iconColorClass,
|
|
68
|
+
iconClass ? iconClass : ''
|
|
69
|
+
]"
|
|
74
70
|
/>
|
|
75
|
-
<span
|
|
76
|
-
v-else-if="svgIcon"
|
|
77
|
-
:class="[iconSizeClass, iconClass]"
|
|
78
|
-
>
|
|
79
|
-
<SVGImage
|
|
80
|
-
:src="svgIcon"
|
|
81
|
-
:color="resolvedSvgIconColor"
|
|
82
|
-
/>
|
|
83
|
-
</span>
|
|
84
71
|
</template>
|
|
85
72
|
</template>
|
|
86
73
|
</component>
|
|
@@ -124,19 +111,14 @@ const props = defineProps({
|
|
|
124
111
|
validator: (value: ButtonSize) => Object.values(ButtonSize).includes(value),
|
|
125
112
|
},
|
|
126
113
|
icon: {
|
|
127
|
-
type: String as PropType<
|
|
128
|
-
default: "
|
|
114
|
+
type: String as PropType<string>,
|
|
115
|
+
default: "mdi:help"
|
|
129
116
|
},
|
|
130
117
|
iconPosition: {
|
|
131
118
|
type: String as PropType<IconPosition>,
|
|
132
119
|
default: IconPosition.NONE,
|
|
133
120
|
validator: (value: IconPosition) => Object.values(IconPosition).includes(value),
|
|
134
121
|
},
|
|
135
|
-
svgIcon: String as PropType<string>,
|
|
136
|
-
useSVGIconColor: {
|
|
137
|
-
type: Boolean as PropType<boolean>,
|
|
138
|
-
default: false,
|
|
139
|
-
},
|
|
140
122
|
iconClass: String as PropType<string>,
|
|
141
123
|
disabled: {
|
|
142
124
|
type: Boolean as PropType<boolean>,
|
|
@@ -318,14 +300,23 @@ const iconSizeClass = computed(() => {
|
|
|
318
300
|
return variant[props.size as ButtonSize] || 'w-[20px] h-[20px] min-w-[20px] min-h-[20px]'
|
|
319
301
|
})
|
|
320
302
|
|
|
321
|
-
const
|
|
303
|
+
const textSizeClass = computed(() => {
|
|
304
|
+
const variant = {
|
|
305
|
+
[ButtonSize.XS]: 'text-xs',
|
|
306
|
+
[ButtonSize.SM]: 'text-sm',
|
|
307
|
+
[ButtonSize.MD]: 'text-sm',
|
|
308
|
+
[ButtonSize.LG]: 'text-sm',
|
|
309
|
+
[ButtonSize.XL]: 'text-sm',
|
|
310
|
+
[ButtonSize.XXL]: 'text-base',
|
|
311
|
+
}
|
|
312
|
+
return variant[props.size as ButtonSize] || 'text-sm'
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
const iconColorClass = computed(() => {
|
|
322
316
|
const variant = {
|
|
323
317
|
[ButtonStyleType.PRIMARY_BRAND_FILLED]: 'text-text-neutral-on-filled',
|
|
324
318
|
[ButtonStyleType.PRIMARY_BRAND_SOFT]: 'text-icon-primary-brand-on-soft-bg',
|
|
325
|
-
[ButtonStyleType.PRIMARY_BRAND_TRANSPARENT]:
|
|
326
|
-
'text-text-primary-brand-default',
|
|
327
|
-
!props.disabled && 'hover:text-text-primary-brand-hover',
|
|
328
|
-
],
|
|
319
|
+
[ButtonStyleType.PRIMARY_BRAND_TRANSPARENT]: 'text-text-primary-brand-default',
|
|
329
320
|
[ButtonStyleType.SECONDARY_BRAND_FILLED]: 'text-text-neutral-on-filled',
|
|
330
321
|
[ButtonStyleType.NEUTRAL_FILLED]: 'text-text-neutral-on-neutral-filled-bg',
|
|
331
322
|
[ButtonStyleType.NEUTRAL_OUTLINED]: 'text-text-default',
|
|
@@ -339,18 +330,6 @@ const svgIconColorClass = computed(() => {
|
|
|
339
330
|
return variant[props.styleType as ButtonStyleType] || 'text-text-default'
|
|
340
331
|
})
|
|
341
332
|
|
|
342
|
-
const textSizeClass = computed(() => {
|
|
343
|
-
const variant = {
|
|
344
|
-
[ButtonSize.XS]: 'text-xs',
|
|
345
|
-
[ButtonSize.SM]: 'text-sm',
|
|
346
|
-
[ButtonSize.MD]: 'text-sm',
|
|
347
|
-
[ButtonSize.LG]: 'text-sm',
|
|
348
|
-
[ButtonSize.XL]: 'text-sm',
|
|
349
|
-
[ButtonSize.XXL]: 'text-base',
|
|
350
|
-
}
|
|
351
|
-
return variant[props.size as ButtonSize] || 'text-sm'
|
|
352
|
-
})
|
|
353
|
-
|
|
354
333
|
const horizontalPaddingClass = computed(() => {
|
|
355
334
|
const variant = {
|
|
356
335
|
[ButtonSize.XS]: 'px-2',
|
|
@@ -375,19 +354,6 @@ const gapClass = computed(() => {
|
|
|
375
354
|
return variant[props.size as ButtonSize] || 'gap-2'
|
|
376
355
|
})
|
|
377
356
|
|
|
378
|
-
// Computed functions
|
|
379
|
-
const resolvedSvgIconColor = computed(() => {
|
|
380
|
-
if (props.useSVGIconColor) return undefined
|
|
381
|
-
|
|
382
|
-
const val = svgIconColorClass.value
|
|
383
|
-
|
|
384
|
-
if (Array.isArray(val)) {
|
|
385
|
-
return val.filter(Boolean).join(' ')
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
return val
|
|
389
|
-
})
|
|
390
|
-
|
|
391
357
|
// Props for the dynamic component
|
|
392
358
|
const componentProps = computed(() => {
|
|
393
359
|
if (props.actionType === ButtonActionType.LINK) {
|
|
@@ -18,21 +18,14 @@
|
|
|
18
18
|
:disabled="disabled"
|
|
19
19
|
|
|
20
20
|
>
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
:
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
<Icon
|
|
22
|
+
:name="icon"
|
|
23
|
+
:iconClass="[
|
|
24
|
+
iconSizeClass,
|
|
25
|
+
iconColorClass,
|
|
26
|
+
iconClass ? iconClass : ''
|
|
27
|
+
]"
|
|
26
28
|
/>
|
|
27
|
-
<span
|
|
28
|
-
v-else-if="svgIcon"
|
|
29
|
-
:class="[iconSizeClass, iconClass]"
|
|
30
|
-
>
|
|
31
|
-
<SVGImage
|
|
32
|
-
:src="svgIcon"
|
|
33
|
-
:color="resolvedSvgIconColor"
|
|
34
|
-
/>
|
|
35
|
-
</span>
|
|
36
29
|
</component>
|
|
37
30
|
</template>
|
|
38
31
|
|
|
@@ -69,13 +62,8 @@ const props = defineProps({
|
|
|
69
62
|
validator: (value: ButtonSize) => Object.values(ButtonSize).includes(value),
|
|
70
63
|
},
|
|
71
64
|
icon: {
|
|
72
|
-
type: String as PropType<
|
|
73
|
-
default: "
|
|
74
|
-
},
|
|
75
|
-
svgIcon: String as PropType<string>,
|
|
76
|
-
useSVGIconColor: {
|
|
77
|
-
type: Boolean as PropType<boolean>,
|
|
78
|
-
default: false
|
|
65
|
+
type: String as PropType<string>,
|
|
66
|
+
default: "mdi:help"
|
|
79
67
|
},
|
|
80
68
|
iconClass: String as PropType<string>,
|
|
81
69
|
disabled: {
|
|
@@ -242,14 +230,11 @@ const iconSizeClass = computed(() => {
|
|
|
242
230
|
return variant[props.size as ButtonSize] || 'w-[20px] h-[20px] min-w-[20px] min-h-[20px]'
|
|
243
231
|
})
|
|
244
232
|
|
|
245
|
-
const
|
|
233
|
+
const iconColorClass = computed(() => {
|
|
246
234
|
const variant = {
|
|
247
235
|
[ButtonStyleType.PRIMARY_BRAND_FILLED]: 'text-text-neutral-on-filled',
|
|
248
236
|
[ButtonStyleType.PRIMARY_BRAND_SOFT]: 'text-icon-primary-brand-on-soft-bg',
|
|
249
|
-
[ButtonStyleType.PRIMARY_BRAND_TRANSPARENT]:
|
|
250
|
-
'text-text-primary-brand-default',
|
|
251
|
-
!props.disabled && 'hover:text-text-primary-brand-hover',
|
|
252
|
-
],
|
|
237
|
+
[ButtonStyleType.PRIMARY_BRAND_TRANSPARENT]: 'text-text-primary-brand-default',
|
|
253
238
|
[ButtonStyleType.SECONDARY_BRAND_FILLED]: 'text-text-neutral-on-filled',
|
|
254
239
|
[ButtonStyleType.NEUTRAL_FILLED]: 'text-text-neutral-on-neutral-filled-bg',
|
|
255
240
|
[ButtonStyleType.NEUTRAL_OUTLINED]: 'text-text-default',
|
|
@@ -263,19 +248,6 @@ const svgIconColorClass = computed(() => {
|
|
|
263
248
|
return variant[props.styleType as ButtonStyleType] || 'text-text-default'
|
|
264
249
|
})
|
|
265
250
|
|
|
266
|
-
// Computed functions
|
|
267
|
-
const resolvedSvgIconColor = computed(() => {
|
|
268
|
-
if (props.useSVGIconColor) return undefined
|
|
269
|
-
|
|
270
|
-
const val = svgIconColorClass.value
|
|
271
|
-
|
|
272
|
-
if (Array.isArray(val)) {
|
|
273
|
-
return val.filter(Boolean).join(' ')
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return val
|
|
277
|
-
})
|
|
278
|
-
|
|
279
251
|
// Props for the dynamic component
|
|
280
252
|
const componentProps = computed(() => {
|
|
281
253
|
if (props.actionType === ButtonActionType.LINK) {
|
|
@@ -18,26 +18,21 @@
|
|
|
18
18
|
...(actionType === ButtonActionType.ACTION ? { onClick: emitClick } : {})
|
|
19
19
|
}"
|
|
20
20
|
:disabled
|
|
21
|
-
|
|
22
21
|
>
|
|
23
22
|
<!-- Left icon -->
|
|
24
|
-
<
|
|
23
|
+
<Icon
|
|
25
24
|
v-if="iconPosition === IconPosition.LEFT"
|
|
26
|
-
:icon
|
|
27
|
-
|
|
28
|
-
preserveAspectRatio="xMidYMid meet"
|
|
29
|
-
class="min-w-[20px]"
|
|
25
|
+
:name="icon"
|
|
26
|
+
:iconClass="textIconClass"
|
|
30
27
|
/>
|
|
31
28
|
<span :class="[ 'font-semibold' ]">
|
|
32
29
|
{{ text }}
|
|
33
30
|
</span>
|
|
34
31
|
<!-- Right icon -->
|
|
35
|
-
<
|
|
32
|
+
<Icon
|
|
36
33
|
v-if="iconPosition === IconPosition.RIGHT"
|
|
37
|
-
:icon
|
|
38
|
-
|
|
39
|
-
preserveAspectRatio="xMidYMid meet"
|
|
40
|
-
class="min-w-[20px]"
|
|
34
|
+
:name="icon"
|
|
35
|
+
:iconClass="textIconClass"
|
|
41
36
|
/>
|
|
42
37
|
</component>
|
|
43
38
|
</template>
|
|
@@ -68,8 +63,8 @@ const props = defineProps({
|
|
|
68
63
|
default: 'Button text'
|
|
69
64
|
},
|
|
70
65
|
icon: {
|
|
71
|
-
type: String as PropType<
|
|
72
|
-
default: "
|
|
66
|
+
type: String as PropType<string>,
|
|
67
|
+
default: "mdi:help"
|
|
73
68
|
},
|
|
74
69
|
iconPosition: {
|
|
75
70
|
type: String as PropType<IconPosition>,
|