PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / trunk
Booking for Appointments and Events Calendar – Amelia vtrunk
2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / v3 / src / views / _components / button / AmButton.vue
ameliabooking / v3 / src / views / _components / button Last commit date
AmAdvButton.vue 1 day ago AmButton.vue 1 day ago AmButtonGroup.vue 1 day ago
AmButton.vue
653 lines
1 <template>
2 <button
3 v-bind="bindProps"
4 class="am-button"
5 :disabled="disabled || loading"
6 :autofocus="autofocus"
7 :type="nativeType"
8 :class="[
9 type ? 'am-button--' + type : '',
10 size ? 'am-button--' + size : '',
11 category ? 'am-button--' + category : '',
12 {
13 'is-icon-only': iconOnly,
14 'is-disabled': disabled,
15 'is-loading': loading,
16 'is-round': round,
17 'is-circle': circle,
18 },
19 customClass,
20 ]"
21 :style="{ ...cssVars, ...style }"
22 @click="handleClick"
23 >
24 <!-- Loading slot -->
25 <slot v-if="(loadingIcon || Object.keys(loadingIcon).length) && loading" name="loading">
26 <component :is="loadingIcon" v-if="typeof loadingIcon === 'object'"></component>
27 <span v-if="typeof loadingIcon === 'string'" :class="`am-icon-${loadingIcon}`"></span>
28 </slot>
29
30 <!-- Icon slot -->
31 <slot v-if="(icon || Object.keys(icon).length) && iconOnly && !loading" name="icon">
32 <component :is="icon" v-if="typeof icon === 'object'"></component>
33 <span v-if="typeof icon === 'string'" :class="`am-icon am-icon-${icon}`"></span>
34 </slot>
35
36 <!-- Prefix slot -->
37 <slot v-if="(prefix || Object.keys(prefix).length) && !iconOnly && !loading" name="prefix">
38 <component :is="prefix" v-if="typeof prefix === 'object'"></component>
39 <span v-if="typeof prefix === 'string'" :class="`am-icon-${prefix}`"></span>
40 </slot>
41
42 <!-- Default slot -->
43 <span v-if="$slots.default && !iconOnly" class="am-button__inner" :class="innerClass">
44 <slot />
45 </span>
46
47 <!-- Suffix slot -->
48 <slot v-if="(suffix || Object.keys(suffix).length) && !iconOnly && !loading" name="suffix">
49 <component :is="suffix" v-if="typeof suffix === 'object'"></component>
50 <span v-if="typeof suffix === 'string'" :class="`am-icon am-icon-${suffix}`"></span>
51 </slot>
52 </button>
53 </template>
54
55 <script setup>
56 import { useColorTransparency } from '../../../assets/js/common/colorManipulation'
57
58 import { computed, ref, inject } from 'vue'
59
60 /**
61 * Component props
62 */
63 const props = defineProps({
64 id: {
65 type: String,
66 },
67 customClass: {
68 type: String,
69 default: '',
70 },
71 innerClass: {
72 type: String,
73 default: '',
74 },
75 iconOnly: {
76 type: Boolean,
77 default: false,
78 },
79 size: {
80 // default / medium / small / mini / micro
81 type: String,
82 default: 'default',
83 validator(value) {
84 return ['default', 'medium', 'small', 'mini', 'micro'].includes(value)
85 },
86 },
87 category: {
88 // primary / secondary / success / warning / danger / error
89 type: String,
90 default: 'primary',
91 validator(value) {
92 return ['primary', 'secondary', 'success', 'warning', 'danger', 'error', 'waiting'].includes(
93 value,
94 )
95 },
96 },
97 type: {
98 // filled / plain / text
99 type: String,
100 default: 'filled',
101 validator(value) {
102 return ['filled', 'plain', 'text'].includes(value)
103 },
104 },
105 nativeType: {
106 // button / submit / reset
107 type: String,
108 default: 'button',
109 validator(value) {
110 return ['button', 'submit', 'reset'].includes(value)
111 },
112 },
113 round: {
114 type: Boolean,
115 default: false,
116 },
117 circle: {
118 type: Boolean,
119 default: false,
120 },
121 loading: {
122 type: Boolean,
123 default: false,
124 },
125 disabled: {
126 type: Boolean,
127 default: false,
128 },
129 autofocus: {
130 type: Boolean,
131 default: false,
132 },
133 prefix: {
134 type: [String, Object, Function],
135 default: '',
136 },
137 suffix: {
138 type: [String, Object, Function],
139 default: '',
140 },
141 icon: {
142 type: [String, Object, Function],
143 default: '',
144 },
145 loadingIcon: {
146 type: [String, Object, Function],
147 default: '',
148 },
149 style: {
150 type: Object,
151 default: () => {
152 return {}
153 },
154 },
155 })
156
157 // Create filtered properties
158 const bindProps = computed(() => {
159 const filterObj = { ...props }
160 const arrayProp = ['id']
161
162 return Object.fromEntries(Object.entries(filterObj).filter(([key]) => arrayProp.includes(key)))
163 })
164
165 /**
166 * Component emits
167 * @type {EmitFn<string[]>}
168 */
169 const emits = defineEmits(['click'])
170
171 /**
172 * Handle click function
173 * @param evt
174 */
175 function handleClick(evt) {
176 emits('click', evt)
177 }
178
179 // * Color Vars
180 let amColors = inject(
181 'amColors',
182 ref({
183 colorPrimary: '#1246D6',
184 colorSuccess: '#019719',
185 colorError: '#B4190F',
186 colorWarning: '#CCA20C',
187 colorMainBgr: '#FFFFFF',
188 colorMainHeadingText: '#33434C',
189 colorMainText: '#1A2C37',
190 colorSbBgr: '#17295A',
191 colorSbText: '#FFFFFF',
192 colorInpBgr: '#FFFFFF',
193 colorInpBorder: '#D1D5D7',
194 colorInpText: '#1A2C37',
195 colorInpPlaceHolder: '#1A2C37',
196 colorDropBgr: '#FFFFFF',
197 colorDropBorder: '#D1D5D7',
198 colorDropText: '#0E1920',
199 colorBtnPrim: '#265CF2',
200 colorBtnPrimText: '#FFFFFF',
201 colorBtnSec: '#1A2C37',
202 colorBtnSecText: '#FFFFFF',
203 colorBtnWaiting: '#CCA20C',
204 colorBtnWaitingText: '#FFFFFF',
205 colorBtnDanger: '#B4190F',
206 colorBtnDangerText: '#FFFFFF',
207 }),
208 )
209
210 const cssVars = computed(() => {
211 let cssVariables = {}
212 if (props.category === 'primary') {
213 cssVariables = {
214 '--am-c-btn-first': amColors.value.colorBtnPrim,
215 '--am-c-btn-second': amColors.value.colorBtnPrimText,
216 '--am-c-btn-first-op80': useColorTransparency(amColors.value.colorBtnPrim, 0.8),
217 '--am-c-btn-first-op30': useColorTransparency(amColors.value.colorBtnPrim, 0.3),
218 '--am-c-btn-first-op20': useColorTransparency(amColors.value.colorBtnPrim, 0.1),
219 }
220 }
221
222 if (props.category === 'secondary') {
223 cssVariables = {
224 '--am-c-btn-first': amColors.value.colorBtnSec,
225 '--am-c-btn-second': amColors.value.colorBtnSecText,
226 '--am-c-btn-first-op80': useColorTransparency(amColors.value.colorBtnSec, 0.8),
227 '--am-c-btn-first-op30': useColorTransparency(amColors.value.colorBtnSec, 0.3),
228 '--am-c-btn-first-op20': useColorTransparency(amColors.value.colorBtnSec, 0.1),
229 }
230 }
231
232 if (props.category === 'waiting') {
233 let bgr = amColors.value?.colorBtnWaiting ?? '#CCA20C'
234 let text = amColors.value?.colorBtnWaitingText ?? '#FFFFFF'
235
236 cssVariables = {
237 '--am-c-btn-first': bgr,
238 '--am-c-btn-second': text,
239 '--am-c-btn-first-op80': useColorTransparency(bgr, 0.8),
240 '--am-c-btn-first-op30': useColorTransparency(bgr, 0.3),
241 '--am-c-btn-first-op20': useColorTransparency(bgr, 0.1),
242 }
243 }
244
245 if (props.category === 'warning') {
246 cssVariables = {
247 '--am-c-btn-first': amColors.value.colorWarning,
248 '--am-c-btn-second': amColors.value.colorMainBgr,
249 '--am-c-btn-first-op80': useColorTransparency(amColors.value.colorWarning, 0.8),
250 '--am-c-btn-first-op30': useColorTransparency(amColors.value.colorWarning, 0.3),
251 '--am-c-btn-first-op20': useColorTransparency(amColors.value.colorWarning, 0.1),
252 }
253 }
254
255 if (props.category === 'danger') {
256 cssVariables = {
257 '--am-c-btn-first': amColors.value.colorBtnDanger,
258 '--am-c-btn-second': amColors.value.colorBtnDangerText,
259 '--am-c-btn-first-op80': useColorTransparency(amColors.value.colorBtnDanger, 0.8),
260 '--am-c-btn-first-op30': useColorTransparency(amColors.value.colorBtnDanger, 0.3),
261 '--am-c-btn-first-op20': useColorTransparency(amColors.value.colorBtnDanger, 0.1),
262 }
263 }
264
265 return cssVariables
266 })
267 </script>
268
269 <style lang="scss">
270 @mixin am-button-block {
271 .am-button {
272 --am-h-btn: 40px;
273 --am-fs-btn: 15px;
274 --am-fw-btn: 500;
275 --am-lh-btn: 1.6;
276 --am-rad-btn: 6px;
277 --am-padd-btn: 8px 24px;
278
279 display: inline-flex;
280 align-items: center;
281 justify-content: center;
282 height: var(--am-h-btn);
283 font-size: var(--am-fs-btn);
284 font-weight: var(--am-fw-btn);
285 line-height: var(--am-lh-btn);
286 white-space: nowrap;
287 text-decoration: none;
288 text-transform: unset;
289 border-radius: var(--am-rad-btn);
290 outline: 0;
291 margin: 0;
292 padding: var(--am-padd-btn);
293 cursor: pointer;
294 transition: 0.3s all ease-in-out;
295
296 // Inner
297 span {
298 display: flex;
299 align-items: center;
300 justify-content: center;
301 overflow: hidden;
302 }
303
304 &.am-button {
305 // Type - filled / plain / text
306 &--filled {
307 --am-c-btn-bgr: var(--am-c-btn-first);
308 --am-c-btn-text: var(--am-c-btn-second);
309 --am-c-btn-border: var(--am-c-btn-first);
310 background-color: var(--am-c-btn-bgr);
311 color: var(--am-c-btn-text);
312 border: 1px solid var(--am-c-btn-border);
313
314 &:not(.is-disabled) {
315 &:hover {
316 --am-c-btn-bgr: var(--am-c-btn-first-op80);
317 }
318
319 &:focus:not(:active) {
320 --am-c-btn-border: var(--am-c-btn-first);
321 box-shadow: 0 0 0 3px var(--am-c-btn-first-op30);
322 }
323
324 &:active {
325 --am-c-btn-bgr: var(--am-c-btn-first);
326 }
327 }
328 }
329
330 &--plain {
331 --am-c-btn-bgr: transparent;
332 --am-c-btn-text: var(--am-c-btn-first);
333 --am-c-btn-border: var(--am-c-btn-first-op30);
334 --am-c-btn-shadow: var(--am-c-btn-first-op20);
335 background-color: var(--am-c-btn-bgr);
336 color: var(--am-c-btn-text);
337 border: 1px solid var(--am-c-btn-border);
338 box-shadow: 0 1px 3px var(--am-c-btn-shadow);
339
340 &:not(.is-disabled) {
341 &:hover {
342 --am-c-btn-bgr: var(--am-c-btn-first-op20);
343 box-shadow: none;
344 }
345
346 &:focus:not(:active) {
347 --am-c-btn-border: var(--am-c-btn-second);
348 box-shadow: 0 0 0 2px var(--am-c-btn-first-op20);
349
350 &.is-icon-only {
351 --am-c-btn-border: var(--am-c-btn-first);
352 }
353
354 &:hover {
355 --am-c-btn-border: var(--am-c-btn-first-op20);
356 }
357 }
358
359 &:active {
360 --am-c-btn-bgr: var(--am-c-btn-first-op30);
361 box-shadow: none;
362 }
363 }
364 }
365
366 &--text {
367 --am-c-btn-bgr: transparent;
368 --am-c-btn-text: var(--am-c-btn-first);
369 --am-c-btn-border: transparent;
370 --am-c-btn-shadow: transparent;
371 background-color: var(--am-c-btn-bgr);
372 color: var(--am-c-btn-text);
373 border: 1px solid var(--am-c-btn-border);
374
375 &:not(.is-disabled) {
376 &:hover {
377 --am-c-btn-bgr: var(--am-c-btn-first-op20);
378 }
379
380 &:focus:not(:active) {
381 box-shadow: 0 0 0 2px var(--am-c-btn-first);
382 }
383
384 &:active {
385 --am-c-btn-bgr: var(--am-c-btn-first-op30);
386 }
387 }
388 }
389
390 // Size - default / medium / small / mini / micro
391 &--default {
392 --am-h-btn: 40px;
393 --am-fs-btn: 15px;
394 --am-lh-btn: 1.6;
395 --am-padd-btn: 8px 24px;
396
397 &.is-icon-only {
398 --am-padd-btn: 8px;
399 width: 40px;
400 }
401 }
402 &--medium {
403 --am-h-btn: 36px;
404 --am-fs-btn: 14px;
405 --am-lh-btn: 1.42857;
406 --am-padd-btn: 8px 20px;
407
408 &.is-icon-only {
409 --am-padd-btn: 8px;
410 width: 36px;
411 }
412 }
413 &--small {
414 --am-h-btn: 32px;
415 --am-fs-btn: 14px;
416 --am-lh-btn: 1.42857;
417 --am-padd-btn: 6px 16px;
418
419 &.is-icon-only {
420 --am-padd-btn: 6px;
421 width: 32px;
422 }
423 }
424 &--mini {
425 --am-h-btn: 28px;
426 --am-fs-btn: 13px;
427 --am-lh-btn: 1.53846;
428 --am-padd-btn: 4px 12px;
429 &.is-icon-only {
430 --am-padd-btn: 4px;
431 width: 28px;
432 }
433 }
434 &--micro {
435 --am-h-btn: 24px;
436 --am-fs-btn: 12px;
437 --am-lh-btn: 1.66666;
438 --am-padd-btn: 2px 12px;
439
440 &.is-icon-only {
441 --am-padd-btn: 2px;
442 --am-fs-btn: 16px;
443 width: 24px;
444 }
445 }
446
447 // Category - primary / secondary / success / warning / danger / error
448 // classes usage to change css variables
449 &--primary {
450 }
451 &--secondary {
452 }
453 &--success {
454 }
455 &--warning {
456 }
457 &--danger {
458 }
459 &--error {
460 }
461
462 // Circle
463 &.is-circle {
464 border-radius: 50%;
465 }
466
467 // Round
468 &.is-round {
469 border-radius: 20px;
470 }
471
472 // Disabled
473 &.is-disabled {
474 opacity: 0.7;
475 cursor: not-allowed;
476 }
477
478 &--waiting-list {
479 // TODO
480 }
481 }
482
483 &.am- {
484 &w20 {
485 width: 20%;
486 }
487
488 &w25 {
489 width: 25%;
490 }
491
492 &w30 {
493 width: 30%;
494 }
495
496 &w35 {
497 width: 35%;
498 }
499
500 &w40 {
501 width: 40%;
502 }
503
504 &w45 {
505 width: 45%;
506 }
507
508 &w50 {
509 width: 50%;
510 }
511
512 &w55 {
513 width: 55%;
514 }
515
516 &w60 {
517 width: 60%;
518 }
519
520 &w65 {
521 width: 65%;
522 }
523
524 &w70 {
525 width: 70%;
526 }
527
528 &w75 {
529 width: 75%;
530 }
531
532 &w80 {
533 width: 80%;
534 }
535
536 &w85 {
537 width: 85%;
538 }
539
540 &w90 {
541 width: 90%;
542 }
543
544 &w95 {
545 width: 95%;
546 }
547
548 &w100 {
549 width: 100%;
550 }
551
552 &mw20 {
553 max-width: 20%;
554 }
555
556 &mw25 {
557 max-width: 25%;
558 }
559
560 &mw30 {
561 max-width: 30%;
562 }
563
564 &mw35 {
565 max-width: 35%;
566 }
567
568 &mw40 {
569 max-width: 40%;
570 }
571
572 &mw45 {
573 max-width: 45%;
574 }
575
576 &mw50 {
577 max-width: 50%;
578 }
579
580 &mw55 {
581 max-width: 55%;
582 }
583
584 &mw60 {
585 max-width: 60%;
586 }
587
588 &mw65 {
589 max-width: 65%;
590 }
591
592 &mw70 {
593 max-width: 70%;
594 }
595
596 &mw75 {
597 max-width: 75%;
598 }
599
600 &mw80 {
601 max-width: 80%;
602 }
603
604 &mw85 {
605 max-width: 85%;
606 }
607
608 &mw90 {
609 max-width: 90%;
610 }
611
612 &mw95 {
613 max-width: 95%;
614 }
615
616 &mw100 {
617 max-width: 100%;
618 }
619 }
620 }
621 }
622
623 // Public
624 .amelia-v2-booking #amelia-container {
625 @include am-button-block;
626 }
627
628 // Dropdown
629 .am-dialog {
630 @include am-button-block;
631 }
632
633 // Modal - Dialog
634 .am-dialog-popup {
635 @include am-button-block;
636 }
637
638 // Dropdown that is used in select component and select options
639 .am-select-popper {
640 @include am-button-block;
641 }
642
643 // Menu dropdown that is used in customer and employee panel
644 .am-cc__popper {
645 @include am-button-block;
646 }
647
648 // Admin
649 #amelia-app-backend-new {
650 @include am-button-block;
651 }
652 </style>
653