SVGFusion

May 20, 2026 · View on GitHub

SVGFusion Logo

SVGFusion

SVGs to React, Vue 3, and React Native Components

Convert SVG files into blazing-fast React, Vue 3, and React Native components with automatic color extraction, full TypeScript support, and seamless integration into any modern workflow.

npm version TypeScript React Vue.js

DocumentationPackages GuideNPMTry Interactive Playground

Quick Start

# Using main package (includes all features)
npx svgfusion ./icons --output ./components --framework react

# Or install globally
npm install -g svgfusion
svgfusion ./icons --output ./components --framework vue

# For CLI-only usage (smaller download)
npx svgfusion-cmd ./icons --output ./components --framework react

Available Packages

SVGFusion is available as a monorepo with specialized packages for different use cases:

PackageDescriptionInstallationCLI UsageUse Case
svgfusionComplete toolkitnpm install svgfusionnpx svgfusionGeneral usage
svgfusion-cmdCommand-line interfacenpm install -g svgfusion-cmdnpx svgfusion-cmdCLI-only usage
svgfusion-domBrowser-optimizednpm install svgfusion-domN/A (browser only)Web applications
svgfusion-coreCore enginenpm install svgfusion-coreN/A (programmatic only)Custom tooling
svgfusion-reactReact generatornpm install svgfusion-reactN/A (programmatic only)React-only projects
svgfusion-vueVue generatornpm install svgfusion-vueN/A (programmatic only)Vue-only projects
svgfusion-react-nativeReact Native generatornpm install svgfusion-react-nativeN/A (programmatic only)React Native-only projects

Tip: For most users, the main svgfusion package includes everything you need. Use specialized packages only if you need specific functionality.

CLI Options

Choose the right CLI option for your needs:

CommandPackageSizeWhen to Use
npx svgfusionsvgfusionFull bundleGeneral usage, includes all features
npx svgfusion-cmdsvgfusion-cmdSmallerCLI-only usage, faster downloads

Both commands support the same CLI options and features. The difference is package size and dependencies.

Key Features

  • Advanced Transformations: Color splitting, stroke width extraction, and SVG optimization
  • Framework Support: Generate React, Vue 3, and React Native components with TypeScript support
  • Browser & Node.js: Works in both browser environments and Node.js
  • Batch Processing: Convert entire directories with watch mode support
  • Production Ready: Optimized output with proper error handling and accessibility
  • Zero Configuration: Works out of the box with sensible defaults

Try It Live

Experience SVGFusion instantly in your browser! - Launch Interactive Playground →

Upload your SVG files, experiment with different options, and see the generated React/Vue components in real-time. No installation required!

Examples

CLI Usage

# Convert all SVG files in a directory to React components
npx svgfusion ./icons --output ./components

# Add prefixes, suffixes, and generate index file
npx svgfusion ./icons --prefix Icon --suffix Component --index

# Advanced: Split colors for Custom CSS Class with fixed stroke width
npx svgfusion ./icons --split-colors --fixed-stroke-width --prefix Icon

Installation

# Install globally (recommended for CLI usage)
npm install -g svgfusion

# Or use npx (no installation needed)
npx svgfusion ./icons --output ./components

# Or install locally for programmatic usage
npm install svgfusion
# or
yarn add svgfusion
# or
pnpm add svgfusion

CLI Options

SVGFusion CLI

svgfusion ./icons --output ./components --prefix Icon --suffix Svg

You can add a prefix and/or suffix to the generated component names using the --prefix and --suffix options:

npx svgfusion ./svgs --prefix Icon --suffix Svg

This will generate components like IconStarSvg, IconUserSvg, etc.

Both options sanitize input to remove symbols and spaces. If omitted, no prefix/suffix is added.

Example

npx svgfusion ./svgs --prefix App --suffix Widget
# Output: AppStarWidget, AppUserWidget, ...

For more details, run:

npx svgfusion --help

CLI Usage

# Convert to React components (default)
svgfusion ./icons --output ./components

# Convert to Vue 3 components
svgfusion ./icons --output ./components --framework vue

# Convert to React Native components (uses react-native-svg)
svgfusion ./icons --output ./components --framework react-native

# Single file conversion with TypeScript
svgfusion ./star.svg --output ./components --typescript

# Batch processing with recursive directory scanning
svgfusion ./icons --output ./components --recursive

# Generate index file for tree-shaking
svgfusion ./icons --output ./components --index

# Advanced: Split colors for maximum customization
svgfusion ./icons --output ./components --split-colors

# Advanced: Fixed stroke width with split colors
svgfusion ./icons --output ./components --split-colors --fixed-stroke-width

# Using npx (no global install needed)
npx svgfusion ./icons --output ./components --framework react

Available CLI Options

svgfusion <input> [options]

Arguments:
  <input>                      SVG file or directory to convert

Options:
  -o, --output <dir>           Output directory for generated components (default: "./components")
  -f, --framework <framework>  Target framework: react, vue, or react-native (default: "react")
  --typescript                 Generate TypeScript components (default: true)
  --javascript                 Generate JavaScript components
  --split-colors               Enable color splitting feature
  --fixed-stroke-width         Enable fixed stroke width feature
  --memo                       Wrap component with React.memo (default: true)
  --no-memo                    Disable React.memo wrapping
  --forward-ref                Enable forwardRef support (default: true)
  --no-forward-ref             Disable forwardRef support
  -n, --name <name>            Custom component name
  --optimize                   Enable SVG optimization (default: true)
  --no-optimize                Disable SVG optimization
  --recursive                  Process directories recursively
  --prefix <prefix>            Add prefix to component names
  --suffix <suffix>            Add suffix to component names
  --index                      Generate index.ts file for directory processing
  -h, --help                   Show help

--prefix <prefix> Add prefix to component name (sanitized) --suffix <suffix> Add suffix to component name (sanitized) --split-colors Extract individual color props for each SVG color --fixed-stroke-width Add support for non-scaling stroke width -h, --help Show help


### Using with npx (No Installation Required)

Perfect for trying out SVGFusion or one-time conversions:

```bash
# Convert React components
npx svgfusion ./assets/icons --output ./src/components/icons

# Convert Vue components with TypeScript
npx svgfusion ./assets/icons --output ./src/components --framework vue --typescript

# Convert single file
npx svgfusion ./logo.svg --output ./src/components --framework react

# Batch convert with index generation
npx svgfusion ./assets/icons --output ./src/components --recursive --index

# Convert with custom naming
npx svgfusion ./assets/icons --output ./src/components --prefix Icon --suffix Component --index

# Advanced: Split colors for Custom CSS Class compatibility
npx svgfusion ./assets/icons --output ./src/components --split-colors --prefix Icon

# Advanced: Fixed stroke width with split colors
npx svgfusion ./assets/icons --output ./src/components --split-colors --fixed-stroke-width

Programmatic Usage

Single File Conversion

import { SVGFusion } from 'svgfusion';

const engine = new SVGFusion();
const svgContent = `<svg viewBox="0 0 24 24"><path fill="#FF0000" stroke="#00FF00" d="..."/></svg>`;

const result = await engine.convert(svgContent, {
  framework: 'react', // 'react' | 'vue' | 'react-native'
  transformation: { splitColors: true },
  generator: { componentName: 'MyIcon', typescript: true },
});

console.log(result.code); // The generated component code

API Reference

For the complete API documentation, visit svgfusion.netlify.app.

Examples

Input SVG

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
        fill="currentColor" class="star-fill"/>
</svg>

Generated React Component

import type { SVGProps } from 'react';

interface StarIconProps extends SVGProps<SVGSVGElement> {}

const StarIcon = (props: StarIconProps) => {
  return (
    <svg viewBox="0 0 24 24" {...props}>
      <path
        d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
        fill="currentColor"
        className="star-fill"
      />
    </svg>
  );
};

export { StarIcon };

Generated React Component with Color Splitting

import type { SVGProps } from 'react';

interface StarIconProps extends SVGProps<SVGSVGElement> {
  fillColor?: string;
}

const StarIcon = ({ fillColor = 'currentColor', ...props }: StarIconProps) => {
  return (
    <svg viewBox="0 0 24 24" {...props}>
      <path
        d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
        fill={fillColor}
        className="star-fill"
      />
    </svg>
  );
};

export { StarIcon };

Generated Vue Component

<script setup lang="ts">
import type { SVGAttributes } from 'vue';

interface StarIconProps extends SVGAttributes {}

defineOptions({ inheritAttrs: false });
</script>

<template>
  <svg v-bind="$attrs" viewBox="0 0 24 24">
    <path
      d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
      fill="currentColor"
      class="star-fill"
    />
  </svg>
</template>

Generated Vue Component with Color Splitting

<script setup lang="ts">
import type { SVGAttributes } from 'vue';

interface StarIconProps extends SVGAttributes {
  fillColor?: string;
}

const props = withDefaults(defineProps<StarIconProps>(), {
  fillColor: 'currentColor',
});

defineOptions({ inheritAttrs: false });
</script>

<template>
  <svg v-bind="$attrs" viewBox="0 0 24 24">
    <path
      d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
      :fill="fillColor"
      class="star-fill"
    />
  </svg>
</template>

## Advanced Configuration

### Split Colors with Intelligent Attribute Handling

The `splitColors` option extracts individual color properties from SVG elements and intelligently manages fill/stroke attributes:

```typescript
// Input SVG with mixed attributes
const svgContent = `
  <svg viewBox="0 0 24 24">
    <path fill="#FF0000" d="..." />          <!-- Has fill only -->
    <path stroke="#00FF00" d="..." />        <!-- Has stroke only -->
    <path fill="#0000FF" stroke="#FFFF00" /> <!-- Has both -->
    <path d="..." />                         <!-- Has neither -->
  </svg>
`;

// Convert with split colors
const result = await convertToReact(svgContent, {
  name: 'MultiColorIcon',
  splitColors: true,
  typescript: true,
});

// Generated component behavior:
// - Path with fill only: gets stroke="none" (prevents unwanted stroke)
// - Path with stroke only: gets fill="none" (prevents black fill default)
// - Path with both: keeps both as dynamic props
// - Path with neither: remains unchanged (no unnecessary attributes)

// Generated component props:
// - color, color2, color3 (for extracted colors in order)
// - colorClass, color2Class, color3Class (for CSS classes)
// - Colors are automatically converted to hex format
```

**Color Extraction Rules:**
- Colors are extracted from `fill`, `stroke`, and `stop-color` attributes
- All colors are converted to lowercase hex format (e.g., `#ff0000`)
- Empty or invalid color values are ignored
- Duplicate colors are automatically deduplicated
- Colors are assigned as `color`, `color2`, `color3`, etc. in order

**Intelligent Attribute Handling:**
- Elements with `fill` only → adds `stroke="none"`
- Elements with `stroke` only → adds `fill="none"`
- Elements with both `fill` and `stroke` → keeps both as props
- Elements with neither → no attributes added
- Empty attribute values (`fill=""`) are treated as non-existent

Transformation Options

SVGFusion provides comprehensive transformation capabilities through the transformation options API:

const result = await engine.convert(svgContent, {
  framework: 'react',
  transformation: {
    splitColors: true, // Extract color props
    splitStrokeWidths: true, // Extract stroke width props
    fixedStrokeWidth: true, // Non-scaling stroke support
    normalizeFillStroke: true, // Normalize fill/stroke attributes
    accessibility: true, // Add accessibility features
    optimize: true, // Apply SVG optimizations
    removeComments: true, // Remove XML comments
    removeDuplicates: true, // Remove duplicate elements
    minifyPaths: false, // Minify path data
  },
  generator: { componentName: 'MyIcon', typescript: true },
});

Fixed Stroke Width Support

The fixedStrokeWidth transformation adds support for non-scaling stroke width:

const result = await convertToReact(svgContent, {
  name: 'StrokeIcon',
  isFixedStrokeWidth: true,
});

// Generated component includes:
// - isFixedStrokeWidth prop
// - vector-effect="non-scaling-stroke" when prop is true

Fill/Stroke Normalization

The normalizeFillStroke transformation intelligently handles fill and stroke attributes:

  • Normalizes attribute values across all SVG elements
  • Ensures consistent color and stroke width application
  • Optimizes attribute inheritance and cascading

Custom SVGO Configuration

import { createSvgoConfig, optimizeSvg } from 'svgfusion';

const customConfig = createSvgoConfig({
  removeViewBox: false,
  preserveColors: true,
  preserveClasses: true,
});

const optimizedSvg = optimizeSvg(svgContent, customConfig);

Batch Processing with SVGFusion Engine

import { SVGFusion, readSvgDirectory } from 'svgfusion';
import { writeFileSync } from 'fs';
import path from 'path';

const engine = new SVGFusion();
const svgFiles = await readSvgDirectory('./icons', true); // recursive

for (const svgFile of svgFiles) {
  const svgContent = readFileSync(svgFile, 'utf-8');
  const result = await engine.convert(svgContent, {
    framework: 'react',
    generator: {
      componentName: path.basename(svgFile, '.svg'),
      typescript: true,
    },
    transformation: {
      splitColors: true,
    },
  });

  writeFileSync(`./components/${result.filename}`, result.code);
}

Index File Generation

When using the --index flag or generateIndex: true option, SVGFusion creates an optimized index file for tree-shaking:

Named Exports (Default)

// Auto-generated index file for tree-shaking
// This file exports all components for optimal bundling

export { default as IconStar } from './IconStar';
export { default as IconUser } from './IconUser';
export { default as IconHome } from './IconHome';

// Barrel export for convenience
export { IconStar, IconUser, IconHome };

// TypeScript component types
export type IconComponent = React.ComponentType<React.SVGProps<SVGSVGElement>>;
export type IconComponents = {
  IconStar: IconComponent;
  IconUser: IconComponent;
  IconHome: IconComponent;
};

Default Exports

// Auto-generated index file
// Warning: Default exports are less tree-shakeable

import IconStar from './IconStar';
import IconUser from './IconUser';
import IconHome from './IconHome';

export default {
  IconStar,
  IconUser,
  IconHome,
};

// Individual exports for flexibility
export { default as IconStar } from './IconStar';
export { default as IconUser } from './IconUser';
export { default as IconHome } from './IconHome';

Usage

// Tree-shakeable named imports (recommended)
import { IconStar, IconUser } from './components';

// Default import
import * as Icons from './components';
const { IconStar, IconUser } = Icons;

Complex Filename Support

SVGFusion handles complex filenames from design systems:

# Design system metadata
"Size=xl, Color=Brand, Type=Glass.svg" GlassBrandXl
"User Profile Avatar, Type=Solid.svg" UserProfileAvatarTypeSolid

# Standard patterns
"icon-star.svg" IconStar
"user-profile-avatar.svg" UserProfileAvatar

Styling Support

CSS Classes

<path class="primary-color" />
<circle class="bg-blue-500" /> <!-- Tailwind -->

CSS Variables

<path fill="var(--primary-color)" />
<circle fill="currentColor" />

Gradients & Patterns

<defs>
  <linearGradient id="gradient">
    <stop offset="0%" style="stop-color:#ff6b6b" />
    <stop offset="100%" style="stop-color:#4ecdc4" />
  </linearGradient>
</defs>
<path fill="url(#gradient)" />

Testing

npm test          # Run tests
npm run test:coverage # Run with coverage

Development

npm run dev       # Watch mode
npm run build     # Build for production
npm run lint      # Lint code
npm run format    # Format code

Browser Usage (New!)

SVGFusion now supports browser environments! Convert SVG strings to component code without writing files.

Try the Interactive Playground: svgfusion.netlify.app/playground

import { convertToReact, convertToVue } from 'svgfusion-dom';

const svgContent = `<svg viewBox="0 0 24 24"><path fill="#3B82F6" d="..."/></svg>`;

// Convert to React component string
const reactResult = await convertToReact(svgContent, {
  componentName: 'MyIcon',
  typescript: true,
  splitColors: true,
});

console.log(reactResult.code); // Generated React component code

// Convert to Vue component string
const vueResult = await convertToVue(svgContent, {
  componentName: 'MyIcon',
  typescript: true,
  sfc: true,
});

console.log(vueResult.code); // Generated Vue component code

Browser Features:

  • All conversion features (color splitting, stroke fixing, etc.)
  • React, Vue, and React Native component generation
  • TypeScript support
  • Batch conversion
  • Color extraction and validation
  • Index file generation
  • Works in all modern browsers
  • Interactive Playground with Monaco Editor

Browser API Documentation

Node API Documentation

License

MIT © SVGFusion Contributors

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details.