This skill is used in any vite + vue3 project to quickly initialize an Iconify icon system consistent with the pure-admin approach, providing:
IconifyIconOffline(offline icons)IconifyIconOnline(online icons)useRenderIcon(unified分流 rendering)offlineIcon(local offline icon mapping and compatibility aliases)
The goal is to let the business layer only care about "which icon to pass", and not about whether the underlying implementation is offline, online, or a component object.
Applicable scenarios
- A new project integrating the Iconify icon system for the first time
- An old project wants to unify the icon rendering entry point and reduce repeated encapsulation everywhere
- Needs to be compatible with the old
IconXxxnaming, while also supporting the new-stylecollection/name、collection:name - Menus, routes, and configuration-driven scenarios need to return
Componenttype icons
Core principles [CRITICAL]
- Unified export: business code should preferentially use the
ReIconexport, do not re-encapsulate everywhere@iconify/vue - Offline first: high-frequency icons should preferentially use offline mapping, and long-tail icons should go online
- Configuration-driven scenarios should preferentially use
useRenderIcon: menus, routes, and table configurations should uniformly return components - Keep the compatibility layer: the old
IconXxxis only for compatibility, and is not the first choice for new code
1. Copying strategy (define the mode first) [CRITICAL]
Prefer the "copy + minimal modification" strategy, and do not rewrite from memory.
1.1 Preferred sources
- The original pure-admin solution (architecture reference)
- The actual ReIcon code already implemented in your project (implementation reference)
If there is already a runnable src/components/ReIcon, preferentially copy it completely and then make minimal changes.
1.2 File mapping (must be executed according to the table)
Map the source project src/components/ReIcon to the same path in the target project:
来源文件 -> 目标文件
src/components/ReIcon/index.ts -> src/components/ReIcon/index.ts
src/components/ReIcon/type.ts -> src/components/ReIcon/type.ts
src/components/ReIcon/src/hooks.ts -> src/components/ReIcon/src/hooks.ts
src/components/ReIcon/src/iconifyIconOffline.ts -> src/components/ReIcon/src/iconifyIconOffline.ts
src/components/ReIcon/src/iconifyIconOnline.ts -> src/components/ReIcon/src/iconifyIconOnline.ts
src/components/ReIcon/src/offlineIcon.ts -> src/components/ReIcon/src/offlineIcon.ts
Copying only these 6 files is enough to complete the core capability.
1.3 Only these 4 types of content are allowed to be changed
- Path alias:
@/whether it exists - Entry registration location:
main.tsorsrc/plugins/icon.ts - Offline icon list:
offlineIcon.tsthe imports and mapping items - Historical compatibility aliases:
IconXxxwhether they need to be retained
Apart from the above changes, do not proactively change the API, types, or export structure.
2. Install dependencies
Install in the target project:
pnpm add -D @iconify/json @iconify/vue unplugin-icons vite-svg-loader
Optional tools:
pnpm add @pureadmin/utils
If you use the
~icons/...component import method,unplugin-iconsis required.
3. Configure the Vite plugin
In vite.config.ts(or the plugin aggregation file), add unplugin-icons:
import Icons from "unplugin-icons/vite";
export default defineConfig({
plugins: [
vue(),
Icons({
compiler: "vue3",
scale: 1,
}),
],
});
4. Create the ReIcon directory structure
Recommended structure:
src/components/ReIcon/
├── index.ts
├── type.ts
└── src/
├── iconifyIconOffline.ts
├── iconifyIconOnline.ts
├── hooks.ts
└── offlineIcon.ts
5. Ready-made code package (can be copied directly)
The template code has been split into the templates/ directory; copy it directly by path, and there is no need to manually extract code from the documentation.
templates/ReIcon/index.ts
templates/ReIcon/type.ts
templates/ReIcon/src/iconifyIconOffline.ts
templates/ReIcon/src/iconifyIconOnline.ts
templates/ReIcon/src/hooks.ts
templates/ReIcon/src/offlineIcon.ts
templates/setup-icon.ts
Copying rules:
templates/ReIcon/**->src/components/ReIcon/**templates/setup-icon.ts->src/plugins/icon.ts(or merge into your entry registration file)- After copying, only change the content listed in the "required changes checklist".
If you want to "copy the old project verbatim without changing a single character," copy the old project
offlineIcon.tsin full, then fill in the missing exports against the template.
6. Entry registration (optional but recommended)
In src/plugins/icon.ts(or the equivalent entry), register:
import type { App } from "vue";
import { IconifyIconOffline, IconifyIconOnline, registerOfflineIcons } from "@/components/ReIcon";
export function setupIcon(app: App) {
registerOfflineIcons(app);
app.component("IconifyIconOffline", IconifyIconOffline);
app.component("IconifyIconOnline", IconifyIconOnline);
}
If the old project already makes extensive use of Element Plus global icon aliases, do not delete the original registration; only add the iconify capability.
7. Business usage conventions
7.1 Template direct output (offline)
<IconifyIconOffline icon="ep/menu" width="18" height="18" />
7.2 Template direct output (online)
<IconifyIconOnline icon="ri:home-4-line" width="18" height="18" />
7.3 Configuration-driven (menu/route/table)
import { useRenderIcon } from "@/components/ReIcon";
const iconComp = useRenderIcon("ep/setting", { width: "18px", height: "18px" });
7.4 Menu configuration conventions
Menu item icon can be written directly as:
- Old alias:
IconUser - Offline string:
ep/setting - Online string:
ri:shield-user-line
The rendering layer uniformly goes through useRenderIcon; do not write another set of icon branching logic inside the menu component.
8. Must-change checklist (check immediately after copying) [CRITICAL]
~icons/...Whether the import takes effect (if it does not take effect, it is usually a missing configuration ofunplugin-icons)- path alias
@/components/ReIconwhether it can be resolved registerOfflineIcons(app)whether it is executed during the application startup phase- If the old page uses
IconXxx, whether the corresponding alias exists
9. Offline icon expansion strategy
Expand offlineIcon.ts:
- The same online icon is reused frequently in the backend
- Sensitive to network dependency (intranet or weak network)
- Want the string to stably hit the offline path in
useRenderIconstable hit offline path
Expansion steps:
- Import the icon:
import EpXxx from "~icons/ep/xxx" - Add a mapping:
offlineIcons["ep/xxx"] = markRaw(EpXxx) - Add a compatibility alias if necessary:
aliasIcons.IconXxx = offlineIcons["ep/xxx"]
10. Verification checklist
-
vite.config.tshas enabledunplugin-icons -
ReIconThe directory and export structure are complete -
useRenderIconCan handle components, offline strings, and online strings at the same time - Old
IconXxxpages are not broken - Configuration-driven scenarios such as menus/routes can render icons normally
- At least one example page covers all four usages (old alias, offline, online, hook)
11. Common pitfalls [CRITICAL]
- Accidentally deleting original comments and explanations: integration refactoring should use minimal patches; do not overwrite entire files and cause information loss
- Style class names too broad: example pages should avoid
.icon-titlenames that easily conflict like this; use more locally semantic class names - Mistaking the compatibility layer for the standard:
IconXxxonly preserves compatibility; new code should prioritizeep/menu、ri:...、useRenderIcon - Repeated encapsulation in the business layer: do not bypass
ReIconto create another set ofrenderIcon
12. Recommended implementation order (10 minutes)
- Dependency installation + Vite plugin
- Copy the 6
ReIconfiles according to the mapping table - Entry registration (keep old aliases)
- Choose a menu or example page to integrate
useRenderIcon - After completing the verification checklist, migrate business pages in batches
13. References
- Pure-Admin Icon solution research report: https://01s-11comm-doc.ruan-cat.com/docs/reports/2025-11-14-pure-admin-icon-solution-research.md
- Iconify icon search: https://icon-sets.iconify.design/
- Iconify official documentation: https://iconify.design/
14. Icon animations and gradients (useIconEffect)
Inject multi-color gradient fills and breathing animations (glow + scaling) into Iconify SVG icons.
Quick start
# GSAP 策略需要安装
pnpm add gsap
<script setup lang="ts">
import { ref } from "vue";
import { useIconEffect } from "@/components/ReIcon";
const iconRef = ref<HTMLElement | null>(null);
useIconEffect({
target: iconRef,
gradient: {
stops: [
{ offset: "0%", color: "#3cd8ff" },
{ offset: "100%", color: "#2f73ff" },
],
},
breath: {
strategy: "gsap",
gsap: { scale: [1, 1.12], duration: 2.2, ease: "sine.inOut" },
},
});
</script>
Detailed documentation
For detailed content including the complete API reference, gradient injection principles, three-layer animation strategy selection, CSS solutions, multi-card scenarios, global coordinator, known constraints and pitfalls, see the following reference files:
| reference files | Content | When to read |
|---|---|---|
references/useIconEffect.md |
Complete API reference, core principles of gradient injection, three-layer animation strategies (GSAP/CSS/Auto), CSS solutions, strategy selection guide, known constraints and pitfalls | When useIconEffect is needed |
references/breath-coordinator.md |
Global coordinator pattern (Pinia/Composable), cost quantification of independent per-instance usage, decision tree, integration with KeepAlive | ≥4 instances or when global pause/resume is needed |
Template file
| Template file | Description |
|---|---|
templates/ReIcon/src/useIconEffect.ts |
useIconEffect composable source code |
templates/ReIcon/type.ts |
Type definitions (GradientStop, IconBreathConfig, etc.) |
templates/breathCoordinator.pinia.ts |
Global coordinator — Pinia Store version |
templates/breathCoordinator.composable.ts |
Global coordinator — pure Composable version |