🚚 Delivering perfectly packed components with Storybook, React, Typescript and Tailwind
If there is one thing that we folks at Circuit believe, it’s that delivery can be better. Not just a little bit better for a handful of people but significantly better for everyone involved. One of the ways that we get to do that is through a neat product of ours called Circuit for Teams.
Just to give you a little more context before we start with the nerdy talk, Circuit for Teams (C4T) allows delivery companies to better manage their operations. Think route optimisation, driver tracking, recipient notifications, that kind of stuff.
Today we’re going to talk about the C4T web app and how we’re rebuilding it from scratch, with Storybook and a handful of other charming component building tools.
A component-first approach
The best thing about working on a new version of a product that already works is that you don’t need to rush nearly as much. Product market fit is already proved, users are being served a well-rounded experience, and cash-flow is coming in.
Surely there are improvements to be made—otherwise, I wouldn’t be here today—but the effort made during that first iteration is what now allows us to focus on scalability, performance and stability.
That newfound focus is what motivated us to work in a component-driven manner. We needed strong, solid foundations for our new app, and we found the perfect stack to do so. Let’s talk about that.
Storybook and the beauty of building components in isolation
Programmers are experts in shooting themselves in the foot.
Sometimes we do so on purpose when trying to predict the future and optimizing too early. Some other times, we get so entangled in business logic and boilerplate that our code stops making sense even to ourselves. Storybook helps with the latter.
You can think of Storybook as a UI sandbox where you can to play, test, and stress your components with a minimum amount of friction.
Forget about authenticating and navigating through four routes just to check if the hover styles are correct on your
ProfilePicture component. Keep Storybook running alongside your app and use it whenever you need to tweak and test a component.
Another great thing about Storybook is how it encourages you to build components in isolation. Just go ahead and implement your component as a simple piece of UI, completely unaware and decoupled of anything else in your app.
Doing so makes writing component tests much, much easier as you only need to focus on what your component should do given specific user actions, state, and/or props.
And trust me, having an environment where tests are easy to write is a godsend when you need to be sure that your component is rock-solid and every single edge-case works as expected. Strong houses need strong foundations.
React, Typescript and Tailwind for speed and safety
One thing that helps, though, is TypeScript.
Truth be told, TypeScript can be frustrating and does make development a little slower, even more so during the early days of development.
However, a TS codebase evolves in a much more predictable and reliable way. It is a good trade-off if you can afford a little learning curve and longer project setup.
Now, every stack choice can make your team move faster or slower in multiple, often unpredictable ways. But one pick that worked surprisingly well for us was pairing React with Tailwind.
I say surprisingly well as one of the many front-end engineers that despised the very own idea of Tailwind. The infinite amount of utility classes looked ugly and felt limiting, I thought that I’d need to create custom classes every time a new edge-case popped up and DX would be awful.
Well, I couldn’t be more wrong. Turns out that Tailwind works really well for building components when your design system is built over its classes and patterns. Communication with the design team also goes a long way when regular Tailwind styles don’t cut it.
We even found a nice way to make TW’s classes look a little bit better with Styled Components and Twin, so instead of:
<div className=“bg-gray-50 rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500”’ />
We do something like:
const Button = tw.div` bg-gray-50 rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500 ` <Button />
Crawling, walking, running and making it even better
Our current component test standard only covers prop/state/render tests while ignoring style changes, so one thing that we’re definitely exploring in the future is Visual Testing with Storybook.
Tailwind helps prevent visual regressions quite a lot, but we can never be too careful.
With all that being said, we are still in the early days of this rebuild, and while this stack has proved reliable (and pretty fun) to work with, there are still a lot of improvements that we’re considering for the future—which most certainly will be featured around here.