DEV Community

loading...

Discussion on: A Better Way to Structure React Projects

Collapse
krisguzman_dev profile image
Kris Guzman Author

Hi, thanks for the thoughtful reply. I’m not quite sure I understand the implications you outlined. I think you made quite a few assumptions about how styling would work with an atomic design component folder structure.

There is no need to have a big organisms.scss file, each component can have its own styling. I don’t personally use scss, I use styled components which works very well with this structure. But the same can be achieved with scss without a problem.

Your point about there being no purpose in having an atom called “button” isn’t really connected to atomic design. That’s a project specific decision. There’s nothing wrong with making a second atom called SubmitButton if you need it, and keeping your buttons in a folder called atoms/buttons if you find that you have several different kinds of buttons.

It sounds like you made the assumption that I’m encouraging a super rigid structure, but my only point was that this is a “better” way to structure a React project in comparison to container / component structures. The “best” way is to utilize various patterns, such as atomic design, and incorporate the best parts into your own workflow.

This folder structure is a good starting point, but of course it can be extended / modified to suite the needs of a specific project. Each of my projects utilize a variation of this pattern, but by no means are they identical.

Thanks for reading!

Collapse
gruckion profile image
Stephen Rayner

Use it in production in a large application. Atomic design sounds fancy but it’s not a good solution.

Doesn’t simply the process and contains much boilerplate.

Collapse
joelbonetr profile image
JoelBonetR • Edited

I'll add an example using a basic common CSS (or Sass) methodology:

buttons.scss

@use './variables.scss';

.btn { 
  border-radius: 4px;
  border: none;
  &.btn-primary {
    background: $primary-background;
    box-shadow: $top-layer-shadow;
    font-family: $bolder-typo;
  }
  &.btn-default {
    background: $default-background;
    box-shadow: $regular-layer-shadow;
    font-family: $regular-typo;
  }
}

home.scss

 @use '../buttons.scss';
  // specific context view (page) styles (usually non reusable)

on HTML:

  <link rel="../scss/home.scss" ... />
  <header>
      <!-- some nice catching banner -->
      <button class="btn btn-primary"> Get yours at 50% discount!   </button>
  </header>
  <!-- informative content  -->
  <footer>
      <!-- some contact / leads secondary/basic form -->
      <button class="btn btn-default"> Submit 
    </footer>

As you can see it's very straightforward and very semantically strict which makes the things easier to devs.
Also on terms of performance you add what you need excepting few vars that hopelessly will come across with variables.scss (which also could be named customize.scss or similar if you build a framework).

Let's try to use atomic design to reach the same result:

../atoms/shadows.scss

 .top-layer-shadow {
    box-shadow: 0 0 5px rgba(20, 20, 20, .8);
 }
 .regular-layer-shadow {
    box-shadow: 0 0 4px rgba(66, 66, 66, .55);
 }

../atoms/backgrounds.scss

.default-background {
  background: #fefefe;    
}
.primary-background {
  background: #fec940;
}

../atoms/fonts.scss

.regular-typo {
  font-family: 'Ubuntu-regular';
}
.bolder-typo{
  font-family: 'Ubuntu-bold';
}

../atoms/buttons.scss

.btn { 
  border-radius: 4px;
  border: none;
}

html:

   <link rel="../scss/atoms/shadows.scss" ... />
   <link rel="../scss/atoms/backgrounds.scss" ... />
   <link rel="../scss/atoms/fonts.scss" ... />
   <link rel="../scss/atoms/buttons.scss" ... />
    <header>
      <!-- some nice catching banner -->
      <button class="btn primary-background bolder-typo top-layer-shadow "> Get yours at 50% discount!   </button>
    </header>
    <!-- informative content  -->
    <footer>
      <!-- some contact / leads secondary/basic form -->
      <button class="btn default-background regular-typo regular-layer-shadow"> Submit   </button>
    </footer>

you can, of course, import the things on the scss like that too as alternative:
home.scss

@use './scss/atoms/shadows.scss'; 
@use '../scss/atoms/backgrounds.scss';
@use '../scss/atoms/fonts.scss';
@use '../scss/atoms/buttons.scss';

and load the home.scss on the html as single item, but this means you'll load across tones of super-componentized style sheets.

I'm not assuming a specific way to organize the code, i'm just translating the atomic design concept into the code.
I've a draft post about CSS methodologies, comparing them all and taking own conclusions which I'll finish to write when I can (I lack enough time to do it at this point, give me some weeks haha) it's not an easy task... on a little project, maybe. On a big project where you have a total line count over 10.000 lines of scss code or more it's a mess not using the right methodologies.

I've tried to translate atomic into scss properly before, the first time it was a mess for being more strict than needed on dev time, then I need to refactor things up and get a more usable code on it (i'm talking about a real project which is into production with 20K+ customers on it and which implies connection between many company Apps as a wrapper to add a service as value to our customers).

In fact I wrote a complete framework which I need to refactor for making it usable for everyone (adding customisation vars on each piece of code instead adding values according to our design system) so I've that pending too on my list and I'll give that free for everyone too so you can collaborate, give feedback and use it on your projects.

TL;DR:
Design has its process. On development, we have ours. It can not be done the same way because the tools we use are too different (on design you can easily copy-paste -> edit an element while on development you need to import -> override, causing overheating, being less able to override in the future and performance issues) so we need to found the best way to work on each development stage instead trying to find out a single way to work for eveyone.

Thread Thread
krisguzman_dev profile image
Kris Guzman Author

I appreciate you breaking down an example! I see what you're saying, you find it difficult to pull out common styling while also having component specific styling.

The only part where I'm confused is why you feel you are forced to structure your scss files that way with an atomic design structure? I personally wouldn't do that either.

For example, I usually using CSS-in-JS libraries, which allows me to setup a "theme". This is where I would put my fonts, shadows, global button styles, etc. Material UI does this pretty well.

In SCSS, I imagine you can do something similar. But if you don't want a global theme file, you can still have a structure where your actual components are in, for example: components/atoms/* and you have a "master" style sheet for all buttons at components/atoms/buttons.scss. If you don't want your SCSS files in your components folder, then you can still do something like scss/buttons.scss no problem.

Maybe I'm misunderstanding, but it looks like you are trying to enforce atomic design principles in your styles. Atomic design is an abstract way to categorize components, but there's no reason you have to apply the same structure to your styles.

Thread Thread
joelbonetr profile image
JoelBonetR

Seems we are on a middle point. We does not use libraries or frameworks to handle styling because we are seeking performance on our projects and those frameworks and libraries are generic tools that solves a need but not in the better way (according to performance).

If you abstract your structure and keep your files on a correct way (semantically) and you inherit what is needed on each place you'll found yourself breaking up the atomic principles, that's because it's a design methodology which does not fit into a development process as is.

The only way to fit atomic design into development is having a greenfield where components look always the same regardless of the context (which is never true because you'll get a strict but unbalanced design) so you can reuse all components as is. Working on big projects makes you think how to handle the things for being nice to handle (or less hell like) for the developers while maintaining the performance and scalability (avoid overrides when possible, handle theming variables for re-desing easily and quickly and so).

The project structure deals with the speed devs can find the exact files they (we) need to edit something, avoid duplicity and avoid any other concern.

Using CSS-in-JS makes you handle a styling for a component directly inside the same component. This, even being ok in most cases must be used together with scss. Scss for the global things, css-in-js for specific component styling so you get an inheritance Sass -> component.

Imagine you have 68 components which uses an outline-color: blue and you need to redesign (by a rebranding process or whatever) that to be green. You'll need to edit it in 68 places instead doing that on a global place which is more correct and brainless.

It always depend on how big is your project and how much it's going to grow so you can analyze, choose and define the right methodology and patterns for it. You can fail and learn, you can success and learn too but there's experience from others that can help you with that too.

Thread Thread
krisguzman_dev profile image
Kris Guzman Author

Maybe it would help if I explain what I typically do with this kind of setup.

I have a components folder with an atomic design structure, and I also have a "domains" folder so that I can create one-off components and business logic heavy components that are specific to a piece of the application. (resolving the limitation you mentioned about having greenfield components).

For styling, you wrongly state that css-in-js makes you handle styling directly in the component. At it's most basic level, yes, but I use a theme object in my projects, which contain styles for shadows, colors, spacing, etc, that can be setup in one place and used anywhere. I also have a globalStyles.ts file (for styled components) where I set global styles for typography and fonts.

I think it's important to remember that there is no universal project structure, and I never said there was. This project structure, like any other, can be adapted, modified, and built upon to suit the needs of a specific project (large and small).

Thread Thread
joelbonetr profile image
JoelBonetR

nice I'm getting more what you tried to explain, thanks for clarifying!