Super flexible container
Tags: tutorial, react, javascript, emotion
Published: 2022-06-24 17:25:27

#SitoContainer
Super flexible container, very similar to @mui's Box
## First!
### 1 - Create a new react app
If you are using yarn (I recommended it)  
`yarn create react-app <container-name>`  
or if you like to use npm  
`npx create-react-app <container-name>`  
 if everything goes fine you will have a page like this one at localhost:3000 (if port 3000 is not busy):

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q6hntn4nx0su99s3nggo.jpg)
## Next!
### 2 - Install [@emotion](https://www.npmjs.com/package/@emotion/react)  
Emotion is a library designed for writing css styles with JavaScript. It provides powerful and predictable style composition in addition to a great developer experience with features such as source maps, labels, and testing utilities. Both string and object styles are supported.

dependencies:  
`yarn add @emotion/css @emotion/react @emotion/styled`  
or with npm:  
`npm install @emotion/css @emotion/react @emotion/styled`    

## **Time to CODE!**
### 3 - Create your container component
You can remove other files in `/src` folder, all but index.js and App.js  
Go to your `App.js` file at `/src` directory, in this file you will find this one:  
```
import logo from "./logo.svg";
import "./App.css";

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
```
We will remove all of these and will create your new component, in this case your container component, in this tutorial will be SitoContainer:  
```
function SitoContainer() {
  return <div></div>;
}

export default SitoContainer;
```
Well now our container should render its children, so let's import PropTypes from [prop-types](https://www.npmjs.com/package/prop-types)  
```
import PropTypes from "prop-types";

function SitoContainer(props) {
  
  const { children } = props;

  return <div>{children}</div>;
}

SitoContainer.defaultProps = {
  children: <></>,
};

SitoContainer.propTypes = {
  children: PropTypes.node,
};

export default SitoContainer;
```
Ok, now we should allow our future users to customize our component with their CSS rules, so let's add other props, like:

- sx (styled-components like [MUI](https://mui.com/system/basics/#the-sx-prop))
- style (inline-style)
- className (css classname)

```
import PropTypes from "prop-types";

import { css } from "@emotion/css";

function SitoContainer(props) {
  const { children, className, sx, style } = props;

  // IMPORTANT!!!
  // this is for turn your styled-components rules as dynamic 
  // @emotion/css class
  const newSx = css({sx});

  return (
    <div className={`${className} ${newSx}`} style={style}>
      {children}
    </div>
  );
}

SitoContainer.defaultProps = {
  className: "",
  sx: {},
  style: {},
  children: <></>,
};

SitoContainer.propTypes = {
  children: PropTypes.node,
  className: PropTypes.string,
  sx: PropTypes.oneOfType([
    PropTypes.arrayOf(
      PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])
    ),
    PropTypes.func,
    PropTypes.object,
  ]),
  style: PropTypes.oneOfType([
    PropTypes.arrayOf(
      PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])
    ),
    PropTypes.func,
    PropTypes.object,
  ]),
};

export default SitoContainer;
```
_Note that PropTypes of style and sx props are really tedious, this is because these props can be almost anything_    
Well our container is almost done, we can add other props like:  
- id (html identification)
- display (flex, block, etc.)  
In my case I added:
- background (string)
- fullWidth (boolean)
- flexDirection (row, column, etc)  

You can check in my [github repo](https://github.com/SitoNumbis/sito-container)

## Finally!
### 4 - Bundle your container and publish it
Create a file with the name `.babelrc` containing:
```
{
  "presets": [
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ]
  ]
}
```
This is for support for the experimental syntax `jsx`, if you want to look futher, [read here](https://babeljs.io/docs/en/babel-preset-react)  
Install two dev dependencies:  
`yarn add @babel/cli @babel/preset-react`  
or with npm:  
`npm install @babel/cli @babel/preset-react`  
Add this script to your `package.json`:  
`"publish:npm": "babel src/ -d dist --copy-files"`  
and this line, also to your `package.json`:  
`"main":"dist/App.js"`  
This last part is for tell to npm, or yarn, where to look your modules when a user install them
Use for local test `npm install my-package` where `my-package` is the root folder of your package, in this case our container  
If everything goes fine, on the command line, navigate to the root directory of your package and run to publish your package:  
`npm publish`  
_for more instructions [read here](https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages)_  

If you want to try my container, you can check here [sito-container](https://www.npmjs.com/package/sito-container)