Skip to content

Instantly share code, notes, and snippets.

@ryanoglesby08
Last active February 16, 2022 20:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanoglesby08/603966db3884178e4bade6b5d878c437 to your computer and use it in GitHub Desktop.
Save ryanoglesby08/603966db3884178e4bade6b5d878c437 to your computer and use it in GitHub Desktop.
Generate React icon components from SVG files using SVGR
import { transform } from '@svgr/core'
import fs from 'fs'
import template from "./template"
const ICON_DEFAULT_COLOR = 'black'
const fileName = "svgs/myIcon.svg"
const svgData = fs.readFileSync(fileName)
const componentData = transform.sync(
svgData,
{
icon: true,
plugins: ['@svgr/plugin-jsx', '@svgr/plugin-prettier'],
prettier: true,
prettierConfig: {
parser: 'typescript',
semi: false,
useTabs: false,
},
svgProps: {
// Aids in unit testing by consumers, such as asserting an icon is on the page or not
'data-testid': `svg_${fileName}`,
},
// Removing fill or stroke values set to our default color allow any color to be passed in
replaceAttrValues: {
[ICON_DEFAULT_COLOR]: 'inherit',
},
template: template,
typescript: true,
},
{
componentName: fileName,
}
)
fs.writeFileSync(
`src/icons/${fileName}.tsx`,
componentData,
)
const GENERATED_MESSAGE = `/**
* @generated
* This file was automatically generated and should not be edited.
*/`
// See docs for SVGR custom templates: https://react-svgr.com/docs/custom-templates/
const iconTemplate = ({ template }, opts, { componentName, jsx }) => {
const plugins = ['jsx', 'typescript']
const typeScriptTpl = template.smart({ plugins })
return typeScriptTpl.ast`
${GENERATED_MESSAGE}
import React from 'react'
import { system, Config } from 'styled-system'
import { Box, BoxProps, useTheme } from 'design-system'
type Props = BoxProps & React.SVGProps<SVGSVGElement>
const config: Config = {
fill: {
property: 'fill',
scale: 'colors',
},
stroke: {
property: 'stroke',
scale: 'colors',
},
}
const styleFn = system(config)
const Svg = (props: React.SVGProps<SVGSVGElement>) => (${jsx})
const ${componentName} = (props: Props) => {
const theme = useTheme()
const styledProps = styleFn({ ...props, theme })
return <Box as={Svg} {...props} {...styledProps} />
}
export default ${componentName}
`
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment