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