Skip to content

Instantly share code, notes, and snippets.

@akodkod
Created February 19, 2023 21:04
Show Gist options
  • Save akodkod/e56c33dfa9774573cdaf27ebb16943a1 to your computer and use it in GitHub Desktop.
Save akodkod/e56c33dfa9774573cdaf27ebb16943a1 to your computer and use it in GitHub Desktop.
<script setup lang="ts">
import { LifebuoyIcon } from "@heroicons/vue/24/outline"
import { FunctionalComponent } from "vue"
import type { IconName } from "~/components/Icon.vue"
const props = withDefaults(defineProps<{
type?: "button" | "submit" | "reset"
variant?: "primary" | "secondary" | "tertiary"
size?: "sm" | "md" | "lg"
icon?: IconName | FunctionalComponent
rightIcon?: IconName | FunctionalComponent
loading?: boolean
disabled?: boolean
}>(), {
type: "button",
variant: "primary",
size: "md",
icon: undefined,
rightIcon: undefined,
loading: false,
disabled: false,
})
const variantClasses = computed(() => ({
primary: {
button: "bg-indigo-500 text-white hover:bg-indigo-600 active:bg-indigo-700",
icon: "text-white",
},
secondary: {
button: "bg-gray-100 text-gray-800 hover:bg-gray-200 active:bg-gray-300",
icon: "text-gray-800",
},
tertiary: {
button: "bg-transparent text-gray-800 hover:bg-gray-100 active:bg-gray-200",
icon: "text-gray-800",
},
}[props.variant]))
const sizeClasses = computed(() => ({
sm: {
button: "h-8 px-3 gap-1 text-sm",
icon: "h-3 w-3",
text: "translate-y-[-0.5px]",
},
md: {
button: "h-10 px-4 gap-1.5",
icon: "h-3.5 w-3.5",
text: "translate-y-[-1px]",
},
lg: {
button: "h-12 px-5 gap-2 text-lg",
icon: "h-4 w-4",
text: "",
},
}[props.size]))
</script>
<template>
<button
:class="[
'flex items-center justify-center font-medium rounded-md whitespace-nowrap',
variantClasses.button,
sizeClasses.button,
]"
>
<component
:is="icon"
v-if="icon"
:class="['text-gray-800', variantClasses.icon, sizeClasses.icon]"
/>
<span :class="sizeClasses.text">
<slot />
</span>
<component
:is="loading ? LifebuoyIcon : rightIcon"
v-if="rightIcon || loading"
:class="[
'text-gray-800',
variantClasses.icon,
sizeClasses.icon,
loading && 'animate-spin',
]"
/>
</button>
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment