Files
ForgeFlow-ERP/frontend/src/components/ActionButton.vue
T
2026-06-12 16:00:56 +08:00

59 lines
1.9 KiB
Vue

<template>
<button
class="action-button"
:class="[
`action-button-${normalizedVariant}`,
`action-button-${normalizedSize}`,
{ 'action-button-icon-only': iconOnly }
]"
:type="type"
:disabled="disabled || loading"
:data-button-kind="normalizedVariant"
:data-button-tone="buttonTone"
>
<AppIcon v-if="icon" :name="icon" :tone="iconTone" />
<span v-if="!iconOnly" class="action-button-label"><slot /></span>
<span v-if="loading" class="action-button-spinner" aria-hidden="true"></span>
</button>
</template>
<script setup>
import { computed } from "vue";
import AppIcon from "./AppIcon.vue";
const props = defineProps({
icon: { type: String, default: "" },
variant: { type: String, default: "secondary" },
size: { type: String, default: "md" },
type: { type: String, default: "button" },
disabled: { type: Boolean, default: false },
loading: { type: Boolean, default: false },
iconOnly: { type: Boolean, default: false }
});
const normalizedVariant = computed(() => {
return ["primary", "secondary", "success", "warning", "danger", "ghost"].includes(props.variant)
? props.variant
: "secondary";
});
const normalizedSize = computed(() => (["sm", "md", "lg"].includes(props.size) ? props.size : "md"));
const buttonTone = computed(() => {
if (normalizedVariant.value === "danger") return "danger";
if (normalizedVariant.value === "primary") return "primary";
if (normalizedVariant.value === "success") return "success";
if (normalizedVariant.value === "warning") return "warning";
return "neutral";
});
const iconTone = computed(() => {
if (normalizedVariant.value === "danger") return "danger";
if (normalizedVariant.value === "primary") return "primary";
if (normalizedVariant.value === "success") return "success";
if (normalizedVariant.value === "warning") return "warning";
return "muted";
});
</script>