Skip to content

Instantly share code, notes, and snippets.

@lisonge
Last active February 5, 2026 06:32
Show Gist options
  • Select an option

  • Save lisonge/0823670565d4c727f23ea14c4bcb826f to your computer and use it in GitHub Desktop.

Select an option

Save lisonge/0823670565d4c727f23ea14c4bcb826f to your computer and use it in GitHub Desktop.
const modules = import.meta.glob<string>('@/assets/svg/*.svg', {
eager: true,
query: 'raw',
import: 'default',
});
export default Object.fromEntries(
Object.entries(modules).map(([k, v]) => {
const name = k.split('/').at(-1)!.split('.')[0];
const t = document.createElement('template');
t.innerHTML = v;
return [name, t.content.firstChild as SVGSymbolElement];
}),
);
<script lang="ts">
const svgElMap = computedAsync(
async () => (await import('./svg')).default,
{},
);
</script>
<script setup lang="ts">
const props = withDefaults(
defineProps<{
name: string;
}>(),
{},
);
const svgEl = computed(() => svgElMap.value[props.name]);
const actualEl = shallowRef<SVGSVGElement>();
watchEffect(() => {
const s = svgEl.value;
const a = actualEl.value;
if (!s || !a) return;
a.replaceChildren(...Array.from(s.cloneNode(true).childNodes));
});
</script>
<template>
<svg
v-if="svgEl"
ref="actualEl"
class="SvgIcon"
:name="name"
:viewBox="svgEl.getAttributeNS(null, 'viewBox') || undefined"
:fill="svgEl.getAttribute('fill') || undefined"
></svg>
</template>
<style>
.SvgIcon {
display: block;
overflow: hidden;
height: var(--svg-h, 1em);
}
.SvgIcon:not([fill]) {
fill: currentColor;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment