Let's look at how you should approach creating a component library in your organization.
If you work in an organization with several applications, you’ll most likely find yourself recreating the same pieces of UI again and again. They’ll look almost the same, of course, and have slightly different APIs. You might even have gotten around to test one or two of them. At best.
Creating reusable components is among the very best investments you can make. You create something once, test it once and use it everywhere! It’s become more popular in the last couple of years, and getting funding to create your own has gotten easier, too.
However, making these reusable components isn’t without its own challenges. You need to give the APIs some real thought, you need to consider more use-cases, and you might even need to document a thing or two for the next developer that’s being onboarded. It’s often very different from writing application code, and it requires a different set of skills and experiences to pull off well.
I’ve been creating reusable component libraries, design systems, and UI kits for both large and small organizations for the better part of a decade now, and I’ve gotten a few tips I want to share with you. I’ve come up with them through experimentation, iteration, lots of errors, and a few successes. They might not all work in your context or situation, but I’m sure you’ll gain a few new perspectives after reading this.
I once heard of a project where they’ve hired this guy to create a component library for them. He sat alone in his office for 6 months or so, and coded up every component perfectly. The code was immaculate, the test coverage was triple-digit and he had created lots of components for people to use.
The problem was, however, that barely any of his code was of any use to the rest of the teams that had been eagerly awaiting his delivery! The components were high-level concoctions that weren’t really reusable because their use cases were so narrow. The APIs didn’t make sense to people, and to top it off, the documentation was in a language that some of the teams didn’t know. The component library was abandoned after a few months.
Understanding your user’s needs is one of the most basic lessons in product development. And when you’re developing a component library that other developers will use, understanding what they need is paramount for creating the right components.
Creating a quick user survey might be the most cost-effective move you’ve ever done. Here are a few questions you might ask:
Gaining this user insight will leave you much more informed, and make creating the right thing much easier than just using your intuition.
When you create a component library, there are a few things you’ll do over and over again. Some examples are:
To make these common activities easier to handle, you should put in the work to automate as much of them as possible. Invest in creating the infrastructure that makes this possible.
To create new components, use a tool to bootstrap the required files automatically. I personally love Plop, mostly because its name makes me smile every time - but writing your own scripts is also fine. The most important thing is that creating new components and packages shouldn’t be more than a single CLI command.
Releasing new versions of your components is hard - especially if you’re using a monorepo. Changesets is a great tool for handling both releasing and creating changelog entries for you. It makes the entire process of creating releases a breeze! Couple it with its GitHub Action, and you’ll have automated the most gruesome part of creating a library in a few minutes.
Updating and deploying your documentation site should be automated. Make sure it’s deployed automatically whenever you merge a pull request to your main branch and make editing it easy. I personally enjoy using Sanity as a CMS, as it gives me the flexibility I crave. However, using something simpler, like MDX, will probably suffice for most use cases.
Ensuring you don’t screw up is harder, but not that hard. Write unit tests for your components, and use a tool like Cypress to create more elaborate end-to-end tests of your component library. Did you know you can automate lots of accessibility testing this way, for instance? Pretty neat!
Investing in setting up and automating all of these things will make creating, developing, and maintaining your component library much easier in the long run.
There are lots of things you can do to create more reusable, compassionate components. I even did a talk on the subject! But one of the most important things I want you to remember is this: Your component consumers will have diverging needs.
Let’s look at an example. An accordion, for example. Most times you’ll need an accordion, you want to add a title that’s always shown, and some content that’s shown when the user clicks it. The simplest API I can come up with (in React this time) is the following:
<Accordion>
<AccordionItem title="Want to read a joke?">
<p>
I'm afraid for the calendar. Its days are numbered.
</p>
</AccordionItem>
<AccordionItem title="Want to see a dog?">
<figure>
<img
src="https://placedog.net/500"
alt="A random dog"
/>
<p>Here is a dog!</p>
</figure>
</AccordionItem>
</Accordion>
That’s a great API in my mind. However, it assumes a bunch of things. It assumes you want the same accordion “expanded / not expanded” icon for every accordion, it assumes you only want text in the titles, and it assumes you don’t want to do something funky we haven’t thought of.
9 times out of 10, this is the best API. However, you need to provide your consumers with the possibility to freestyle within the limits of your design. In those cases, you need to provide a lower level of components for your users to compose yourself. Here’s the same example in a more low-level component design:
<Accordion>
<article>
<AccordionButton>
<LaughIcon /> Want to read a joke?{" "}
<AccordionStatusIcon />
</AccordionButton>
<AccordionPanel>
<p>
I'm afraid for the calendar. Its days are numbered.
</p>
</AccordionPanel>
</article>
...
</Accordion>
Providing this flexibility to your more complex components will make them much easier to use while preserving most of the flexibility of writing the code yourself.
This might be a no-brainer, but I want to include it anyway. Too many times have I seen component libraries start with complex components, such as date pickers, just to fail or diverge because it’s too much work too early.
When developing your component library, you should focus on creating the smallest, most reusable pieces of code first.
The stereotypical button should definitely be a part of this group, but also components such as headings, paragraphs, links, grids, stacks, and icons. Creating these first, instead of creating them as a part of larger components, will make creating those larger components so much easier.
Documenting your components is incredibly important. It makes it easy to onboard new colleagues, and for old colleagues to understand new components. Perhaps it’ll even be valuable for you down the line!
While there are lots of ways to document a component library – JSDoc comments, TypeScript types, and Storybook stories, to name a few – nothing really measures up to a custom-made website. It gives you a level of control that generic tools just can’t provide, and
If you have the resources to do so, invest in building a custom website for documenting your component library - and use that very component library to create it. It makes it easy to spot developer experience faux pas, lets you try out your components in a real-world scenario, and documents it all in the process!
That doesn’t mean you should skimp on writing JSDoc comments or TypeScript types. Those are incredibly useful for in-context docs and are a real make-or-break for the developer experience of using your components. And since the developers are your users, the DX is UX. So make sure to remember that as well.
I don’t care if you’re a world-famous developer – you’re not going to do a better job than the rest of your organization combined. Involving your co-workers and users in your component library might be the most important thing you can do for its long-term success.
But how can you involve the rest of your co-workers in this process?
The secret is in starting small, and sowing seeds of inclusion all over. Here are a few tips you can employ if you feel comfortable doing so:
Make sure you know your users as well as you can. Invite colleagues for a coffee, ask them out to lunch, whatever – just create an excuse to get some real one-on-one feedback from them. Perhaps they love what you are trying to do? Perhaps they have suggestions for improving the process? Listen!
This is the best way to hone your backlog - ask people what they actually need right now. This will help you figure out what to do when, and create a bunch of very satisfied customers in the process!
Once you got people using your component library, you want them to help create it. This will exponentially boost your throughput and is great fun as well.
Once you’ve figured out what your colleagues need, offer to sit down with them and pair-program that feature. This will onboard people faster than any guide you’ll ever write, as they’ll see all the things they need to do, being done.
Woah, that was a lot of high-level advice. It won’t help you much with the coding itself, but it should definitely help you do all the organizational stuff better. And with a bit of luck, you’ll help save your company both lots of money and lots of headaches.
Best of luck!
All rights reserved © 2024