@kythera/kui-icons
v1.0.5
Published
Icons for Kythera UI
Downloads
3
Readme
kui icons
kui icons is a library used throughout KOS, and possibly more, to allow for the reusability of icons across projects. It is meant to function as a quick and easy way to generate React Components from .svg
files.
Quick Start
This library utilizes SVGR (https://react-svgr.com/) along with React to automatically generate React Components from svgs.
Before continuing, run npm install
in the terminal to make sure the proper dependencies and libraries are installed.
If you are just generating components then put all of the svgs that you would like to use into the assets
folder. Then, run npm run svgr
in the terminal. This will generate a .tsx
file that contains a React component for each svg . It also generates src/icons/index.tsx
which aggregates each generated component for ease of use.
If an svg is removed from, added to, or updated in the assets
folder, it is usually a good idea to completely delete the src/icons
folder before running the SVGR command to mitigate errors.
SVGR
As mentioned above, SVGR is a library used to generate React Components from .svg
files. This is the main dependency of this repo so understanding how it works and how we are using it is important if you'd like to make modifications. Official documention for this library can be found at https://react-svgr.com/.
Customization
There are 3 main ways to modify the creation of svg components generated by SVGR: the Command Line Interface (CLI), the Configurtion File, and Templates. The specific details of how they are used in this repo are discussed below.
CLI
Within package.json
the svgr command, npm run svgr
, can be modified (options and arguments can be found at https://react-svgr.com/). For our library, most of the arguments utilize separate files instead of writing out every option in the command line.
The very end of this command specifies the directory to pull from and the directory to put the generated files in using the format outputDir -- inputDir
. For our use case, the input directory is the assets
folder and the output directory is src/icons
.
Configuration File
A JSON formatted configuration file can be used by adding --config-file path/to/file
to the svgr command. There are many things that can be added to this file (found at https://react-svgr.com/docs/options/), however, the most important ones for our purposes are expandedProps
replaceAttrValues
, and svgProps
. Their specific uses can be found in the .svgrrc
config file.
expandedProps
: Determines the order in which the component's custom properties are added. "start"
will add the props as the first line in the component and "end"
will add the props last.
replaceAttrValues
: Replaces all occurrences of a value within the svg file in the assets folder with the provided values. For example, "#fff": "#000"
will replace every occurrence of #fff
in the svg with #000
.
svgProps
: Default values to be applied to properties of the generated React component. For example, "transform": "{rotate(90)}"
will set each component's transform property to {rotate(90)}
.
Component Template
The next argument for the svgr command is --template ./src/iconTemplate.js
. iconTemplate.js
provides a template for the resulting react components. The default template can be found at https://react-svgr.com/docs/custom-templates/.
Our template makes use of an IconProps
interface which is defined in src/icons/index.tsx
. This allows for the use of our own custom properties in the generated React Component. It's important to note that these IconProps
cannot be modified by the svgProps
argument in .svgrrc
.
The template also exports the generated components as named components based on the name of the svg in the assets
folder.
Another custom-made variable found in our component template is the rotation order. An array is defined called rotationOrder
that determines which rotations match up with which angles. The default order is 'up', 'right', 'down', 'left'
which matches up with a 0, 90, 180, and 270 degree rotation respectively. This order can be modified to better match whatever svg you have.
For example, say you have an Arrow svg that points right without any rotation and has been used across multiple designs so changing the svg itself could prove to be a time-consuming process. In the template, you could set up a statement that changes its rotation order to be ['right', 'down', 'left', 'up']
. Doing this will make it so selecting 'right'
will not rotate at all, 'down'
will rotate by 90 degrees, and so on. This order doesn't necessarily have to be clockwise either. You could set up the component with an order of ['down', 'right', 'left', 'up']
if it suits your use case.
How this order is applied to each component is defined in the svgProps: transform
argument in the .svgrrc file discussed previously.
Index Template
The third argument for the svgr command is --index-template ./src/indexTemplate.js
. indexTemplate.js
provides a template for the resulting src/icons/index.tsx
file. Ours is set up so that each svg React Component is accumulated under an Icon
component.
This Icon
has an iconTitle
property which determines which generated svg component to use. These iconTitles are automatically generated strings (The iconTitle
of TestSvg.svg
would be test svg
) under the IconTitles
interface also found in src/icons/index.tsx
.
The Icon
component also has a size
and rotation
property. size
is an enum that can be found in src/ts/type.ts
and defaults to 'm'
. The rotation
property does not have a default and should always be explicitly set. How the size
property affects the displayed icon can be found near the top of the Icon
component's definition. How rotation
affects the Icon
component can be found in .svgrrc
under the svgProps: transform
argument.
There is one more property which is fill
. This is a string that defines the color of the svg and has no explicit default. Any color that CSS accepts can also be used for this property (rgb(), hsl(), hex, etc.).
Storybook
Storybook is a way to view and test the components within this library. To use storybook, run npm run storybook
in the terminal. This will bring up a webpage in which each icon can be viewed and modified. You can change the icon through the iconTitle
dropdown, change the fill
using hex, change the rotation
, and change the size
.
Each section is a story and these can be modified in src/stories
. To find out more about storybook, please refer to their official documentation at https://storybook.js.org/docs/react/get-started/why-storybook.
Storybook stories are not automatically generated. So, if an svg is added from, removed from, or the name is changed in the assets
folder, a story may need to be added, removed, or updated to properly view it.
Example
Say you have a file named Arrow.svg
which looks like: :arrow_up:. After putting this file into the assets
folder and running npm run svgr
in the terminal, two files will be generated: src/icons/index.tsx
and src/icons/Arrow.tsx
. Arrow.tsx
will contain an exported React Component with the name Arrow
as well values substituted and set according to what is found in .svgrrc
and src/iconTemplate.js
.
src/icons/index.tsx
will have a definition for the IconProps
interface which defines the types for iconTitle
, size
and rotation
. iconTitle
s have the IconTitles
type which is another interface defined in index.tsx
. IconTitles
are generated according to the name of the svg files in assets
. For this example, the only title would be 'arrow'
.
Below IconTitles
is the definition for the Icon
React Component. The main logic of this component is the long chain of if
statements. This will select one of the previously generated svg React Components based on the inputted iconTitle
.
So, let's say you have just generated these components and now want to use them inside a file named index.ts
. Instead of importing each component under src/icons
, we only need to import Icon
from src/icons
.
import { Icon } from 'src/icons';
Using the Arrow
icon in a project that imports this repo would look something like this:
<Icon iconTitle="arrow" fill="#fff" size="m" rotation="right">
And then on the screen, you would see something like this: :arrow_right: