Skip to content

Instantly share code, notes, and snippets.

@JonathanXDR
Last active February 28, 2024 12:13
Show Gist options
  • Save JonathanXDR/12e4cd9498157353decbe4671bb333e1 to your computer and use it in GitHub Desktop.
Save JonathanXDR/12e4cd9498157353decbe4671bb333e1 to your computer and use it in GitHub Desktop.
A Vue component built with the composition API & script setup to render @primer/octicons SVGs easily in your projects.
<script setup lang="ts">
import rawIconsData from '@primer/octicons/build/data.json'
import { computed, defineProps, onMounted, watch, withDefaults } from 'vue'
interface IconSVG {
tag: string
attrs: {
[key: string]: any
}
}
interface IconData {
[key: string]: {
name: string
keywords: string[]
heights: {
[key: string]: {
width: number
path: string
ast: any
}
}
}
}
const iconsData: IconData = rawIconsData
const props = withDefaults(
defineProps<{
name: string
size?: number
width?: number
height?: number
}>(),
{
size: 16
}
)
const iconData = computed(() => iconsData[props.name])
const iconSVG = computed<IconSVG | string>(() => {
if (!iconData.value || !iconData.value.heights[props.size]) {
return ''
}
const iconSizeData = iconData.value.heights[props.size]
const viewBox = `0 0 ${iconSizeData.width} ${props.size}`
const customWidth = props.width ?? iconSizeData.width
const customHeight = props.height ?? props.size
return {
tag: 'svg',
attrs: {
width: customWidth,
height: customHeight,
viewBox,
class: `octicon octicon-${props.name}`,
innerHTML: iconSizeData.path
}
}
})
const checkIconAvailability = () => {
if (!iconData.value) {
throw new Error(`The icon "${props.name}" does not exist.`)
}
if (!iconData.value.heights[props.size]) {
throw new Error(
`The size "${props.size}" does not exist for the icon "${props.name}".`
)
}
}
watch(() => props.name, checkIconAvailability)
watch(() => props.size, checkIconAvailability)
onMounted(checkIconAvailability)
</script>
<template>
<div v-if="typeof iconSVG === 'string'"></div>
<component :is="iconSVG.tag" v-else v-bind="iconSVG.attrs" />
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment