Today we are going to build a custom button component using Vue and Tailwindcss. Here you can look into my codepen.
As you have seen, I have kept different options for the colors, size, and roundness of the button. By default this button ships with a loading spinner. You could use the loading feature when you are waiting for the promise to return from axios.
It follows three steps -
Creating the Button Component
Create a file called LoadingButton.vue
in /src/Shared/LoadingButton.vue
and add
//LoadingButton.vue <template> <component :is="tag" :type="type" v-on="$listeners" :disabled="disableButton" :class="[btnClass, colorVariants]" :variant="variant" :variant-type="variantType" :size="size" :href="to" > <slot /> </component> </template> <script> export default { name: "LoadingButton", props: { tag: { type: String, default: "button" }, disabled: { type: Boolean, default: false }, variant: { type: String, default: "primary" }, variantType: { type: String, default: "normal" }, size: { type: String, default: "normal" }, rounded: { type: String, default: "medium" }, type: { type: String, default: "" }, to: { type: String } }, data() { return { loading: false, disableButton: this.disabled }; }, methods: { startLoading() { this.loading = true; this.disableButton = true; }, stopLoading() { this.loading = false; this.disableButton = false; } }, computed: { btnClass() { return { "base-spinner": this.loading == true, "cursor-not-allowed": this.disableButton == true, "base-button inline-flex align-middle align-items-center justify-center font-medium focus:outline-none border-2": true, "rounded-lg": this.rounded === "medium", "rounded-full": this.rounded === "large", "px-6 py-3": this.size == "normal", "px-4 py-2": this.size == "small" }; }, colorVariants() { switch (this.variant) { case "primary": switch (this.variantType) { case "normal": switch (this.disableButton) { case true: return "border-blue-300 bg-blue-300 text-white"; break; default: break; } return "border-blue-600 bg-blue-600 hover:bg-blue-700 hover:border-blue-700 text-white"; break; case "outline": return "border-gray-200 text-blue-500 hover:text-blue-700"; break; default: break; } break; case "danger": switch (this.variantType) { case "normal": switch (this.disableButton) { case true: return "border-red-300 bg-red-300 text-white"; break; default: break; } return "border-red-600 bg-red-600 hover:bg-red-700 hover:border-red-700 text-white"; break; case "outline": return "border-gray-200 text-red-500 hover:text-red-600"; break; default: break; } break; case "warning": switch (this.variantType) { case "normal": return "border-orange-600 bg-orange-600 hover:bg-orange-700 hover:border-orange-700 text-white"; break; default: break; } break; case "success": switch (this.variantType) { case "normal": switch (this.disableButton) { case true: return "border-green-300 bg-green-300 text-white"; break; default: break; } return "border-green-600 bg-green-600 hover:bg-green-700 hover:border-green-700 text-white"; break; case "outline": return "border-2 border-gray-200 text-green-500 hover:text-green-700"; break; default: break; } break; case "white": switch (this.variantType) { case "normal": return "border-white bg-white text-blue-600 hover:text-blue-800"; break; default: break; } break; case "secondary": switch (this.variantType) { case "outline": return "border-gray-300 text-gray-500 hover:text-blue-500"; break; default: break; } break; default: break; } } } }; </script>
Using the component
Now, we will use the loading-button
component in our App.vue
.
// App.vue <template> <div id="app"> <loading-button @click="submit" ref="submitButton">Save Changes</loading-button> </div> </template> <script> import LoadingButton from "@/Shared/LoadingButton"; export default { name: "app", components: { LoadingButton }, methods: { submit() { //calling the startLoading method of the button, which enables the button to loading state this.$refs.submitButton.startLoading(); } } }; </script>
Using the props
default option
Name | Type | Description | Accepted |
---|---|---|---|
variant | String | Color scheme of the button | primary , danger, success, warning, secondary |
variant-type | String | Normal button or ghost button | normal , outline |
rounded | String | border radius of the button | medium , large |
size | String | padding of the button | normal , small |
Methods Available
default option
Name | Description |
---|---|
startLoading | start loading state of the button |
stopLoading | stop loading state of the button |
N.B.
- Only primary, danger and success variant accepts a disabled prop.
- secondary variant is only available for outline button.
Top comments (0)