Write React components with Tailwind and Windsock
15 Juin 2020
This year I discovered Tailwind, it’s an utility-first framework, that makes writing css blazing fast and effective. I think it’s an amazing tool, very close to perfection!
But, there is one thing that bugs me, I don’t like very long class strings in my code and here is why:
- it can be difficult to find a class when the className string is very long,
- code reviews can be complicated depending on your formating tool, adding or removing only one class can cause a lots of modified lines for a single commit,
- you are more intent to duplicate code like when you’re styling a list for example.
In my opinion, it’s OK to have long classes when I’m browsing source in the browser but I like to keep it readable in my code.
Hopefully I found a solution that solves all these problems.
The Windsock solution
Before discovering Tailwind, I was using styled-components and I really liked the way it works. If you’re not familiar with styled-components
, here is a quick example, instead of writing a component the «classic» way:
const style = {
color: 'red'
};
const Component = () => {
return (<div style={style}>{children}</div>);
};
You can write the exact same component just like that:
const Component = style.div`
color:red;
`;
Pretty straight forward and convenient!
Windsock is tool that helps create React components with any classes that mimicks the styled-components
API. Instead of writing css backtick code, you add classes. So that «classic» component with a Tailwind class:
const Component = () => {
return (<div className="text-red-900">{children}</div>);
};
Can be written that way:
const Component = tw.div`
text-red-900
`;
Just like styled-component
, you can extend an existing component, pass props to change class, by adding some other class:
const Link = tw.a`
text-red-900
text-underline
`;
const ActiveLink = tw(Link)`
text-red-500
`;
You can also pass props to your Component
to adjust class:
const Component = tw`
p-0
${({ open }) => { open ? "m-0": "m-12" }
`;
I think it’s enought for an introduction to Windsock, let’s see it in real world example.
Real world example: Tailwind homepage
On the homepage of Tailwind there’s an interesting showing how it works. Let’s use this code to see how you would implement this using Windsock. Here is the code from Tailwind homepage:
import React from "react";
const Component = () => {
return (
<div class="md:flex bg-white rounded-lg p-6">
<img class="h-16 w-16 md:h-24 md:w-24 rounded-full mx-auto md:mx-0 md:mr-6" src="avatar.jpg">
<div class="text-center md:text-left">
<h2 class="text-lg">Erin Lindford</h2>
<div class="text-purple-500">Customer Support</div>
<div class="text-gray-600">erinlindford@example.com</div>
<div class="text-gray-600">(555) 765-4321</div>
</div>
</div>
</div>
);
};
It’s 20 lines of code for a simple example because it only handles responsiveness, no animations, no hover state, no active state, etc. But it’s interesting to see how Windsock can keep JSX even more simple.
With Windsock, you can rewrite the component like that:
import React from "react";
import tw from "windsock";
const Component = () => {
return (
<Wrapper>
<Image src="avatar.jpg" />
<Center>
<Name>Erin Lindforf</Name>
<PurpleParagraph>Customer Support</PurpleParagraph>
<GrayParagraph>Customer Support</GrayParagraph>
<GrayParagraph>Customer Support</GrayParagraph>
</Center>
</Wrapper>
);
};
const Wrapper = tw.div`
md:flex
bg-white
rounded-lg
p-6
`;
const Image = tw.img`
h-16
w-16
md:h-24
md:w-24
rounded-full
mx-auto
md:mx-0
md:mr-6
`;
const Center = tw.div`
text-center
md:text-left
`;
const Name = tw.h2`
text-lg
`;
const PurpleParagraph = tw.p`
text-purple-500
`;
const GrayParagraph = tw.p`
text-gray-600
`;
Now the JSX is easier to read and each component with Tailwind class is now defined after the JSX. It’s easy to jump to the definition of a component and back to where it’s used, if you want to change all PurpleParagraph
style, you just need to do it at one place. And if you add/remove a class, it’s just a one line diff.
Finally, if you look at the source code in the browser it’ll end up the same but I think Developer eXperience is a lot better.
Conclusion
Ok, that’s how I write React components with Tailwind and Windsock, I hope you’ve learn something and that you’ll consider giving a try at Windsock. Another cool thing about Windsock is that I like to use Tailwind but it also works perfectly with any other CSS utility framework, because you can add any class, you want not only Tailwind’s.