Dynamic icons
Load Vadivam icons safely from runtime names, validate untrusted values, and choose the appropriate dynamic API for each framework.
Use a dynamic icon only when the icon name is data rather than source code—for example, a CMS field or navigation configuration. For known icons, prefer a static named import because it is simpler and directly tree-shakeable.
Dynamic names are kebab-case values such as activity, arrow-right, and trash. Framework packages type them as IconName and expose an iconNames list and lazy dynamicIconImports map.
Component API
React, React Native, Vue, Solid, Preact, and Lit export a named DynamicIcon from their /dynamic entry point. Svelte and Astro expose their dynamic component as the default export, and Angular uses a standalone directive. Qwik, Flutter, and Compose look icons up in a registry instead, and in plain HTML the <vadivam-icon> element takes a name attribute. Pick your framework:
import { DynamicIcon, type IconName } from "vadivam-react/dynamic";
export function DataIcon({ name }: { name: IconName }) {
return (
<DynamicIcon
name={name}
size={20}
fallback={<span aria-hidden="true">…</span>}
aria-label={name}
/>
);
}import { DynamicIcon } from "vadivam-react-native/dynamic";
<DynamicIcon name="search" size={20} fallback={null} />;<script setup lang="ts">
import { DynamicIcon } from "vadivam-vue/dynamic";
</script>
<template>
<DynamicIcon name="activity" :size="20" title="Activity" />
</template><script lang="ts">
import DynamicIcon from "vadivam-svelte/dynamic";
</script>
<DynamicIcon name="activity" size={20} title="Activity" />import { DynamicIcon } from "vadivam-solid/dynamic";
<DynamicIcon name="activity" size={20} fallback={null} />;import { Component } from "@angular/core";
import { DynamicIcon } from "vadivam-angular/dynamic";
@Component({
imports: [DynamicIcon],
template: '<svg vadivamDynamicIcon="activity" title="Activity"></svg>',
})
export class StatusIcon {}---
import DynamicIcon from "vadivam-astro/dynamic";
---
<DynamicIcon name="activity" size={20} title="Activity" />import { DynamicIcon } from "vadivam-preact/dynamic";
<DynamicIcon name="activity" size={20} fallback={null} />;import { DynamicIcon } from "vadivam-lit/dynamic";
html`${DynamicIcon({ name: "activity", size: 20, fallback: "" })}`;import { icons } from "vadivam-qwik";
const Icon = icons.Activity;
<Icon size={20} />;<script type="module" src="https://cdn.jsdelivr.net/npm/vadivam/dist/elements.js"></script>
<vadivam-icon name="activity" size="20"></vadivam-icon>final icon = VadivamIcons.all['activity'];
if (icon != null) VadivamIcon(icon, size: 20);VadivamIcons.byName("activity")?.let { Icon(it, contentDescription = null) }The component loads the matching per-icon module. A fallback is optional. Keep untrusted strings outside the component until they have been checked against iconNames:
import { iconNames, type IconName } from "vadivam-react/dynamic";
export function isIconName(value: string): value is IconName {
return iconNames.includes(value as IconName);
}
See each framework guide for complete syntax.
Custom icon data
Validate runtime icon names against iconNames before rendering them. The generic Icon and createVadivamIcon APIs also accept custom icon data, but constrain it to safe SVG geometry: circle, ellipse, line, path, polygon, polyline, and rect, with geometry, presentation, accessibility, class, and data attributes. Scripts, animation elements, links, images, raw HTML, string event handlers, URL attributes, and malformed property names are discarded.
This custom-data API is for icon geometry, not arbitrary SVG documents. Named generated icons and dynamic icons selected from iconNames are unchanged.
Import map API
Each framework package exports its generated lazy-import map from /dynamicIconImports:
import dynamicIconImports, {
iconNames,
} from "vadivam-react/dynamicIconImports";
const module = await dynamicIconImports.activity();
const Activity = module.default;
This low-level API is useful for a custom cache or loading boundary. Its module shape is framework-specific, so do not share loaded modules across framework packages.
Bundle and rendering notes
How are dynamic icons bundled?
Dynamic imports create separate asynchronous modules; the exact chunks depend on the bundler.
Do I still need to validate names at runtime?
Yes. The name API is restricted to generated icon names in TypeScript, but runtime data still needs validation against iconNames.
What fallback types are supported?
Fallback types differ by framework: React-family packages accept renderable nodes, Svelte accepts a snippet, and Angular’s directive accepts icon-node data.
Can I use dynamic icons with the core package?
The core vadivam package has no lazy DynamicIcon component. Use a small icon-node map with createIcons, or choose a framework package.