UNPKG

nuxt-svg-sprite-icon

Version:

A powerful SVG sprite module for Nuxt 3 & 4 that automatically generates SVG sprites from your assets and provides an easy-to-use component for displaying icons.

422 lines (321 loc) • 11.7 kB
# Nuxt SVG Sprite Icon <p align="center"> <img width="200px" src="./assets/nuxt-svg-sprite-icon.png" /> </p> <p align=center> <a target="_blank" href="https://vuejs.org/" title="vue"> <a target="_blank" href="http://nodejs.org/download/" title="Nuxt version"> <img src="https://img.shields.io/badge/Nuxt-%3E%3D%203.0.0%20%7C%7C%20%5E4.0.0-brightgreen.svg"> </a> <img src="https://img.shields.io/badge/Vue-%3E%203.0.0-brightgreen.svg"> </a> <a target="_blank" href="http://nodejs.org/download/" title="Node version"> <img src="https://img.shields.io/badge/Node-%3E%3D%2020.0.0-brightgreen.svg"> </a> <a target="_blank" href="https://github.com/MikeCheng1208/nuxt-svg-sprite-icon/pulls" title="PRs Welcome"> <img src="https://img.shields.io/badge/PRs-welcome-blue.svg"> </a> </p> <p align=center>A powerful SVG sprite module for Nuxt 3 & Nuxt 4 that automatically generates SVG sprites from your assets and provides an easy-to-use component for displaying icons.</p> <p align="center"> <a target="_blank" href="https://www.npmjs.com/package/nuxt-svg-sprite-icon"> <img src="https://nodei.co/npm/nuxt-svg-sprite-icon.png?downloads=true&downloadRank=true&stars=true" alt="NPM version"> </a> </p> ## Features - šŸš€ **Auto-generated SVG sprites** - Automatically scans and converts SVG files to sprite format - šŸ“ **Nested folder support** - Organize your icons in folders for better structure - šŸŽØ **CSS-only styling** - Full control over appearance using CSS classes - ⚔ **Hot reload** - Development mode file watching for instant updates - šŸŽÆ **TypeScript support** - Full type safety out of the box - 🌈 **Framework agnostic** - Works seamlessly with UnoCSS, Tailwind, or any CSS framework - šŸ“¦ **Zero configuration** - Works out of the box with sensible defaults - 🪶 **Lightweight** - Minimal API surface with maximum flexibility - šŸ”§ **Enhanced SVG compatibility** - Handles complex SVGs with styles, IDs, and defs ## Quick Setup 1. Add `nuxt-svg-sprite-icon` dependency to your project ```bash # Using pnpm pnpm add -D nuxt-svg-sprite-icon # Using yarn yarn add --dev nuxt-svg-sprite-icon # Using npm npm install --save-dev nuxt-svg-sprite-icon ``` 2. Add `nuxt-svg-sprite-icon` to the `modules` section of `nuxt.config.ts` ```js export default defineNuxtConfig({ modules: [ 'nuxt-svg-sprite-icon' ] }) ``` 3. Create your SVG assets directory and add some SVG files ``` assets/ svg/ home.svg search.svg user/ profile.svg settings.svg ``` 4. Use the SVG icons in your components ```vue <template> <div> <!-- Basic usage --> <SvgIcon name="home" /> <!-- With CSS classes --> <SvgIcon name="home" class="w-6 h-6 text-blue-500" /> <!-- Nested folder --> <SvgIcon name="user/profile" class="w-8 h-8 fill-green-500" /> <!-- Container approach --> <div class="w-100px h-100px"> <SvgIcon name="search" class="w-full h-full fill-red-500" /> </div> </div> </template> ``` That's it! You can now use SVG icons with complete CSS control ✨ ## SVG Compatibility This module has enhanced SVG processing capabilities that handle various types of SVG files: ### āœ… Supported SVG Features - **Inline styles and CSS classes** - Automatically converts `<style>` tags and CSS classes to inline styles - **Gradients / Paint servers (`url(#...)`)** - Supports `linearGradient` / `radialGradient` (including `fill="url(#...)"` and `stroke="url(#...)"`) - **Complex defs** - Preserves functional definitions like `clipPath`, `mask`, `pattern`, and `filter` - **ID conflict resolution** - Automatically prefixes IDs to prevent conflicts between different sprites - **Various SVG formats** - Works with SVGs from different design tools (Figma, Sketch, Illustrator, etc.) ### Examples of Supported SVG Types **SVG with CSS styles:** ```xml <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.721 17.39"> <defs> <style> .cls-1{fill:#fff} </style> </defs> <path class="cls-1" d="M0 6.3L6 11..."/> </svg> ``` **SVG with inline fills:** ```xml <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path fill="white" d="M9.84375 16.0469V19.1178..."/> </svg> ``` **SVG with clipPaths and complex defs:** ```xml <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <g clip-path="url(#clip0)"> <path fill="white" d="..."/> </g> <defs> <clipPath id="clip0"> <rect width="24" height="24"/> </clipPath> </defs> </svg> ``` **SVG with gradients / paint servers (`url(#...)`):** ```xml <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <defs> <linearGradient id="paint0_linear" x1="20" y1="0" x2="0" y2="20" gradientUnits="userSpaceOnUse"> <stop stop-color="#FFCF45"/> <stop offset="1" stop-color="#FFB92A"/> </linearGradient> </defs> <path d="M10 1L12.5 7H19L14 11L16 18L10 14L4 18L6 11L1 7H7.5Z" fill="url(#paint0_linear)"/> </svg> ``` All these formats are automatically processed and optimized for use in sprite systems while maintaining visual fidelity. ## Configuration You can configure the module by adding a `svgSprite` section to your `nuxt.config.ts`: ```js export default defineNuxtConfig({ modules: ['nuxt-svg-sprite-icon'], svgSprite: { // Source directory for SVG files input: '~/assets/svg', // Output directory for generated sprites output: '~/assets/sprite/gen', // Default sprite name (for files in root of input directory) defaultSprite: 'icons', // Global CSS class for all svg-icon instances elementClass: 'svg-icon', // Whether to optimize SVG files (requires svgo) optimize: false } }) ``` ### Nuxt 4 Configuration For Nuxt 4 projects, you can use the new directory structure: ```js export default defineNuxtConfig({ future: { compatibilityVersion: 4, }, modules: ['nuxt-svg-sprite-icon'], svgSprite: { // Use app directory for Nuxt 4 input: './app/assets/svg', output: './app/assets/sprite/gen', defaultSprite: 'icons', elementClass: 'svg-icon', } }) ``` The module automatically detects Nuxt 4 compatibility mode and adjusts paths accordingly. ### Configuration Options | Option | Type | Default | Description | |--------|------|---------|-------------| | `input` | `string` | `'~/assets/svg'` | Directory containing original SVG files | | `output` | `string` | `'~/assets/sprite/gen'` | Directory for generated sprite files | | `defaultSprite` | `string` | `'icons'` | Name of default sprite (for SVGs in root input directory) | | `elementClass` | `string` | `'svg-icon'` | Global CSS class applied to all `<SvgIcon>` elements | | `optimize` | `boolean` | `false` | Enable SVG optimization using SVGO | ## Component API ### SvgIcon Component The `<SvgIcon>` component is automatically registered and available globally. #### Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `name` | `string` | - | **Required.** Name of the icon (supports nested paths like `user/example`) | #### Usage Examples ```vue <template> <!-- Basic usage with default 1em size --> <SvgIcon name="home" /> <!-- Control size with CSS classes --> <SvgIcon name="home" class="w-6 h-6" /> <SvgIcon name="home" class="w-8 h-8" /> <!-- Control size with font-size --> <SvgIcon name="home" class="text-2xl" /> <SvgIcon name="home" style="font-size: 3rem;" /> <!-- Control color --> <SvgIcon name="home" class="text-blue-500" /> <SvgIcon name="home" class="fill-red-600" /> <!-- Nested folder icons --> <SvgIcon name="user/profile" class="w-10 h-10 text-green-500" /> <!-- Container-based sizing --> <div class="w-20 h-20"> <SvgIcon name="search" class="w-full h-full fill-purple-500" /> </div> <!-- Custom styles --> <SvgIcon name="home" class="custom-icon" /> <!-- Interactive states --> <SvgIcon name="home" class="w-8 h-8 text-blue-500 hover:text-blue-700 transition-colors cursor-pointer" /> <!-- Responsive sizing --> <SvgIcon name="home" class="w-4 h-4 md:w-6 md:h-6 lg:w-8 lg:h-8" /> </template> <style scoped> .custom-icon { width: 3rem; height: 3rem; color: #3b82f6; transition: all 0.2s ease; } .custom-icon:hover { color: #1d4ed8; transform: scale(1.1); } </style> ``` ## File Organization The module supports nested folder structures: ``` assets/svg/ ā”œā”€ā”€ home.svg → <SvgIcon name="home" /> ā”œā”€ā”€ search.svg → <SvgIcon name="search" /> ā”œā”€ā”€ user/ │ ā”œā”€ā”€ profile.svg → <SvgIcon name="user/profile" /> │ └── settings.svg → <SvgIcon name="user/settings" /> └── admin/ ā”œā”€ā”€ dashboard.svg → <SvgIcon name="admin/dashboard" /> └── users.svg → <SvgIcon name="admin/users" /> ``` ## Development ```bash # Install dependencies npm install # Generate type stubs and prepare development environment npm run dev:prepare # Develop with the playground npm run dev # Build the playground npm run dev:build # Build the module npm run prepack # Run type checking npm run test:types # Release new version npm run release ``` ## CSS Framework Integration ### With UnoCSS/Tailwind CSS ```vue <template> <!-- Size control --> <SvgIcon name="home" class="w-6 h-6" /> <SvgIcon name="home" class="w-8 h-8" /> <!-- Color control --> <SvgIcon name="home" class="text-blue-500" /> <SvgIcon name="home" class="fill-red-600" /> <!-- Combined styling --> <SvgIcon name="user/profile" class="w-10 h-10 text-green-500 hover:text-green-700 transition-all duration-200" /> <!-- Responsive design --> <SvgIcon name="home" class="w-4 h-4 sm:w-6 sm:h-6 lg:w-8 lg:h-8" /> <!-- Container-based approach --> <div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center"> <SvgIcon name="home" class="w-8 h-8 text-gray-600" /> </div> </template> ``` ### With Custom CSS ```vue <template> <SvgIcon name="home" class="icon-large" /> <SvgIcon name="user/profile" class="icon-animated" /> </template> <style scoped> .icon-large { width: 4rem; height: 4rem; color: #3b82f6; } .icon-animated { width: 2rem; height: 2rem; transition: transform 0.3s ease; } .icon-animated:hover { transform: rotate(180deg) scale(1.2); } </style> ``` ## Troubleshooting ### Icons not displaying 1. **Check file paths**: Ensure your SVG files are in the correct directory 2. **Verify build**: Make sure the module generated sprite files in your output directory 3. **Check console**: Look for any error messages in the browser console 4. **Restart dev server**: Try restarting your development server ### Icons appear as squares This usually indicates that the SVG files have incorrect or missing `viewBox` attributes. The module attempts to extract or generate appropriate viewBox values, but you may need to manually fix your SVG files. ### Size control issues - Use `width` and `height` CSS properties or utility classes like `w-6 h-6` - The default size is `1em`, so you can also control size via `font-size` - For container-based sizing, use `w-full h-full` on the icon ## Performance Considerations - All sprites are injected into the DOM on page load - For large icon sets, consider organizing icons into different folders/sprites - SVG optimization can help reduce file sizes (enable with `optimize: true`) - The CSS-only approach means no JavaScript is needed for styling ## License MIT.