npm package: @grund/ui
Description: # Atomic structure
Latest version: 0.0.85

# Grund UI

# Atomic structure

The Grund components are structured somewhat according to the Atomic Design principles. Currently, however, we only make use of "Atoms" and "Molecules" and "Organisms". This is because "Templates" and "Pages" are very application specific. Below are a quick summary of how we view the different parts of the system and where each component belongs.

## Atoms

-   Rule of thumb: "Doesn't do much of it's own, but is the building parts of pretty much everything"
-   Can include components that doesn't have any dependencies, such as Icon, Overlay, Image, etc. But they could also consist of other components such as Input (native input + icons), Button (native button + icon), etc.

## Molecules

-   Rule of thumb: Molecules are relatively simple groups of UI elements functioning together as a unit.
-   In general, by combining several atoms they suddenly have gained a purpose.
-   This adheres to the "single responsibility principle" - do one thing and do it well.
-   Examples:
    -   InputField: Consists of an Input, an InputLabel and an InputErrorMessage

## Organisms

-   Rule of thumb: Organisms are relatively complex UI components composed of groups of molecules and/or atoms and/or other organisms.
-   Examples:
    -   Forms: consists of multiple FormFields and a Button

# Previous versions

The first version of the @grund/ui package was to use the theme in the maximum way. Everything from colors to fonts to components was defined and overridable in the theme object. For the components it allowed us to define sub components and a dynamic customization of props and how the components behave and looks depending on the props.

However, there are a few cons with this approach:

1. The theme file gets quite complex. This is something that creates a very powerful solution to quickly create ui sets. However, it quickly gets quite complex which makes it unfit for larger projects.
2. Due to the fact that we inject the sub components into the components from the theme, sometimes there is a rendering issue. The best example of this is the Input components that gets unfocused when updated. But also, it is quite bad practise not to make the sub components injected in this way. There might be reference issues etc. A better way is probably to use the defaultProps to change the sub components. Worth mentioning is that defaultProps are also a bad practise due to performance reasons - but it is probably the best way currently.

To conclude, the path forward is to minimize the theme object into more static variables such as fonts, colors, etc. If one wants to customize the components more than this, one have to wrap the grund components into custom components. The grund components will still be built in such a way that every part of each component is overridable.

# Thoughts

Having tried the atomic approach for a library such as this, I have come to realise that it is probably not the most suitable solution for Grund. I think it is much better suited for an actual application, but not for a library.

I think that in order to get it to work properly in an application, everybody in the team needs to be absolutely sure of the rules that are setup for their instance of the atomic approach. Otherwise one will spend a lot of time just figuring out where a specific component should reside. And one also might get confused by just looking at the folder structure. The atomic approach might be best suited when having 100+ components in a project.

There are also the matter of what I have seen some people referring as "domain components". These are components that are specific to a certain context. An example could be a Header with a specific state for a certain page. The word `domain` is a bit vague, though. It could refer to being a sort of page components, but it could also mean being a sort of stateful component.

Another connected issue is the one with connecting stores to components. We could also ish view it as the same issue as with container/presentational components. Sometimes we want to resuse a component that always make use of a certain store. But since the components in general should be stateless as much as humanly possible, it might not be the best of places to put these store-dependent components in the `components` folder. In these cases one might want to put them in another folder? Possibly this folder could be the same as the `domain` one? We'll need to think more about this to come up with a sustainable solution.

# Props

## Styling props

When using a component from a library - e.g. Grund - it most probably exists of several sub components. Not rarely you find youself wanting to style these parts individually.

What I've come to realize is that you need to put different stylings into certain categories. E.g. `position`, `layout` and `text`. The `position` is how it is positioned relative to other elements (e.g. `margin`). The `layout` is how it handles internal components (e.g. `justify-content`) and and example of `text` would be `font-size`.

Their individual styling purposes are very different which means that you, in general, have to separate them in your logic as well. Since a component only have one `style` prop, this is not enough to cover everything in order to completely style a component. To solve this you have two alternativs:

-   Add individual style props to the component - e.g. Use the `style` prop for `position` styling and then add extra props such as `fontSize` to handle the text styling. Most often this is enought.
-   Add category style props - e.g. Use the `style` prop as above, but then add `textStyle` or similar to style you text sub component. This approach could be a little counter intuitive since, if you come from the css world, you are used to use class names. But using `styled-components` or `emotion` we don't have to think about this anymore - at least not in 95% of the time.