Skip to content

Commit

Permalink
show loading animation whie email is being sent
Browse files Browse the repository at this point in the history
  • Loading branch information
Robin Hellemans committed Jan 25, 2024
1 parent 8bdbed9 commit 4c9d8c6
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 10 deletions.
5 changes: 5 additions & 0 deletions components/ContactDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
:email-sent="emailSent"
:email-error="emailError"
:submitted="emailSent"
:loading="emailLoading"
@close="$emit('close')"
@submit="handleSubmit"
/>
Expand All @@ -30,6 +31,7 @@ const isFormAvailable = ref(true);
const dialogEl = ref<HTMLDialogElement | null>(null);
const emailSent = ref(false);
const emailError = ref(false);
const emailLoading = ref(false);
// Prevents overriding display: none on dialog when hidden
const dialogClasses = computed(() => (open ? "flex" : undefined));
Expand All @@ -54,10 +56,13 @@ watch(
async function handleSubmit(contactDetails: ContactDetails) {
try {
emailLoading.value = true;
await sendContactEmail(contactDetails);
emailSent.value = true;
} catch (error) {
emailError.value = true;
} finally {
emailLoading.value = false;
}
}
</script>
Expand Down
28 changes: 28 additions & 0 deletions components/animations/CircularProgressAnimation.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<template>
<!-- Inspired by https://gist.github.com/eYinka/873be69fae3ef27b103681b8a9f5e379 -->
<div class="relative h-6 w-6" role="progressbar">
<svg class="h-full w-full animate-spin" viewBox="0 0 100 100">
<circle
class="fill-transparent stroke-current stroke-[10] text-gray-200"
cx="50"
cy="50"
r="40"
/>
<circle
class="origin-center -rotate-90 fill-transparent stroke-current stroke-[10] transition-[stroke-dashoffset] duration-300"
:class="color"
stroke-linecap="round"
stroke-dasharray="400, 400"
stroke-dashoffset="calc(400 - (400 * 45) / 100)"
cx="50"
cy="50"
r="40"
/>
</svg>
</div>
</template>

<script lang="ts" setup>
// Should be Tailwind text-color class (e.g. text-yellow-300)
defineProps<{ color: string }>();
</script>
27 changes: 21 additions & 6 deletions components/buttons/RegularButton.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
<template>
<button
ref="buttonEl"
:type="buttonType"
class="transition-color rounded border-4 px-2 py-1 duration-200 hover:text-white focus-visible:text-white"
class="transition-color rounded border-4 px-2 py-1 duration-200 enabled:hover:text-white enabled:focus-visible:text-white disabled:cursor-progress"
:class="classes"
:disabled="loading"
>
<CircularProgressAnimation
v-if="loading"
:color="textColorClass"
class="!absolute"
/>
<slot />
</button>
</template>

<script setup lang="ts">
const { type } = defineProps<{
const { type, loading = false } = defineProps<{
buttonType: "button" | "submit" | "reset";
type: "primary" | "danger";
loading?: boolean;
}>();
const classes = computed(() =>
type === "primary"
? "border-yellow-300 focus-visible:bg-yellow-300 hover:bg-yellow-300"
: "border-orange-500 focus-visible:bg-orange-500 hover:bg-orange-500",
const classes = computed(() => {
const loadingClasses = loading
? "text-transparent flex items-center justify-center"
: "";
return type === "primary"
? `border-yellow-300 enabled:focus-visible:bg-yellow-300 enabled:hover:bg-yellow-300 ${loadingClasses}`
: `border-orange-500 enabled:focus-visible:bg-orange-500 enabled:hover:bg-orange-500 ${loadingClasses}`;
});
const textColorClass = computed(() =>
type === "primary" ? "text-yellow-300" : "text-orange-500",
);
</script>
4 changes: 2 additions & 2 deletions components/form/ContactForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
</ErrorMessage>
<div v-else class="flex justify-end gap-2">
<RegularButton button-type="reset" type="danger">Cancel</RegularButton>
<RegularButton button-type="submit" type="primary"
<RegularButton :loading="loading" button-type="submit" type="primary"
>Submit</RegularButton
>
</div>
Expand All @@ -54,7 +54,7 @@
import { useForm } from "vee-validate";
import { toTypedSchema } from "@vee-validate/zod";
defineProps<{ emailSent: boolean; emailError: boolean }>();
defineProps<{ emailSent: boolean; emailError: boolean; loading: boolean }>();
const emit = defineEmits<{
close: [void];
Expand Down
2 changes: 0 additions & 2 deletions todo.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
- Check accessibility
- Add loading animation?
- Prevent client spamming
- Check why pre-commit hook is not running on personal MB

0 comments on commit 4c9d8c6

Please sign in to comment.