How to Create Tailwind Component Variants Using React
In this post I share practical insights gained from real-life commercial projects on how to reduce the boilerplate that comes with Tailwind so you can improve your own, or your own team’s DX, and repositories.
It's quite typical when developers work to deliver features, but maybe don't have time to rework a component and end up with this kind of repetitive code:
Don't get me wrong, it works, but on a team of more than one, with minimal unit tests, it's only a matter of time before it degrades. Someone could add more functionality, maybe a few additional props that make it do even more things than it already does, which would make it even harder to understand.
There's a high probability of the classes either needing to be updated in more than one place, or some kind of regression due to a lack of familiarity with it.
I would always advocate for snapshot testing as a bare minimum, to try to avoid that kind of thing.
That's the bad news out of the way, now for some good news:
If someone misconfigures their IDE to ignore TypeScript errors, there's a console.error() message explaining why it isn't working as expected
The implementation is straight forward
Just think about how easy it is for another developer to use this component, they need only import it and add a few props, simple.
It Works So Why Bother Refactoring?
I intend to create more variants similar to <Alert/>, such as: <Modal/>, <Button/>, <Card/> and I will eventually add more variants to the existing <Alert/> component as and when they're needed.
If the code is simplified, the process of updating it could potentially be a breeze. I can imagine it now ...less time, less refactoring ...it sounds too good to be true doesn't it?
Don't get me wrong, it's not a hard-and-fast rule. I'm all for not refactoring for the sake of it, there are trade-offs such as the time taken now might not be necessary for project X to hit the deadline etc. However, for the little time it takes to do it now I'll bet on it not being worth kicking the can down the road to the next person (or future you) in the long-run!
How to Make It Easier to Manage
Here's the directory structure I'm using for this component:
I'm storing the bulk of the code that applies the variations in a separate hook, located in the component's directory.
The switch statement is no longer being used, I changed to an object lookup to reduce the amount of lines, which in this case makes sense because of the way the properties are named.
Conversely, if they were named in some inane manner I may have been tempted to leave the switch.
I've only left markup that is declared in one place, all variants are handled by the hook and referenced once.
Thanks for reading, if you have a question or spot a mistake, catch me on Twitter.