Features
Compose your own Icon components library, from SVG files to customizable Vue Components that you own.
Build-time SVG to Vue Component:
- One Vue component is created per
.svgfile - Use of the initial name of the icon, converted to PascalCase or snake-case with optional prefix and suffix. Example
user-badge.svgcan give:<IconUserBadge /><UserBadgeIcon /><user-badge />
- Optional support for folder-based namespacing - icon Components can directly be generated in your codebase, making versioning possible
Auto-Registration in Nuxt and Typing
- Full auto-import support (no manual registration) - each icon will be automatically imported and registered in the Nuxt project as individual Vue component in the tree
- Type-safe usage in
<template> - Works with Volar,
<script setup>, and TSX
SVG Output - Accessibility
- Components render a single
<svg>element - No additional wrappers or nested templates
- Attributes from the original SVG are preserved
Theming with CSS Custom Properties and Runtime Access
fill,stroke, andstroke-widthare replaced with CSS Custom Properties (CSS Custom Properties Guide) making theming directly possible- Original values are preserved as fallbacks
- Since CSS Custom Properties work at runtime, they can be used to dynamically change icons components in cascade for each individual icons and property (fill, stroke, stroke-width, etc.)
- Compatible with global tokens or scoped styles
Developer Experience:
- Can provide auto-completion and type-checking in your editor for each icons, as they are directly part of the Nuxt Build like any other component
- Vue DevTools support - unlike other solutions, this module generates Vue components that can be inspected and debugged in the Vue DevTools
The aim is to combine the control and quality of hand-authored components with the scalability and consistency of a build tool.
Comparison with Other Icon Strategies
| Feature | Third-party Libraries | Manual Vue Components | SVG Loaders (vite-svg-loader) | Nuxt Compose Icons |
|---|---|---|---|---|
| Setup | ✅ Easy | ⚠️ Manual | ⚠️ Requires config | ✅ Minimal |
| Source of truth | External package | Vue files | SVG files | SVG files |
| SVG output | Clean (often wrapped) | Custom | Inline | Clean, no wrappers |
| SVG control | Often abstracted | ✅ Full | ✅ Full | ✅ Full |
| Theming | ⚠️ Prop-based, limited | ✅ Manual CSS | ✅ CSS-based | ✅ CSS variables + props |
| Naming consistency | Library-defined | Developer-defined | File-based | Deterministic, file-based |
| Typing | ✅ Provided | ✅ Manual | Depends on setup | ✅ Generated & inferred |
| Scaling | Dependent on library updates | Maintenance-heavy | Flexible but unstructured | Structured, build-generated |
| Nuxt integration | ✅ Works | ✅ Auto-importable | ⚠️ Requires configuration | ✅ Native auto-import |
Example
xml
<svg viewBox="0 0 24 24" <!-- other attributes...--> >
<path d="..." fill="#000" stroke="#fff" stroke-width="2" />
</svg>will generate:
vue
<template>
<svg viewBox="0 0 24 24">
<path
d="..."
fill="var(--icon-fill, #000)"
stroke="var(--icon-stroke, #fff)"
stroke-width="var(--icon-stroke-width, 2)"
/>
</svg>
</template>This provides a balance of control, flexibility, and developer experience, tailored for projects using custom icons or building design systems.