52 lines
1.1 KiB
Vue
52 lines
1.1 KiB
Vue
<template>
|
|
<component
|
|
:is="component"
|
|
v-if="component"
|
|
class="svg-icon"
|
|
:style="iconStyle"
|
|
aria-hidden="true"
|
|
focusable="false"
|
|
/>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
|
|
import { iconRegistry } from '@/components/icons/registry'
|
|
|
|
/** @typedef {import('@/components/icons/icon-names').IconName} IconName */
|
|
|
|
const props = defineProps({
|
|
/** @type {import('vue').PropType<IconName>} */
|
|
name: { type: String, required: true },
|
|
size: { type: [String, Number], default: '1.25rem' },
|
|
color: { type: String, default: 'transparent' },
|
|
})
|
|
|
|
const component = computed(() => {
|
|
const c = iconRegistry[props.name]
|
|
if (!c && import.meta.env.DEV) {
|
|
console.warn(`[SvgIcon] unknown icon "${props.name}"`)
|
|
}
|
|
|
|
return c
|
|
})
|
|
|
|
const sizeValue = computed(() => (typeof props.size === 'number' ? `${props.size}px` : props.size))
|
|
|
|
const iconStyle = computed(() => ({
|
|
width: sizeValue.value,
|
|
height: sizeValue.value,
|
|
color: props.color,
|
|
flexShrink: 0,
|
|
}))
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.svg-icon {
|
|
display: inline-block;
|
|
vertical-align: middle;
|
|
fill: currentcolor;
|
|
}
|
|
</style>
|