Files
material-kit-design/src/components/MkButton.vue
T
2026-06-01 17:09:26 -06:00

90 lines
3.1 KiB
Vue

<script setup>
import { computed } from 'vue'
const props = defineProps({
variant: {
type: String,
default: 'contained',
validator: v => ['contained', 'gradient', 'outline'].includes(v),
},
color: {
type: String,
default: 'primary',
validator: v => ['primary','secondary','info','success','warning','danger','error','light','white','dark','none'].includes(v),
},
size: {
type: String,
default: 'md',
validator: v => ['sm', 'md', 'lg'].includes(v),
},
fullWidth: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
})
// Static string maps — Tailwind scanner reads these to include the classes.
const contained = {
primary: 'bg-primary text-white',
secondary: 'bg-secondary text-white',
success: 'bg-success text-white',
warning: 'bg-warning text-white',
danger: 'bg-danger text-white',
error: 'bg-danger text-white',
info: 'bg-info text-white',
light: 'bg-light text-dark',
white: 'bg-white text-dark shadow-soft-sm',
dark: 'bg-dark text-white',
none: 'bg-transparent text-dark',
}
const gradient = {
primary: 'bg-gradient-primary shadow-primary text-white',
secondary: 'bg-gradient-secondary shadow-secondary text-white',
success: 'bg-gradient-success shadow-success text-white',
warning: 'bg-gradient-warning shadow-warning text-white',
danger: 'bg-gradient-danger shadow-danger text-white',
error: 'bg-gradient-danger shadow-danger text-white',
info: 'bg-gradient-info shadow-info text-white',
light: 'bg-gradient-light shadow-soft-sm text-dark',
white: 'bg-white shadow-soft-md text-dark',
dark: 'bg-gradient-dark shadow-dark text-white',
none: 'bg-transparent text-dark',
}
const outline = {
primary: 'border border-primary text-primary hover:bg-primary/10',
secondary: 'border border-secondary text-secondary hover:bg-secondary/10',
success: 'border border-success text-success hover:bg-success/10',
warning: 'border border-warning text-warning hover:bg-warning/10',
danger: 'border border-danger text-danger hover:bg-danger/10',
error: 'border border-danger text-danger hover:bg-danger/10',
info: 'border border-info text-info hover:bg-info/10',
light: 'border border-gray-300 text-dark hover:bg-light',
white: 'border border-white text-white hover:bg-white/10',
dark: 'border border-dark text-dark hover:bg-dark/10',
none: 'border border-gray-300 text-dark hover:bg-gray-100',
}
const sizes = {
sm: 'px-4 py-1.5 text-xs',
md: 'px-6 py-2.5 text-sm',
lg: 'px-8 py-3.5 text-base',
}
const colorMap = { contained, gradient, outline }
const classes = computed(() => [
'inline-flex items-center justify-center gap-2 font-medium rounded-lg cursor-pointer select-none',
'transition-all duration-200 hover:-translate-y-0.5 active:translate-y-0',
colorMap[props.variant]?.[props.color] ?? '',
sizes[props.size],
props.fullWidth && 'w-full',
props.disabled && 'opacity-60 pointer-events-none cursor-not-allowed',
])
</script>
<template>
<button :class="classes" :disabled="disabled">
<slot />
</button>
</template>