@zap-wunschlachen/wl-shared-components 1.0.76 → 1.0.78
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/.github/workflows/playwright.yml +229 -229
- package/.github/workflows/static.yml +61 -61
- package/.github/workflows/update-snapshots.yml +37 -37
- package/.prettierrc.json +8 -8
- package/.storybook/main.ts +18 -18
- package/.storybook/preview.ts +37 -37
- package/.storybook/storyWrapper.vue +18 -18
- package/.storybook/withVuetifyTheme.decorator.ts +21 -21
- package/App.vue +139 -139
- package/README.md +56 -56
- package/docs/assets.md +62 -62
- package/heroicons.ts +75 -75
- package/index.html +19 -19
- package/package.json +71 -71
- package/playwright.config.ts +48 -48
- package/public/background.svg +60 -60
- package/public/style.css +187 -187
- package/public/technologies.svg +22 -22
- package/scripts/check-translations.ts +352 -352
- package/src/assets/css/base.css +242 -242
- package/src/assets/css/variables.css +176 -176
- package/src/components/Accordion/Accordion.css +65 -65
- package/src/components/Accordion/AccordionGroup.vue +88 -88
- package/src/components/Accordion/AccordionItem.vue +272 -272
- package/src/components/Accordion/presets/default.css +4 -4
- package/src/components/Accordion/presets/elevated.css +25 -25
- package/src/components/Accordion/presets/filled.css +26 -26
- package/src/components/Accordion/presets/index.css +5 -5
- package/src/components/Accordion/presets/plain.css +34 -34
- package/src/components/Appointment/Card/Actions.css +54 -54
- package/src/components/Appointment/Card/Actions.vue +99 -99
- package/src/components/Appointment/Card/AnamneseNotification.css +20 -20
- package/src/components/Appointment/Card/AnamneseNotification.vue +23 -23
- package/src/components/Appointment/Card/Card.css +99 -99
- package/src/components/Appointment/Card/Card.vue +97 -97
- package/src/components/Appointment/Card/Details.css +62 -62
- package/src/components/Appointment/Card/Details.vue +44 -44
- package/src/components/Audio/Audio.vue +187 -187
- package/src/components/Audio/Waveform.vue +118 -118
- package/src/components/Banner/Banner.css +29 -29
- package/src/components/Banner/Banner.vue +89 -89
- package/src/components/Button/Button.vue +257 -257
- package/src/components/CheckBox/CheckBox.css +234 -234
- package/src/components/CheckBox/Checkbox.vue +184 -184
- package/src/components/DateInput/DateInput.css +2 -2
- package/src/components/DateInput/DateInput.vue +376 -370
- package/src/components/Dialog/Dialog.css +6 -6
- package/src/components/Dialog/Dialog.vue +46 -46
- package/src/components/EditField/EditField.css +19 -19
- package/src/components/EditField/EditField.vue +211 -211
- package/src/components/ErrorPage/ErrorPage.css +172 -172
- package/src/components/IconBullet/IconBullet.vue +104 -104
- package/src/components/IconBullet/IconBulletList.vue +55 -55
- package/src/components/Icons/AdvanceAppointments.vue +161 -161
- package/src/components/Icons/Audio/CloudFailed.vue +27 -27
- package/src/components/Icons/Audio/CloudSaved.vue +28 -28
- package/src/components/Icons/Audio/Delete.vue +22 -22
- package/src/components/Icons/Audio/Pause.vue +25 -25
- package/src/components/Icons/Audio/Play.vue +22 -22
- package/src/components/Icons/Calendar.vue +28 -28
- package/src/components/Icons/CalendarNotification.vue +137 -137
- package/src/components/Icons/Chair.vue +43 -43
- package/src/components/Icons/ChairNotification.vue +46 -46
- package/src/components/Icons/Circle.vue +66 -66
- package/src/components/Icons/FavIcon.vue +69 -69
- package/src/components/Icons/FilledCircle.vue +11 -11
- package/src/components/Icons/Group3.vue +57 -57
- package/src/components/Icons/Play.vue +16 -16
- package/src/components/Icons/RingNotification.vue +65 -65
- package/src/components/Icons/SolidArrowRight.vue +14 -14
- package/src/components/Icons/checkbox.vue +19 -19
- package/src/components/Icons/outlineChecked.vue +38 -38
- package/src/components/Input/Input.css +234 -234
- package/src/components/Input/Input.vue +281 -281
- package/src/components/Laboratory/AppointmentCard/AppointmentCard.css +7 -7
- package/src/components/Laboratory/AppointmentCard/AppointmentCard.vue +116 -116
- package/src/components/Laboratory/ChatBoxImage/ChatBoxImage.vue +81 -81
- package/src/components/Laboratory/ChatMessage/ChatMessage.vue +113 -113
- package/src/components/Laboratory/ChatMessage/ChatMessageBadge.css +4 -4
- package/src/components/Laboratory/ChatMessage/ChatMessageBadge.vue +99 -99
- package/src/components/Laboratory/ChatNotification/ChatNotification.vue +130 -130
- package/src/components/Laboratory/DocumentCard/DocumentCard.css +3 -3
- package/src/components/Laboratory/DocumentCard/DocumentCard.vue +50 -50
- package/src/components/Laboratory/DocumentCard/DocumentCardItem.vue +53 -53
- package/src/components/Laboratory/InfoCard/InfoCard.vue +162 -162
- package/src/components/Laboratory/MainColumnsBar/MainColumnsBar.vue +102 -102
- package/src/components/Laboratory/ProgressCircle/ProgressCircle.vue +152 -152
- package/src/components/Laboratory/ProgressLinear/ProgressLinear.css +33 -33
- package/src/components/Laboratory/ProgressLinear/ProgressLinear.vue +75 -75
- package/src/components/Laboratory/SelectionColumnBar/SelectionColumnBar.vue +92 -92
- package/src/components/Laboratory/StatusNotification/StatusNotification.vue +49 -49
- package/src/components/Laboratory/TagLabel/TagLabel.vue +126 -126
- package/src/components/Laboratory/TagLabelGroup/TagLabelGroup.vue +97 -97
- package/src/components/Laboratory/TicketCard/TicketCard.css +3 -3
- package/src/components/Laboratory/TicketCard/TicketCard.vue +143 -143
- package/src/components/Laboratory/TimeLine/TimeLineEvent.css +18 -18
- package/src/components/Laboratory/TimeLine/TimeLineEvent.vue +119 -119
- package/src/components/Laboratory/TimeLine/Timeline.css +4 -4
- package/src/components/Laboratory/TimeLine/Timeline.vue +30 -30
- package/src/components/Loader/Loader.css +78 -78
- package/src/components/MaintenanceBanner/MaintenanceBanner.css +353 -353
- package/src/components/MaintenanceBanner/MaintenanceBanner.vue +140 -140
- package/src/components/MaintenanceBanner/MaintenanceIllustration.vue +54 -54
- package/src/components/Modal/Modal.css +5 -5
- package/src/components/Modal/Modal.vue +29 -29
- package/src/components/NotificationBubble/NotificationBubble.css +4 -4
- package/src/components/NotificationBubble/NotificationBubble.vue +90 -90
- package/src/components/OtpInput/OtpInput.css +43 -43
- package/src/components/OtpInput/OtpInput.vue +181 -181
- package/src/components/PhoneInput/PhoneInput.css +151 -126
- package/src/components/PhoneInput/PhoneInput.vue +230 -139
- package/src/components/RadioGroup/RadioGroup.css +65 -0
- package/src/components/RadioGroup/RadioGroup.vue +134 -0
- package/src/components/Select/Select.css +172 -172
- package/src/components/Select/Select.vue +377 -377
- package/src/components/SelectAutocomplete/SelectAutocomplete.css +172 -172
- package/src/components/SelectAutocomplete/SelectAutocomplete.vue +414 -414
- package/src/components/TextArea/TextArea.css +269 -269
- package/src/components/TextArea/TextArea.vue +207 -207
- package/src/components/TickBox/TickBox.css +116 -116
- package/src/components/TickBox/TickBox.vue +172 -172
- package/src/components/Tile/Tile.css +106 -106
- package/src/components/Tile/Tile.vue +173 -173
- package/src/components/accessibility.css +218 -218
- package/src/components/index.ts +110 -109
- package/src/constants/iconEnums.ts +3 -3
- package/src/i18n/i18n.ts +15 -15
- package/src/i18n/locales/de.json +30 -30
- package/src/i18n/locales/en.json +30 -30
- package/src/index.ts +43 -43
- package/src/main.ts +11 -11
- package/src/pages/AccordionGroupPage.vue +873 -873
- package/src/pages/AllPage.vue +2483 -2365
- package/src/pages/SelectPage.vue +1302 -1302
- package/src/pages/TilePage.vue +902 -902
- package/src/plugins/vuetify.ts +54 -54
- package/src/shims-vue.d.ts +30 -30
- package/src/utils/index.ts +733 -733
- package/src/vite-env.d.ts +1 -1
- package/tests/unit/accessibility/component-a11y.spec.ts +657 -657
- package/tests/unit/components/Accordion/AccordionGroup.spec.ts +228 -228
- package/tests/unit/components/Accordion/AccordionItem.spec.ts +257 -257
- package/tests/unit/components/Appointment/AnamneseNotification.spec.ts +176 -176
- package/tests/unit/components/Appointment/Card/Actions.spec.ts +436 -436
- package/tests/unit/components/Appointment/Card/Card.spec.ts +531 -531
- package/tests/unit/components/Appointment/Card/Details.spec.ts +395 -395
- package/tests/unit/components/Audio/Audio.spec.ts +403 -403
- package/tests/unit/components/Audio/Waveform.spec.ts +483 -483
- package/tests/unit/components/Background/Background.spec.ts +177 -177
- package/tests/unit/components/Core/AnamneseAnswerDialog.spec.ts +344 -0
- package/tests/unit/components/Core/Banner.spec.ts +187 -0
- package/tests/unit/components/Core/Button.spec.ts +346 -346
- package/tests/unit/components/Core/Checkbox.spec.ts +544 -544
- package/tests/unit/components/Core/DateInput.spec.ts +702 -702
- package/tests/unit/components/Core/Dialog.spec.ts +448 -448
- package/tests/unit/components/Core/EditField.spec.ts +541 -541
- package/tests/unit/components/Core/Input.spec.ts +512 -512
- package/tests/unit/components/Core/List.spec.ts +163 -0
- package/tests/unit/components/Core/ListItem.spec.ts +205 -0
- package/tests/unit/components/Core/Modal.spec.ts +518 -518
- package/tests/unit/components/Core/NotificationBubble.spec.ts +606 -606
- package/tests/unit/components/Core/OtpInput.spec.ts +708 -708
- package/tests/unit/components/Core/PhoneInput.spec.ts +757 -619
- package/tests/unit/components/Core/RadioGroup.spec.ts +318 -0
- package/tests/unit/components/Core/Select.spec.ts +712 -712
- package/tests/unit/components/Core/SelectAutocomplete.spec.ts +361 -0
- package/tests/unit/components/Core/TextArea.spec.ts +565 -565
- package/tests/unit/components/Core/TickBox.spec.ts +836 -836
- package/tests/unit/components/Core/Tile.spec.ts +286 -0
- package/tests/unit/components/DateInput/DateInput.spec.ts +128 -0
- package/tests/unit/components/ErrorPage/ErrorPage.spec.ts +313 -313
- package/tests/unit/components/ErrorPage/ErrorPageLogo.spec.ts +153 -153
- package/tests/unit/components/IconBullet/IconBullet.spec.ts +356 -356
- package/tests/unit/components/IconBullet/IconBulletList.spec.ts +371 -371
- package/tests/unit/components/Icons/AdvanceAppointments.spec.ts +186 -186
- package/tests/unit/components/Icons/Audio/CloudFailed.spec.ts +108 -108
- package/tests/unit/components/Icons/Audio/CloudSaved.spec.ts +149 -149
- package/tests/unit/components/Icons/Audio/Delete.spec.ts +158 -158
- package/tests/unit/components/Icons/Audio/Pause.spec.ts +208 -208
- package/tests/unit/components/Icons/Audio/Play.spec.ts +217 -217
- package/tests/unit/components/Icons/CalendarNotification.spec.ts +193 -193
- package/tests/unit/components/Icons/Chair.spec.ts +241 -241
- package/tests/unit/components/Icons/ChairNotification.spec.ts +318 -318
- package/tests/unit/components/Icons/Circle.spec.ts +255 -255
- package/tests/unit/components/Icons/FavIcon.spec.ts +259 -259
- package/tests/unit/components/Icons/FilledCircle.spec.ts +274 -274
- package/tests/unit/components/Icons/Group3.spec.ts +362 -362
- package/tests/unit/components/Icons/Logo.spec.ts +229 -229
- package/tests/unit/components/Icons/MiniLogo.spec.ts +38 -38
- package/tests/unit/components/Icons/RingNotification.spec.ts +400 -400
- package/tests/unit/components/Icons/SolidArrowRight.spec.ts +49 -49
- package/tests/unit/components/Icons/calendar.spec.ts +293 -293
- package/tests/unit/components/Icons/checkbox.spec.ts +315 -315
- package/tests/unit/components/Icons/outlineChecked.spec.ts +441 -441
- package/tests/unit/components/Icons/play.spec.ts +315 -315
- package/tests/unit/components/Laboratory/AppointmentCard.spec.ts +167 -167
- package/tests/unit/components/Laboratory/ChatBoxImage.spec.ts +179 -179
- package/tests/unit/components/Laboratory/ChatMessage.spec.ts +263 -263
- package/tests/unit/components/Laboratory/ChatMessageBadge.spec.ts +282 -282
- package/tests/unit/components/Laboratory/ChatNotification.spec.ts +256 -256
- package/tests/unit/components/Laboratory/DocumentCard.spec.ts +228 -228
- package/tests/unit/components/Laboratory/DocumentCardItem.spec.ts +236 -236
- package/tests/unit/components/Laboratory/InfoCard.spec.ts +308 -308
- package/tests/unit/components/Laboratory/MainColumnsBar.spec.ts +251 -251
- package/tests/unit/components/Laboratory/ProgressCircle.spec.ts +290 -290
- package/tests/unit/components/Laboratory/ProgressLinear.spec.ts +275 -275
- package/tests/unit/components/Laboratory/SelectionColumnBar.spec.ts +288 -288
- package/tests/unit/components/Laboratory/StatusNotification.spec.ts +296 -296
- package/tests/unit/components/Laboratory/TagLabel.spec.ts +353 -353
- package/tests/unit/components/Laboratory/TagLabelGroup.spec.ts +377 -377
- package/tests/unit/components/Laboratory/TicketCard.spec.ts +351 -351
- package/tests/unit/components/Laboratory/TimeLineEvent.spec.ts +381 -381
- package/tests/unit/components/Laboratory/Timeline.spec.ts +419 -419
- package/tests/unit/components/Loader/Loader.spec.ts +197 -197
- package/tests/unit/components/MaintenanceBanner/MaintenanceBanner.spec.ts +302 -302
- package/tests/unit/constants/iconEnums.spec.ts +39 -39
- package/tests/unit/i18n/i18n.spec.ts +88 -88
- package/tests/unit/plugins/vuetify.spec.ts +182 -182
- package/tests/unit/setup.ts +237 -237
- package/tests/unit/src/components/index.spec.ts.skip +192 -192
- package/tests/unit/src/index.spec.ts.skip +182 -182
- package/tests/unit/src/main.spec.ts +111 -111
- package/tests/unit/utils/accessibility.spec.ts +318 -318
- package/tests/unit/utils/anamnese.spec.ts +531 -0
- package/tsconfig.json +26 -26
- package/vite.config.ts +29 -29
- package/vitest.config.ts +91 -91
|
@@ -1,257 +1,257 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<v-btn
|
|
3
|
-
:color="buttonColor"
|
|
4
|
-
:disabled="disabled"
|
|
5
|
-
:append-icon="appendIcon"
|
|
6
|
-
rounded="lg"
|
|
7
|
-
:density="density"
|
|
8
|
-
class="text-none wl-button"
|
|
9
|
-
:variant="variant"
|
|
10
|
-
:size="size"
|
|
11
|
-
:readonly="readonly"
|
|
12
|
-
:style="rootStyle"
|
|
13
|
-
data-testid="root"
|
|
14
|
-
>
|
|
15
|
-
<template v-if="loading || prependIcon" v-slot:prepend>
|
|
16
|
-
<Loader v-if="loading" :size="loaderSize" :inline="true" :bg-color="loaderBgColor" :text-color="loaderTextColor" />
|
|
17
|
-
<v-icon v-else-if="prependIcon">{{ prependIcon }}</v-icon>
|
|
18
|
-
</template>
|
|
19
|
-
<slot>{{ label }}</slot>
|
|
20
|
-
</v-btn>
|
|
21
|
-
</template>
|
|
22
|
-
|
|
23
|
-
<script setup lang="ts">
|
|
24
|
-
import { computed, inject } from 'vue';
|
|
25
|
-
import { siteColors as globalSiteColors } from "../../utils/index";
|
|
26
|
-
import Loader from '../Loader/Loader.vue';
|
|
27
|
-
|
|
28
|
-
// Use injected theme colors if available, otherwise fall back to global siteColors
|
|
29
|
-
const injectedColors = inject<any>('themeColors', null);
|
|
30
|
-
const siteColors = computed(() => {
|
|
31
|
-
if (injectedColors?.value) {
|
|
32
|
-
return injectedColors.value;
|
|
33
|
-
}
|
|
34
|
-
return globalSiteColors || {};
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const props = defineProps({
|
|
38
|
-
/**
|
|
39
|
-
* The color of the button.
|
|
40
|
-
* Default is '--Dental-Blue-0' (a dark blue color).
|
|
41
|
-
*/
|
|
42
|
-
color: {
|
|
43
|
-
type: String,
|
|
44
|
-
default: null,
|
|
45
|
-
},
|
|
46
|
-
/**
|
|
47
|
-
* The text color of the button (for flat variant).
|
|
48
|
-
* Default is 'white'.
|
|
49
|
-
*/
|
|
50
|
-
textColor: {
|
|
51
|
-
type: String,
|
|
52
|
-
default: null,
|
|
53
|
-
},
|
|
54
|
-
/**
|
|
55
|
-
* Icon to display before the button label.
|
|
56
|
-
* Accepts the name of an icon (String).
|
|
57
|
-
*/
|
|
58
|
-
prependIcon: {
|
|
59
|
-
type: String,
|
|
60
|
-
},
|
|
61
|
-
/**
|
|
62
|
-
* Icon to display after the button label.
|
|
63
|
-
* Can be any valid icon name or value (type not specified for flexibility).
|
|
64
|
-
*/
|
|
65
|
-
appendIcon: {},
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Boolean to set the loading state of the button.
|
|
69
|
-
* When true, it shows a loading spinner.
|
|
70
|
-
* Default is false.
|
|
71
|
-
*/
|
|
72
|
-
loading: {
|
|
73
|
-
type: Boolean,
|
|
74
|
-
default: false,
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Defines the density of the button.
|
|
79
|
-
* Accepts 'default', 'comfortable', or other Vuetify density options.
|
|
80
|
-
* Default is 'default'.
|
|
81
|
-
*/
|
|
82
|
-
density: {
|
|
83
|
-
type: String,
|
|
84
|
-
default: 'default',
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* The visual style of the button.
|
|
89
|
-
* Accepts 'flat', 'outlined', 'contained', etc.
|
|
90
|
-
* Default is 'flat'.
|
|
91
|
-
*/
|
|
92
|
-
variant: {
|
|
93
|
-
type: String,
|
|
94
|
-
default: 'flat',
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Size of the button.
|
|
99
|
-
* Accepts 'small', 'medium', 'large', or 'default'.
|
|
100
|
-
* Default is 'default'.
|
|
101
|
-
*/
|
|
102
|
-
size: {
|
|
103
|
-
type: String,
|
|
104
|
-
default: 'default',
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* The text label to display inside the button.
|
|
109
|
-
* Default is 'Button'.
|
|
110
|
-
*/
|
|
111
|
-
label: {
|
|
112
|
-
type: String,
|
|
113
|
-
default: 'Button',
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Boolean to disable the button.
|
|
118
|
-
* When true, the button is disabled and not clickable.
|
|
119
|
-
* Default is false.
|
|
120
|
-
*/
|
|
121
|
-
disabled: {
|
|
122
|
-
type: Boolean,
|
|
123
|
-
default: false,
|
|
124
|
-
},
|
|
125
|
-
/**
|
|
126
|
-
* Boolean to set the button to read-only state.
|
|
127
|
-
* When true, the button displays the readonly attribute.
|
|
128
|
-
* Default is false.
|
|
129
|
-
*/
|
|
130
|
-
readonly: {
|
|
131
|
-
type: Boolean,
|
|
132
|
-
default: false,
|
|
133
|
-
},
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
// Compute the button color with theme fallback
|
|
137
|
-
const buttonColor = computed(() => {
|
|
138
|
-
if (props.color) return props.color;
|
|
139
|
-
|
|
140
|
-
// Use theme colors based on variant and disabled state
|
|
141
|
-
if (props.variant === 'outlined') {
|
|
142
|
-
if (props.disabled) {
|
|
143
|
-
return siteColors.value['button_outline_disabled_border'];
|
|
144
|
-
}
|
|
145
|
-
return siteColors.value['button_outline_border'];
|
|
146
|
-
}
|
|
147
|
-
if (props.disabled) {
|
|
148
|
-
return siteColors.value['button_disabled_bg'];
|
|
149
|
-
}
|
|
150
|
-
return siteColors.value['button_default_bg'];
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
// Compute text color with theme fallback
|
|
154
|
-
const buttonTextColor = computed(() => {
|
|
155
|
-
if (props.textColor) return props.textColor;
|
|
156
|
-
|
|
157
|
-
// Use theme colors based on variant and disabled state
|
|
158
|
-
if (props.variant === 'outlined') {
|
|
159
|
-
if (props.disabled) {
|
|
160
|
-
return siteColors.value['button_outline_disabled_text'];
|
|
161
|
-
}
|
|
162
|
-
return siteColors.value['button_outline_default_text'];
|
|
163
|
-
}
|
|
164
|
-
return siteColors.value['button_default_text'];
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
const buttonStyle = computed(() => {
|
|
168
|
-
if (props.variant === 'flat' || props.variant === 'elevated') {
|
|
169
|
-
return { color: buttonTextColor.value };
|
|
170
|
-
}
|
|
171
|
-
return {};
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
// Compute a CSS variable for focus color to avoid hardcoded values.
|
|
175
|
-
const focusColor = computed(() => {
|
|
176
|
-
return buttonColor.value;
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Expose a style object that includes the focus color custom property.
|
|
180
|
-
const rootStyle = computed(() => ({
|
|
181
|
-
...buttonStyle.value,
|
|
182
|
-
'--wl-button-focus-color': focusColor.value
|
|
183
|
-
}));
|
|
184
|
-
|
|
185
|
-
// Compute loader size based on button size
|
|
186
|
-
const loaderSize = computed(() => {
|
|
187
|
-
switch (props.size) {
|
|
188
|
-
case 'x-small':
|
|
189
|
-
return 16;
|
|
190
|
-
case 'small':
|
|
191
|
-
return 20;
|
|
192
|
-
case 'large':
|
|
193
|
-
return 28;
|
|
194
|
-
case 'x-large':
|
|
195
|
-
return 32;
|
|
196
|
-
default: // 'default' or 'medium'
|
|
197
|
-
return 24;
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
// Compute loader colors based on variant
|
|
202
|
-
const loaderBgColor = computed(() => {
|
|
203
|
-
// For outlined variant, use transparent for background circle to create contrast
|
|
204
|
-
if (props.variant === 'outlined') {
|
|
205
|
-
return 'transparent';
|
|
206
|
-
}
|
|
207
|
-
// For flat/elevated: background circle uses text color (after vice versa swap)
|
|
208
|
-
return buttonTextColor.value;
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
const loaderTextColor = computed(() => {
|
|
212
|
-
// For outlined variant, use the outline color for all elements
|
|
213
|
-
if (props.variant === 'outlined') {
|
|
214
|
-
return buttonColor.value;
|
|
215
|
-
}
|
|
216
|
-
// For flat/elevated: rotating arc and other elements use button background color (after vice versa swap)
|
|
217
|
-
return buttonColor.value;
|
|
218
|
-
});
|
|
219
|
-
</script>
|
|
220
|
-
|
|
221
|
-
<style>
|
|
222
|
-
.wl-button.v-btn--variant-outlined {
|
|
223
|
-
border-width: 1.5px;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/* Disabled button styles */
|
|
227
|
-
.wl-button.v-btn--disabled {
|
|
228
|
-
opacity: 1 !important;
|
|
229
|
-
pointer-events: none !important;
|
|
230
|
-
cursor: not-allowed !important;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/* Accessibility: Focus Indicators (WCAG 2.4.7) */
|
|
234
|
-
.wl-button:focus-visible {
|
|
235
|
-
outline: 2px solid currentColor;
|
|
236
|
-
outline-offset: 2px;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
.wl-button.v-btn--variant-outlined:focus-visible {
|
|
240
|
-
/* Use component-provided focus color with fallback */
|
|
241
|
-
outline-color: var(--wl-button-focus-color, var(--button_outline_border));
|
|
242
|
-
outline-width: 3px;
|
|
243
|
-
box-shadow: 0 0 0 4px rgba(0,0,0,0.08), 0 0 0 6px rgba(255,255,255,0.06) inset;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
.wl-button.v-btn--variant-flat:focus-visible {
|
|
247
|
-
outline-color: var(--wl-button-focus-color, var(--button_default_text));
|
|
248
|
-
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.3);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/* High contrast mode support */
|
|
252
|
-
@media (forced-colors: active) {
|
|
253
|
-
.wl-button {
|
|
254
|
-
border: 2px solid currentColor;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<v-btn
|
|
3
|
+
:color="buttonColor"
|
|
4
|
+
:disabled="disabled"
|
|
5
|
+
:append-icon="appendIcon"
|
|
6
|
+
rounded="lg"
|
|
7
|
+
:density="density"
|
|
8
|
+
class="text-none wl-button"
|
|
9
|
+
:variant="variant"
|
|
10
|
+
:size="size"
|
|
11
|
+
:readonly="readonly"
|
|
12
|
+
:style="rootStyle"
|
|
13
|
+
data-testid="root"
|
|
14
|
+
>
|
|
15
|
+
<template v-if="loading || prependIcon" v-slot:prepend>
|
|
16
|
+
<Loader v-if="loading" :size="loaderSize" :inline="true" :bg-color="loaderBgColor" :text-color="loaderTextColor" />
|
|
17
|
+
<v-icon v-else-if="prependIcon">{{ prependIcon }}</v-icon>
|
|
18
|
+
</template>
|
|
19
|
+
<slot>{{ label }}</slot>
|
|
20
|
+
</v-btn>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup lang="ts">
|
|
24
|
+
import { computed, inject } from 'vue';
|
|
25
|
+
import { siteColors as globalSiteColors } from "../../utils/index";
|
|
26
|
+
import Loader from '../Loader/Loader.vue';
|
|
27
|
+
|
|
28
|
+
// Use injected theme colors if available, otherwise fall back to global siteColors
|
|
29
|
+
const injectedColors = inject<any>('themeColors', null);
|
|
30
|
+
const siteColors = computed(() => {
|
|
31
|
+
if (injectedColors?.value) {
|
|
32
|
+
return injectedColors.value;
|
|
33
|
+
}
|
|
34
|
+
return globalSiteColors || {};
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const props = defineProps({
|
|
38
|
+
/**
|
|
39
|
+
* The color of the button.
|
|
40
|
+
* Default is '--Dental-Blue-0' (a dark blue color).
|
|
41
|
+
*/
|
|
42
|
+
color: {
|
|
43
|
+
type: String,
|
|
44
|
+
default: null,
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* The text color of the button (for flat variant).
|
|
48
|
+
* Default is 'white'.
|
|
49
|
+
*/
|
|
50
|
+
textColor: {
|
|
51
|
+
type: String,
|
|
52
|
+
default: null,
|
|
53
|
+
},
|
|
54
|
+
/**
|
|
55
|
+
* Icon to display before the button label.
|
|
56
|
+
* Accepts the name of an icon (String).
|
|
57
|
+
*/
|
|
58
|
+
prependIcon: {
|
|
59
|
+
type: String,
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Icon to display after the button label.
|
|
63
|
+
* Can be any valid icon name or value (type not specified for flexibility).
|
|
64
|
+
*/
|
|
65
|
+
appendIcon: {},
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Boolean to set the loading state of the button.
|
|
69
|
+
* When true, it shows a loading spinner.
|
|
70
|
+
* Default is false.
|
|
71
|
+
*/
|
|
72
|
+
loading: {
|
|
73
|
+
type: Boolean,
|
|
74
|
+
default: false,
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Defines the density of the button.
|
|
79
|
+
* Accepts 'default', 'comfortable', or other Vuetify density options.
|
|
80
|
+
* Default is 'default'.
|
|
81
|
+
*/
|
|
82
|
+
density: {
|
|
83
|
+
type: String,
|
|
84
|
+
default: 'default',
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The visual style of the button.
|
|
89
|
+
* Accepts 'flat', 'outlined', 'contained', etc.
|
|
90
|
+
* Default is 'flat'.
|
|
91
|
+
*/
|
|
92
|
+
variant: {
|
|
93
|
+
type: String,
|
|
94
|
+
default: 'flat',
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Size of the button.
|
|
99
|
+
* Accepts 'small', 'medium', 'large', or 'default'.
|
|
100
|
+
* Default is 'default'.
|
|
101
|
+
*/
|
|
102
|
+
size: {
|
|
103
|
+
type: String,
|
|
104
|
+
default: 'default',
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The text label to display inside the button.
|
|
109
|
+
* Default is 'Button'.
|
|
110
|
+
*/
|
|
111
|
+
label: {
|
|
112
|
+
type: String,
|
|
113
|
+
default: 'Button',
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Boolean to disable the button.
|
|
118
|
+
* When true, the button is disabled and not clickable.
|
|
119
|
+
* Default is false.
|
|
120
|
+
*/
|
|
121
|
+
disabled: {
|
|
122
|
+
type: Boolean,
|
|
123
|
+
default: false,
|
|
124
|
+
},
|
|
125
|
+
/**
|
|
126
|
+
* Boolean to set the button to read-only state.
|
|
127
|
+
* When true, the button displays the readonly attribute.
|
|
128
|
+
* Default is false.
|
|
129
|
+
*/
|
|
130
|
+
readonly: {
|
|
131
|
+
type: Boolean,
|
|
132
|
+
default: false,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Compute the button color with theme fallback
|
|
137
|
+
const buttonColor = computed(() => {
|
|
138
|
+
if (props.color) return props.color;
|
|
139
|
+
|
|
140
|
+
// Use theme colors based on variant and disabled state
|
|
141
|
+
if (props.variant === 'outlined') {
|
|
142
|
+
if (props.disabled) {
|
|
143
|
+
return siteColors.value['button_outline_disabled_border'];
|
|
144
|
+
}
|
|
145
|
+
return siteColors.value['button_outline_border'];
|
|
146
|
+
}
|
|
147
|
+
if (props.disabled) {
|
|
148
|
+
return siteColors.value['button_disabled_bg'];
|
|
149
|
+
}
|
|
150
|
+
return siteColors.value['button_default_bg'];
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Compute text color with theme fallback
|
|
154
|
+
const buttonTextColor = computed(() => {
|
|
155
|
+
if (props.textColor) return props.textColor;
|
|
156
|
+
|
|
157
|
+
// Use theme colors based on variant and disabled state
|
|
158
|
+
if (props.variant === 'outlined') {
|
|
159
|
+
if (props.disabled) {
|
|
160
|
+
return siteColors.value['button_outline_disabled_text'];
|
|
161
|
+
}
|
|
162
|
+
return siteColors.value['button_outline_default_text'];
|
|
163
|
+
}
|
|
164
|
+
return siteColors.value['button_default_text'];
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const buttonStyle = computed(() => {
|
|
168
|
+
if (props.variant === 'flat' || props.variant === 'elevated') {
|
|
169
|
+
return { color: buttonTextColor.value };
|
|
170
|
+
}
|
|
171
|
+
return {};
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// Compute a CSS variable for focus color to avoid hardcoded values.
|
|
175
|
+
const focusColor = computed(() => {
|
|
176
|
+
return buttonColor.value;
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Expose a style object that includes the focus color custom property.
|
|
180
|
+
const rootStyle = computed(() => ({
|
|
181
|
+
...buttonStyle.value,
|
|
182
|
+
'--wl-button-focus-color': focusColor.value
|
|
183
|
+
}));
|
|
184
|
+
|
|
185
|
+
// Compute loader size based on button size
|
|
186
|
+
const loaderSize = computed(() => {
|
|
187
|
+
switch (props.size) {
|
|
188
|
+
case 'x-small':
|
|
189
|
+
return 16;
|
|
190
|
+
case 'small':
|
|
191
|
+
return 20;
|
|
192
|
+
case 'large':
|
|
193
|
+
return 28;
|
|
194
|
+
case 'x-large':
|
|
195
|
+
return 32;
|
|
196
|
+
default: // 'default' or 'medium'
|
|
197
|
+
return 24;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Compute loader colors based on variant
|
|
202
|
+
const loaderBgColor = computed(() => {
|
|
203
|
+
// For outlined variant, use transparent for background circle to create contrast
|
|
204
|
+
if (props.variant === 'outlined') {
|
|
205
|
+
return 'transparent';
|
|
206
|
+
}
|
|
207
|
+
// For flat/elevated: background circle uses text color (after vice versa swap)
|
|
208
|
+
return buttonTextColor.value;
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const loaderTextColor = computed(() => {
|
|
212
|
+
// For outlined variant, use the outline color for all elements
|
|
213
|
+
if (props.variant === 'outlined') {
|
|
214
|
+
return buttonColor.value;
|
|
215
|
+
}
|
|
216
|
+
// For flat/elevated: rotating arc and other elements use button background color (after vice versa swap)
|
|
217
|
+
return buttonColor.value;
|
|
218
|
+
});
|
|
219
|
+
</script>
|
|
220
|
+
|
|
221
|
+
<style>
|
|
222
|
+
.wl-button.v-btn--variant-outlined {
|
|
223
|
+
border-width: 1.5px;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* Disabled button styles */
|
|
227
|
+
.wl-button.v-btn--disabled {
|
|
228
|
+
opacity: 1 !important;
|
|
229
|
+
pointer-events: none !important;
|
|
230
|
+
cursor: not-allowed !important;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/* Accessibility: Focus Indicators (WCAG 2.4.7) */
|
|
234
|
+
.wl-button:focus-visible {
|
|
235
|
+
outline: 2px solid currentColor;
|
|
236
|
+
outline-offset: 2px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.wl-button.v-btn--variant-outlined:focus-visible {
|
|
240
|
+
/* Use component-provided focus color with fallback */
|
|
241
|
+
outline-color: var(--wl-button-focus-color, var(--button_outline_border));
|
|
242
|
+
outline-width: 3px;
|
|
243
|
+
box-shadow: 0 0 0 4px rgba(0,0,0,0.08), 0 0 0 6px rgba(255,255,255,0.06) inset;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.wl-button.v-btn--variant-flat:focus-visible {
|
|
247
|
+
outline-color: var(--wl-button-focus-color, var(--button_default_text));
|
|
248
|
+
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.3);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/* High contrast mode support */
|
|
252
|
+
@media (forced-colors: active) {
|
|
253
|
+
.wl-button {
|
|
254
|
+
border: 2px solid currentColor;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
</style>
|