Create a react app using Vite - Part 2
Tags: react, typescript, vite, javascript
Published: 2023-08-15 04:57:15

## Styling

I'm going with [TailwindCSS](https://tailwindcss.com/) as my default styling utility library. Skip this if you have other preferences.

#### Tailwindcss

- Install the TailwindCSS and initialize it using the below commands.

```bash
  pnpm add -D tailwindcss postcss autoprefixer
  npx tailwindcss init
  touch postcss.config.js
```

- The init command will create a `tailwind.config.js` file in the root directory where we can configure the tailwind library. Update the config file content property to process the HTML, and TS files in src and public directory as follows.

```js
export default {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: { extend: {} },
  plugins: [],
}
```

- Now we should let the postcss preprocessor know that we are using tailwindcss in our project. To do that, open the postcss.config.js file and add the 'tailwindcss' option to the plugins list.

```js
export default {
  plugins: { tailwindcss: {}, autoprefixer: {} },
}
```

- Open `/src/index.css` file and update it with the following content

```css
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
```

- Open the `src/App.tsx` file and update the `h1` tag as follows and check whether the tailwind class is applied successfully.

```html
<h1 className="text-green-500">Vite + React</h1>
```

## Rendering icons

SVGs are the best image format for rendering icons for the following reasons.

- They are small in size
- The same icon can be used in different places in different sizes without losing the quality, that's why it's called Scalable Vector Graphics.
- A monochromatic icon can be rendered in different colors just by applying CSS

To render the icons inline I'm using this [SVGR plugin](https://react-svgr.com/) to transform the SVGs to react components and then import it wherever necessary just like importing a normal react component.

- Install the necessary packages

```bash
 pnpm add -D @svgr/core @svgr/plugin-svgo vite-plugin-svgr
```

- Update the Vite config to automatically convert the SVGs into react components.

```js
export default defineConfig({
  ...,
  plugins: [
    ...,
    svgr({
      svgrOptions: {
        plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx'],
        svgoConfig: {
          plugins: ['preset-default'],
        },
      },
     }),
  ]
});
```

- Update the package.json file

```json
  ...,
  "scripts": {
    ...,
    "format:svg": "prettier --write '**/*.svg' --parser 'html'",
    "format": "prettier --write . && pnpm format:svg",
  },
  "lint-staged": {
    "**/*.{js,ts,tsx}": [
      "eslint --fix"
    ],
    "**/*.svg": "prettier --write --ignore-unknown --parser 'html'",
    "**/*": "prettier --write --ignore-unknown"
  },
  ...
```

- Open `src/vite-env.d.ts` and add the following entry to avoid the ReactComponent SVG error while importing.

```
/// <reference types="vite-plugin-svgr/client" />
```

- Let's make use of the already available `react.svg` and see how we can import it as an inline SVG. Update the `/src/app.tsx` as follows,

```js
import { ReactComponent as ReactIcon } from 'src/assets/react.svg'

export const App = () => {
  return (
    <div className="font-semibold text-lg text-green-500">
      <ReactIcon width="24px" height="24px" className="text-blue-500" />
      Rendered from react app
    </div>
  )
}
```

### Things to remember

We need to make sure we import SVGs the right way so they are highly customizable and scalable. Rendering the SVGs as inline, allows us to customize the SVG properties such as dimensions, fill color, and stroke color through props.

For the library to properly parse the SVG and allow us to customize it inside our components ensure the following.

1. The SVG you are adding has the fill property in the SVG as 'currentcolor' so it's easy to customize this color based on the prop. Please see reference SVG `src/assets/react.svg`.
2. The SVG shouldn't have width and height set so we can set them inside our components when used. (They will be overwritten anyways but it's better to avoid width and height in the SVG being added)
3. Try to open the SVG in the browser and start deleting the unwanted elements present in the SVG by inspecting the elements in the developer console and making sure only valid tags are present and checking for any visual changes. If there are no visual changes we can delete those elements from the SVG.
4. Set the `path` element's `fill` property to `inherit` so that the color will be inherited from the SVG element itself.
5. Check the SVG size after making these changes.

- If the size of SVG is < 1kb then it's eligible to render as an inline icon. Put the SVG in the `src/assets/icons` path and render it inline using the <SvgIcon> component.
- If the size > 1kb then it will increase the bundle size and affect the performance. Put the SVG in the `src/assets/images` folder and render it using `<img>` tag src. This way it will not hinder the page load.
- This 1kb is an arbitrary value, but it is advised to have a threshold beyond which the icons should be rendered using image tags only.

PS: You can also create a generic UI component wrapper that accepts the SVG as input and render it with some default sizes and config.

## Next part

In the next part of this series, we will see how to add unit testing support to our app using JEST.