SaveButton.vue 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. <script setup lang="ts">
  2. import { ref, computed } from "vue";
  3. const props = defineProps({
  4. defaultMessage: { type: String, default: "Save Changes" }
  5. });
  6. const emit = defineEmits(["clicked"]);
  7. const status = ref("default"); // enum: ["default", "disabled", "save-failure", "save-success"]
  8. const message = computed(() => {
  9. switch (status.value) {
  10. case "save-success":
  11. return `<i class="material-icons icon-with-button">done</i>Saved Changes`;
  12. case "save-failure":
  13. return `<i class="material-icons icon-with-button">error_outline</i>Failed to save`;
  14. case "disabled":
  15. case "saving":
  16. return "Saving...";
  17. case "verifying":
  18. return "Verifying...";
  19. default:
  20. return props.defaultMessage || "Save Changes";
  21. }
  22. });
  23. const style = computed(() => {
  24. switch (status.value) {
  25. case "save-success":
  26. return "is-success";
  27. case "save-failure":
  28. return `is-danger`;
  29. case "saving":
  30. case "verifying":
  31. case "disabled":
  32. return "is-default";
  33. default:
  34. return "is-primary";
  35. }
  36. });
  37. const handleSuccessfulSave = () => {
  38. if (status.value !== "save-success") {
  39. status.value = "save-success";
  40. setTimeout(() => {
  41. status.value = "default";
  42. }, 2000);
  43. }
  44. };
  45. const handleFailedSave = () => {
  46. if (status.value !== "save-failure") {
  47. status.value = "save-failure";
  48. setTimeout(() => {
  49. status.value = "default";
  50. }, 2000);
  51. }
  52. };
  53. defineExpose({
  54. handleSuccessfulSave,
  55. handleFailedSave
  56. });
  57. </script>
  58. <template>
  59. <div>
  60. <transition name="save-button-transition" mode="out-in">
  61. <button
  62. :class="['button', 'save-button-mixin', style]"
  63. :key="status"
  64. :disabled="status === 'disabled'"
  65. v-html="message"
  66. @click="emit('clicked')"
  67. />
  68. </transition>
  69. </div>
  70. </template>