This post is focused on React Native, but should be applicable to pretty much anything with little adjustment.
If you have your UI designed in Figma (or any other vector graphics tool), you likely want to export all the assets for your app from there. So here's what you do to get SVGs out ASAP.
In this particular example I want to export all my icons as SVGs
Export SVGs from Figma
- Make sure your shapes do not use stroke. To get rid of it:
- try using “outline stroke” and then merging with original shape.
- Make sure all shapes are flat (flatten all groups)
- Give all your shapes meaningful and unique names
- Make all shapes black
#000
- Export SVGs using “Advanced SVG Export” plugin:
- Select all shapes you want to export and then open "Advanced SVG Export" plugin
- Make sure you selected “Prefer viewBox to width/height” in plugin settings
- Click on "export layers"
- Extract downloaded archive into
assets/icons
directory of your project
Generate React Component For Each SVG
I use TypeScript, so following generates app/components/icons/index.tsx
file with component per each SVG.
- Install hygen - follow docs
- Run
hygen generator new icons
- Change
_templates/icons/new/hello.ejs.t
to:
---
to: app/components/icons/index.tsx
---
/**********************************************
* THIS IS AUTOGENERATED CODE *
* GENERATOR: hygen icons new *
**********************************************/
<%
const dir = './assets/icons';
const fs = h.require('fs');
const files = fs.readdirSync(dir)
%>
<%-
files.map(v => `import ${v.split('.')[0]}SVG from "../../../assets/icons/${v}"`).join('\n')
%>
import {CreateIcon} from './createIcon';
<%-
files.map(v => `export const ${v.split('.')[0]}Icon = CreateIcon(${v.split('.')[0]}SVG)`).join('\n')
%>
It's nice to have CreateIcon
function in separate file, so you can edit it without touching template. Here's what createIcon.tsx
may look like:
import React from 'react';
import {View} from 'react-native';
import {SvgProps} from 'react-native-svg';
export interface IconProps {
containerStyle?: object;
color: string;
size: number;
}
export function CreateIcon(Icon: React.FC<SvgProps>) {
return ({color, size, containerStyle}: IconProps) => {
return (
<View
style={[
{
width: size,
height: size,
justifyContent: 'center',
alignItems: 'center',
},
containerStyle,
]}>
<Icon fill={color} width={size} height={size} />
</View>
);
};
}
- Add
"g:icons": "HYGEN_OVERWRITE=1 hygen icons new"
, to"scripts"
inpackage.json
With above setup you extract all your svgs into assets/icons
, then run yarn g:icons
(or npm run g:icons
) which will generate app/components/icons/index.tsx
with one component per each SVG file. Yay!
RN Setup
- Install following npm packages:
react-native-svg
,@svgr/core
,@svgr/plugin-svgo
,react-native-svg-transformer
,svgo
- Create
.svgrrc
file in the project root directory with following content:
{
"replaceAttrValues": {
"#000": "{props.color}"
}
}
- Adjust
metro.config.js
as following:
const {getDefaultConfig} = require('metro-config');
module.exports = (async () => {
const {
resolver: {sourceExts, assetExts},
} = await getDefaultConfig();
return {
transformer: {
babelTransformerPath: require.resolve('react-native-svg-transformer'),
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: false,
},
}),
},
resolver: {
assetExts: assetExts.filter((ext) => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],
},
};
})();
-
If you use Typescript, create/edit
@types/declarations.d.ts
:
declare module '*.svg' { import {SvgProps} from 'react-native-svg'; const content: React.FC<SvgProps>; export default content; }
That's It!
Hope that was helpful!
Any questions / suggestions are welcome :)
Top comments (0)