Skip to content
This repository has been archived by the owner on Oct 5, 2022. It is now read-only.

Add script to automate and standardise SVG component generation #15

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

AlanSl
Copy link
Member

@AlanSl AlanSl commented Jun 19, 2020

  • Add script to generate SVG components
  • Update index.ts lists of svg components if script has changed anything
  • Check generated components pass lint, typechecks, and work in the app
  • Thorough check for any regressions on individual icons in web and native
  • Check if nodejs utility scripts like this should be in ts run through ts-node, rather than js
  • Update documentation

We established that handling SVGs is one area in which we could improve developer experience and efficiency by creating a standardised, streamlined, but non-project-specific solution for a common pain point.

This PR focuses on static SVG images, like icons. These must:

  • be converted to components written differently for web (using regular <svg> elements) and native (using components from react-native-svg to use native OS elements)
  • have various attributes and elements that aren't supported in native removed or re-written
  • be modified to allow props to be passed in
  • have typing applied, including an index.d.ts file.

Previous approach

Currently, any time an SVG icon or image is added or updated, the workflow appears to be the following (this is undocumented, I'm inferring this from the state of the files):

  1. Use either the SVGR web app or npx @svgr/cli <options> with typescript options chosen to generate the index.web.ts file. At least some of the icon components were clearly generated by SVGR, but others look like they might have been manually created, copying the SVGR approach.
  2. Re-do 1. with native options applied, to generate the index.native.ts file.
  3. Manually remove various SVG attributes that are allowed by SVGR but aren't compatible with react-native-svg's typescript typing, such as classnames and filters
  4. Manually edit in icon typing imported from src/components/atoms/icons/common.ts
  5. Put the files in a new directory in src/components/atoms/icons/
  6. Copy and paste an index.d.ts from another icon
  7. Manually update src/components/atoms/icons/index.ts (SVGR can generate indexes, but only in js, not in ts)
  8. Store the original SVG file in src/assets/icons, and try to avoid these files getting out of sync with the components.

It works, but it's cumbersome and allows inconsistency to creep in: even here there are already inconsistencies in naming (e.g. some match the original SVG names while some have different folder names) and in how different icons have been converted (e.g. which attributes are stripped and which elements modified). There are also some leftover SVG assets that appear to be unused and some SVG components without source files.

It would also be a pain to make general changes to how icons are used (for example applying currentColor or em sizing). This would probably need to be done by hand for every asset.

New approach

This PR adds a script that handles all of this.

To add one or more new SVG icons or images:

  1. Add the .svg file(s) to src/assets/icons or src/assets/images
  2. Run npm run convert-svg. This generates all the needed files, with typing, and updates the appropriate index.ts

To update existing SVG icons or images:

  1. Replace .svg file(s) in src/assets/icons or src/assets/images
  2. If necessary, edit the template in scripts/convert-svg.js (e.g. to add a prop or attribute conversion)
  3. Run npm run convert-svg:update. This generates files and updates indexes as above, overwriting rather than ignoring those that were already generated

The script also adds a comment to each generated component, saying that it was generated by this script and pointing to the asset file it was generated from, so it's easy for anyone picking up a project and looking at a particular icon or image to see what is going on. For example:

/* Generated by scripts/convert-svg from src/assets/icons/bot.svg */

...and the console output gives a summary of what has been done:

image

I think this is a good example of how an "accelerator" project can streamline a common, normally-troublesome workflow.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant