DEV Community

Cover image for A tool to convert SVG into React 17 / TypeScript components + Ion Icons
Dorival Pedroso
Dorival Pedroso

Posted on

A tool to convert SVG into React 17 / TypeScript components + Ion Icons

Since this interesting post Making SVG icon libraries for React app, I've been converting SVG files into React components... manually. Now I've created a tool to automate the process, and it may be useful to you too.

Others have been also using SVG-React components, in particular for Icons:

The tool is here: https://github.com/cpmech/svg-to-react, and it is supposed to work for not only Icons.

Some key aspects that I've considered are:

  • Generate React 17 components; those without "import React..."
  • Generate TypeScript components that I can copy-n-paste into my projects
  • Optimize and (try to) fix the path colors.
  • Wrap the SVG into a CSS flex composition to make it easy to adjust the SVG size.

To accomplish these goals, I use:

  • svgo to optimize the SVG, a lot.
  • svgson to fix fill="currentColor" (optionally)

Usage:

✔ What is the "input" directory? · /tmp/svg-to-react/assets
✔ What is the "output" directory? · /tmp/svg-to-react/svgs
✔ What is the prefix for the components? · Svg
✔ What is the base url for XCollection.tsx? · 
✔ Add fill="currentColor" if missing? (Y/n) · true
✔ Delete existent output directory? ️⚠️  (y/N) · true
🚀 Processing SVG files
... processing SvgLogoGithub
... processing SvgLogoWhatsapp
... processing SvgSync
😀 DONE
Enter fullscreen mode Exit fullscreen mode

The resulting code makes it easy to rescale and center the SVG file. The tool also generates an XCollection.tsx component to visualize all generated SVG.

For example, I've used to create React Icons (again ;-): https://github.com/cpmech/iricons

The generated React component looks like this:

export interface SvgSyncProps {
  size?: string; // size of square container
  style?: React.CSSProperties; // not for height or width
}

export const SvgSync: React.FC<SvgSyncProps> = ({ size = '24px', style }) => {
  return (
    <div
      style={{
        display: 'inline-flex',
        alignItems: 'center',
        justifyContent: 'center',
        ...style,
        height: size,
        width: size,
      }}
    >
      <div
        style={{
          position: 'relative',
          height: 0,
          width: '100%',
          padding: 0,
          paddingBottom: '100%',
        }}
      >
        <svg
          style={{
            position: 'absolute',
            height: '100%',
            width: '100%',
            left: 0,
            top: 0,
          }}
          viewBox="0 0 512 512"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path d="..." fill="currentColor"/>
        </svg>
      </div>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

And can be directly imported into a React project.

I hope it helps 😀

Top comments (0)