I came across this pattern working with my team at Mozilla, so I can’t take full credit. However, I found this method of working with components too simple and elegant not to share. Long story short this is a great way to manage a component that takes a large number of styling props. This pattern will help you map prop parameters to your SCSS files in a clean, scalable way
Before getting into the weeds, the ideal setup for this pattern is TypeScript (we will be using enums) and React CSS Modules ( using enums to pinpoint values on the styles object ).
If you are impatient like me you can scroll down to the code, it is simple to understand, if you are interested in the what and why, stick around.
I was tasked with creating a React component library, of course, we need to have buttons in the library so I started there. I quickly realized just a simple button that needed to cover all aspects of what the button “could” be was not so simple. We only have a “primary” and a “secondary” button style but both primary and secondary styles encapsulate a “solid”, “outline” and “clear” type. Not to mention each has :focus, :disabled, :hover styles. Oh yea and we have a light and dark mode. Oh and also, the buttons will have a “small”, “medium” and “large” option. That’s a lot.
In addition to stuffing all of this functionality into one component, I also wanted to make the implementation of the button, from the DX side, extremely easy . A component library is only as good as how easy it is to use.
After writing a lot of bad code, I went back to the drawing board. One thing I felt was right about my bad code was I had some pretty nice enums that outlined all the button names. I also had some pretty clean SCSS going on. It hit me that there was almost a perfect one to one pattern with my enums and my SCSS. With a little tweaking I could make it a perfect one and use the JSX as just a middle-man for my enum and SCSS to communicate.
I have not been a huge fan of how React handles CSS, but having the styles imported as an object did open up doors for more possibilities. In this case I had the styles I wanted and the enums established, but how could I connect these to worlds? Good ole bracket notation!
First we have the button categories and sizes declared in enums.
Here is an example of the primary button “solid” and the size styles breakdown in the SCSS. Look to the ButtonCategoriesE enum to get an idea of what all the other CSS classes would look like.
The Button component will have, among others, the category prop and the size prop. I like to set defaults to the most likely scenario, in this case that would be a “solid/medium” button.
Using the Button component is very powerful now with just two styling pops. This is an example of an “outlined/large” button.
Hopefully you found this pattern helpful. Leave a comment if you thought this was great or, on the other hand, have some suggestions to make it better!