Last active
June 28, 2022 20:41
-
-
Save joakimriedel/aa02d774f1aa53500631024ec7ecf45d to your computer and use it in GitHub Desktop.
Vue component for SVG icons using Vue 3, async import using Vite, and Typescript strict typings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- This script for defining icon sources and type could be put in external ts file --> | |
<script lang="ts"> | |
/** define all the icons that we want to make available here */ | |
const iconSources = { | |
signin: () => | |
import("@fortawesome/fontawesome-free/svgs/solid/sign-in-alt.svg"), | |
signout: () => | |
import("@fortawesome/fontawesome-free/svgs/solid/sign-out-alt.svg"), | |
plus: () => import("@fortawesome/fontawesome-free/svgs/solid/plus.svg"), | |
}; | |
export type IconSources = keyof typeof iconSources; | |
</script> | |
<script setup lang="ts"> | |
import { PropType, ref, toRefs, watch } from "vue"; | |
import fallbackSrc from "../assets/fallback.svg"; | |
const props = defineProps({ | |
// using PropType<IconSources> here to restrict input to our defined icons only | |
// will also provide intellisense if you use Volar extension in VS Code | |
icon: { type: String as PropType<IconSources>, required: true }, | |
width: { type: Number, required: false, default: 25 }, | |
height: { type: Number, required: false, default: 25 }, | |
}); | |
const { icon, width, height } = toRefs(props); | |
const iconSrc = ref<string>(); | |
// use watch to reload icon source if prop 'icon' changes | |
watch( | |
icon, | |
async (newIcon) => (iconSrc.value = (await iconSources[newIcon]()).default), | |
{ | |
// set immediate flag for initial load | |
immediate: true, | |
} | |
); | |
</script> | |
<template> | |
<transition> | |
<img v-if="iconSrc" :src="iconSrc" :width="width" :height="height" /> | |
<img v-else :src="fallbackSrc" :width="width" :height="height" /> | |
</transition> | |
</template> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
see the following issue on how to inline svg icons using vite: vitejs/vite#1204