Button.vue
2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<template>
<button
:type="type"
:class="[baseClasses, variantClass, sizeClass, roundedClass, block ? buttonBlock : '', className]"
:disabled="disabled"
@click="$emit('click', $event)"
>
<span v-if="leftIcon" class="mr-2">
<slot name="leftIcon">
{{ leftIcon }}
</slot>
</span>
<slot></slot>
<span v-if="rightIcon" class="ml-2">
<slot name="rightIcon">
{{ rightIcon }}
</slot>
</span>
</button>
</template>
<script setup>
import { computed } from 'vue'
const buttonVariants = {
primary: 'bg-gradient-to-r from-green-500 to-blue-500 hover:from-green-600 hover:to-blue-600 text-white border-transparent',
secondary: 'bg-white hover:bg-gray-50 text-gray-700 border-gray-300',
success: 'bg-green-600 hover:bg-green-700 text-white border-transparent',
danger: 'bg-red-600 hover:bg-red-700 text-white border-transparent',
warning: 'bg-yellow-500 hover:bg-yellow-600 text-white border-transparent',
info: 'bg-blue-500 hover:bg-blue-600 text-white border-transparent',
ghost: 'bg-transparent hover:bg-gray-100 text-gray-700 hover:text-gray-900 border-transparent'
}
const buttonSizes = {
xs: 'px-2 py-1 text-xs',
sm: 'px-2 py-1 text-sm',
md: 'px-4 py-2',
lg: 'px-6 py-3 text-lg',
xl: 'px-8 py-4 text-xl'
}
const buttonRounded = {
none: 'rounded-none',
sm: 'rounded-sm',
md: 'rounded-md',
lg: 'rounded-lg',
full: 'rounded-full'
}
const buttonBlock = 'w-full flex justify-center'
const props = defineProps({
variant: {
type: String,
default: 'primary',
validator: (value) => Object.keys(buttonVariants).includes(value)
},
size: {
type: String,
default: 'md',
validator: (value) => Object.keys(buttonSizes).includes(value)
},
rounded: {
type: String,
default: 'md',
validator: (value) => Object.keys(buttonRounded).includes(value)
},
block: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
className: {
type: String,
default: ''
},
leftIcon: {
type: [String, Object],
default: null
},
rightIcon: {
type: [String, Object],
default: null
},
type: {
type: String,
default: 'button'
}
})
defineEmits(['click'])
const baseClasses = 'flex items-center justify-center font-medium border shadow-sm transition duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed'
const variantClass = computed(() => buttonVariants[props.variant] || buttonVariants.primary)
const sizeClass = computed(() => buttonSizes[props.size] || buttonSizes.md)
const roundedClass = computed(() => buttonRounded[props.rounded] || buttonRounded.md)
</script>