What is a Component Library and Should You Build Your Own?


First published: 05/08/2024

What if there were no music albums?

I’m a huge music fan. One of my favourite pastimes is to put on a record and listen to it front to back. A music album is simple in concept, it’s a suite of recorded tracks by an artist and is considered a complete and coherent set of songs.

But what if recorded music didn’t exist? Instead of putting songs to tape, CD, or mp3 (or FLAC if you’re that way inclined), you could only listen to an album if the artist played it live for you. You’d need to go to the band, ask them to set up their equipment and get them to play the album front-to-back. They’d need to play it the same way every time to ensure that everyone had the exact same experience.

The cracks would start to show. It’s not an efficient way to ensure that anyone interested in the band’s music can listen to it. If Taylor Swift were to play her song Fortnight personally for every person who listened to it on Spotify, it would take her 3,179 years. And that doesn’t account for any plane travel. Artists would get bored, maybe even careless, leading to a lesser experience for their listeners.

So how does this relate to web development? Every time you build a UI control, you have to ensure it’s functioning, robust, and accessible. You’ll get bored if you keep rewriting the same UI every time. Mistakes will slip through, leading to a worse experience for your end users.

A little about me

I’ve been a web developer for nearly 10 years, and I’ve written hundreds of components myself, often the same UI pattern many times. I’ve used dozens of component libraries, and have built admin dashboards, component libraries, mobile applications, blogs, figma plugins, VSCode extensions, and more. This article will be a distillation about where I see the role of components, libraries, and whether developers should write their own.

What is a component?

When building user interfaces, we don’t write all the HTML markup from scratch every single time. We write our UIs using components— reusable building blocks that encapsulate common UI patterns. Writing a component lets you use it multiple times in a single project or even in independent projects.

Here I’ve written a counter component, I’ve written it once and used it in multiple places on the page.

Us tutorial creators like to demo counters like they’re going out of style, but a real-world application will contain dozens of different UI patterns written as components.

In this article, I’ll group CSS rules that provide styling for certain UI patterns under the components umbrella. The definition can get murky depending on who you ask.

What is a component library?

Not all components are standalone. It makes sense for many components to be grouped within a single package, called a component library.

If you want your site to have a specific look or feel, you can use a component library. There are component libraries that:

  • offer components that adhere to a design specification.
  • offer multiple solutions for a specific UI pattern.
  • work with specific toolchain

But they come in different shapes and sizes. The definition I’ve come to use when defining a component library is the following:

A component library is a set of reusable components that are cohesive in their utility, or appearance (or both). A great component library will help developers achieve their UI needs efficiently, while offering an exemplary experience for the end user.

What’s the difference between a component library and a design system

I talk about guidelines and design systems later in this article, so I’ll take a moment to disambiguate them. It can be difficult to see where one ends, one begins, or one subsumes the other.

Design Systems

I see a design system as a specification for how things should look, feel, and behave. A design system can encompass a product, a brand, or a company to ensure consistency across the suite of experiences. A comprehensive design system will dictate everything from font families, font sizes, spacing sizes, UI patterns, and copy guidelines.

A few of the most well-known design systems include:

While many design systems are specific to companies, there are design systems, like Material Design, that teams across the globe use to shortcut their way to building familiar feeling products. You’ve probably used a handful of products that use Material Design principles but they’re certainly not free from basic usability issues.

Component Libraries

As for component libraries, they may or may not be the code implementation of a design system. If you work for a company with a design system, it’s likely that the corresponding component library (if one exists), is tightly integrated with it.

For instance, Google’s Material Web is a web component implementation of Material Design. Base Web and Lightning Web Components are also open source too.

A brief history of component libraries

The concept of UI components (or widgets) has been around for a long time. If you want to see a museum’s worth of retro user interfaces, grab some popcorn and watch this 2+ hour video of “all the widgets” from 1974-1990.

From the early 2000s, we’d start seeing component libraries made to help developers build for the web. The web browser landscape back then was unrecognisable from what we see now. Versions of Internet Explorer deviated away from the spec entirely, which was particularly problematic given the huge market share that IE had back in the day. Internet Explorer 6 was famously known for being a pain to develop for. Mainly due to its incorrect implementation of the box model, and lack of CSS2 support.

Fortunately, when I started web development in earnest, many of these issues were ironed out. By this point, there were still a handful of libraries that made writing complex interfaces with cross-browser support a little easier. jQuery UI, the first component library I used, supported accordions and other widgets. But the browser is constantly evolving, and we now have a native way of implementing this accordion pattern using the details and summary elements, available in all browsers in 2020. With these elements, you can get pretty far along creating interactive accordions without JavaScript.

Contrast this with 2009, and these elements haven’t been implemented in any browser. It required a fair bit of JS to get working. Have a look at the jQuery UI v1.7 source code, and CTRL+F “accordion” if you want to see how web devs were implementing accordions 15 years ago.

Over the next couple of decades, the capabilities of the web grew. More powerful devices meant more powerful browsers. More powerful browsers meant web applications became more ambitious. Developers responded by creating the tools to help us build these applications by allowing us to create UIs using building blocks, i.e., a component model. We saw a proliferation of these component-based frameworks. I’m talking Angular, React, and Vue. Each with its own rich ecosystem of component libraries.

With tools like jQuery UI, library consumers would write the markup themselves, and manually add the interactivity, like so:

With the newer component model, developers could author fully encapsulated components with markup and behaviour, and consume it by doing little more than plopping it on the page:

You can see that the behaviour between the two accordion components aren’t 1-2-1. I could add a little JS to make it behave like the jQuery accordion. The benefit is that the second accordion is built using HTML only, and the JS can be used to enhance the core experience.

What makes a good component library?

The challenge with building a component library is that they’re not a one-and-done deal. Many of the most popular libraries have been around for years and have had heaps of research, usage feedback, and contributions to get them to where they are now.

I’ve found that a good component library often has the following traits:

  • It understands the problems of its target developers and solves those problem well
  • It has great documentation
  • It ensures a good experience for the end-user
  • It’s robust and caters for appropriate input modes and devices.

On the flip side, a way to discern if a component library isn’t good is if it doesn’t consider accessibility, has an inconsistent API, has little to no project stewardship, or has no clear and consistent documentation.

What are the benefits of using a component library?

We know what a good component library looks like, so let’s see how one can make your life, and the lives of your users a little better.

Component libraries save you time

If you’re on a project with a tight deadline, it’s important to be efficient. But efficiency shouldn’t come at the cost of crafting a robust web experience. Using a component library lets you spend less time reinventing the wheel and more time focusing on the finer details.

Component libraries make you and your users happier

We’re not motivated by repetitive work. We enjoy technical challenges, and writing the same components over again is not a fun challenge. We’ve already spoken about what happens when we get bored and let mistakes slip through.

If you wanted to implement a dialog component from scratch, you’d need to:

  • Handle focus trapping correctly
  • Make the rest of the page inert
  • Position the dialog correctly
  • Ensure that it works with assistive technologies

It takes work to remember and implement the above, but the consequence of getting it wrong can render your interface literally unusable, such is the case if you incorrectly handle focus.

By using a component library that’s been built with the end users in mind, you can prevent the risk of introducing broken experiences, while spending less time rebuilding the same components.

Component libraries lead to consistent experiences

If you work for a company with several different web applications, they’ll generally follow a set of guidelines. These guidelines might dictate the colour palette to use, the size of your typography, or how UI elements should look and behave.

But you increase the likelihood of your application deviating from the style guide if you’re re-writing components. By having a component library, you can more easily audit your component’s UI against the brand guidelines so they look great, wherever they’re used.

Uber has several different apps that share the same user interface elements. I’m almost certain that they use the same component library across these apps. That way each new app is virtually guaranteed to adhere to the brand’s guidelines.

Different Uber apps side by side, showing how similar they are in terms of appearance

What are the drawbacks of using a third-party component library?

The benefits I’ve mentioned above are irrespective of whether you’re using your own component library or a third party. If you or your team has decided that they don’t want to build a library, and instead lean on a third-party, then it’s worth considering the following.

Vendor lock-in

By choosing a component library, you’re picking a partner who will greatly impact how you write your frontend code and how your interfaces will look and behave.

The former will have a big impact on you, and the latter will have a big impact on your end users. Using a component library is locking you into the standards of that component library.

The library could introduce massive breaking changes in a major version that could require dedicated development time, and a lot of testing to ensure that no serious regressions were introduced.

A few years back I used React Admin to build a complex admin dashboard to an internal division. The library offered a suite of components specifically dedicate for fetching and displaying complex data. Because our application at the time relied heavily on React Admin, upgrading between major versions was challenging, especially as many of the internal tools used by React Admin had been swapped out for others. The change surface was huge, and we spent a good deal of time upgrading and flagging the issues that we spotted.

I don’t believe that building our own solution would have saved us any time in the long term, but this kind of vender lock-in is worth considering, especially before going all in on a tool.

Code bloat

Shocking as it is, libraries with a lot of components tend to be written using lots of code. Code that you download when installing dependencies, and code you sending over to your end users.

Modern tooling makes it easier to perform bundle optimisations like tree-shaking to remove unused code, but there’s no guarantee that you’re removing all of the code that your users won’t need.

Unless you dig deep into the libraries that you’re using, you may not be aware of all the separate packages they’re importing. You could end up with hundreds of unnecessary dependencies. The folks in the e18e community have been working hard at bringing this problem to light, while also fixing it too.

Many of these problems could also be said about rolling your own component library. The biggest difference is that you have stewardship over your component library. You’re able to define how it solves your specific problems, and you have control over improving its shortcomings.

The different shapes a component library can take

The initial proposal for the World Wide Web was a tool to improve communication between researchers at CERN. The proposal outlined how documents could be shared, and linked to one another through the use of hypertext. This is the fundamental cornerstone of the web, and we still use the humble <a> tag to link between other HTML documents across the web.

But the web has grown in scope over the last few decades, and the browsers we use to navigate the web have become beasts of their own. The browsers today can enable powerful forms of creative expression, and the running of native-like software.

There are hundreds of different solutions out there, some general purpose, others hyper-niche, but finding the right tool for your next project requires a complex decision process that might look like this.

The different kinds of component libraries, and when you should use them. The diagram's context is explored below

This isn’t a comprehensive list of ALL use cases or component library types, but it illustrates how component libraries differ in terms of:

  • the technologies involved.
  • the levels of abstraction they offer.
  • the problems they solve.

Let’s take a look at some of the most common component library types

Utility classes libraries / CSS Style Guides

For me, Bootstrap is the first that comes to mind. Back in the day, if you wanted to give your site a quick lick of paint, you’d drop the CDN link to the bootstrap CSS file and immediately get that Bootstrap look. It was everywhere in the mid-2010s.

A demo example of a Bootstrap web, circa 2013

The technical scope of these kind of tools range from

  • A single CSS file (Pico)

to

  • A toolchain to generate CSS classes based on your configuration (Tailwind)

Dozens of other tools, like Open Props, fit somewhere in between.

Off-the-shelf component libraries

If you’re building an interactive web application, you might just want to grab a suite of components that look great and function well. There are many of these off-the-shelf component libraries that give you everything you need and more.

Regardless of which framework you’re writing your app with, there’s likely to be a set of great looking components for you to use.

Another great component library is Shoelace, which provides dozens of fully interactive and fully-styled components.

What makes libraries like Shoelace particularly interestingly is that it’s built using web components, the browser’s built-in way of writing components. Building your UIs with tools like Shoelace, give you the added benefit of being able to use them across different frontend frameworks. Which is something I’ve spoken a little about in the past.

Here’s the same Shoelace component being used in Vue and React.

Shoelace in Vue and React

Unstyled components

Depending on your project’s specs, you might not have the luxury of using an off-the-shelf tool. Your design specs might be very specific.

I’ve seen teams roll components at the first sign of friction. And in one case of a hand-rolled data picker, led to a way worse user experience. In retrospect, using an unstyled component library would have given the team flexibility with appearance, while ensuring that the time

That’s why you can reach for a library out there that offers completely unstyled components with flexible styling hooks. If it’s a good library, it’ll also take care of all those complex interactions. It’s a best of both worlds situation.

It’s easy to mess up a checkbox if you want to push beyond the styling hooks that the browser provides, unless you test with a wide-range of devices and input modes.

Radix is a popular example of a library, but it’s built using React.

Other examples of component libraries like this are Lion and HeadlessUI.

Copy Pastable Component Libraries

Some developers might want the best of both worlds. They might want a component built by a trusted third-party library, while also having full control over the markup, styles, and functionality. Libraries like ShadCN allow for this kind of work flow, by allowing developers to copy and paste the component definition into their own projects, effectively letting them own the component.

Why isn’t there one component library to rule them all?

At this point, it’s probably clear why no such single component library exists. We’ve looked at a non-exhaustive look at different groups of component libraries.

There is, however, a movement to introduce a “Global Design System”, a concept spearheaded by Brad Frost.

In the announcement, Brad outlines that in the hundreds of projects he’s been a part of, many of the UI controls behave (or should behave) similarly across these various projects, yet developers reimplement the same thing in every single project. This has lead to lots of wasted time and effort, and inconsistencies between projects. This also expands to the existing component libraries out there. You’ll see that the keyboard behaviour for a combobox in React Aria, is different to that of the combobox in ShadCN.

Brad Frost is proposing a Global Design System as a set of web components that should be adoptable by almost any frontend project to ensure a baseline of functionality for the controls that are not yet available in HTML.

There are discussions going on within the Open UI to see how this could start taking shape within the next few years.

Should you build your own component library?

This article has been a wide dive into component libraries, and with all that context, you’ll inevitably ask yourself, when staring at the empty HTML page for your next big project, whether to build your own component library or use an existing one.

My first thought is: I don’t think you should build your library.

I generally favour picking a battle-tested library. Particularly one that has:

  • Been used across thousands of projects
  • A strong community, in Discord, or GitHub
  • Great documentation
  • A strong focus on accessibility
  • Worked with the strengths of the chosen framework

Most importantly out of all of these is to use a component library puts care into building accessible components.

Take a combobox for instance. It’s a search input and a select menu mixed into one. If you’ve built your own, you may get it looking good, and working with your mouse. But you’ll also need to consider:

  • Cross browser support
  • Tab and focus behaviour
  • Screen reader support
  • Handle states for async loading of search results

Konnor Rogers, who does excellent work in the web + web component space, has shared countless frustrations with his experiences building an accessible combobox. Here’s one such tweet he shared.

Screen reader support is particularly complex, and is worth of its own bullet-point list. To support screen readers, you’ll also need to handle:

  • live regions
  • interactive controls
  • selected items
  • support between different screen readers

As a side note, I only have access to Voiceover, meaning it’s difficult for me to test these complex UI patterns using different screen readers. Like browsers, there are differences between screen readers. In this article, Are We Live?, Scott O’Hara describes how there’s variance among the difference with how they treat the live regions.

This means it’s also up to you, the developer to pick a component library that you can trust has been developed with accessibility in mind. This is why it’s also important to pick a component library that has a strong community. It’s important to be able to:

  • See the bugs and issues others have flagged for a given library
  • Suggest (or even contribute) improvements and changes to such library
  • Discuss ideas with members of the community and build working relationships with active members of the community or even maintainers themselves

Finally, and not least, a great component library will consider much more than the aesthetics of their components. For a component library designed for the web, it should try it’s best to:

  • adhere to the Web Content Accessibility Guidelines (WCAG)
  • ensure that the components work across different input modalities (touch, keyboard, screen reader)
  • ensure that the components are usable for folks with additional requirements, like those living with vestibular disorders, vision impairments, or a broken hand.

Building your own component library can be a good thing, actually

If I haven’t scared you off from building a component library, then let me contradict myself and explain why it can be a really good thing to build your own.

If you take the time to put care and attention into building a component library, then you’ll find yourself a developer who better understands the browser platform, accessibility best practices, testing practices, and more.

But it doesn’t just stop there, there are some excellent reasons to build your own library.

For starters, you can build something tailored to your needs, and avoid some of the bloat you might get form an off-the-shelf component library. It’s up to you and your team to understand your end users, and you can build something specifically for them.

You also have the opportunity to experiment with novel approaches. If you have a hyper-niche problem, there might not be a component library out there to solves that need. It could be a component library that:

  • Visualises data in specific way
  • Has a distinct and unique visual identity
  • Is built on a new framework

That gives you the opportunity to build something tailored to your needs. You then have the opportunity to change and fix things as your needs change, or as you understand the problem space better.

Importantly, you’ll learn more about the web by doing so. If it’s your first time building a component library, it can be an opportunity to dive deeper into the HTML browser specs, or brush up on your web accessibility knowledge. This will improve your abilities as a web developer, which will serve you well in any frontend project in the future. It could even help you land your next job.

So whether you should build a component library depends on your end goals. Consider questions like:

  • Do I want to better under stand the browser?
  • Do I want to build something quickly?
  • Do I want to make it usable for as many users as possible?
  • Do libraries exist that solve my current problem?

Depending on what your answers are, you can make the right call for your project.



If you enjoyed this article, then I figure you like to be kept in the loop with web development tips. If so, the Component Odyssey newsletter might be right up your alley.