Before diving into building you're own component library from scratch, let's have a look at the different types of component libraries out there, and the benefits and drawbacks of using them.
đĄ I want to give a special shoutout to stephband (Mastodon, Bluesky) for proofreading and providing feedback.
Please note that this is a X-Post from my site. The content is largely the same, but the original post has interactive snippets and videos that are omitted in this article.
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.
<body>
<div class="wrapper">
<counter-button></counter-button>
<counter-button></counter-button>
<counter-button></counter-button>
</div>
<script type="module">
import { LitElement, html } from 'lit';
class CounterButton extends LitElement {
constructor() {
super();
this.count = 0;
}
static properties = {
count: { type: Number }
};
_increment() {
this.count++;
}
render() {
return html`
<button @click=${this._increment}>Count: ${this.count}</button>
`;
}
}
customElements.define('counter-button', CounterButton);
</script>
</body>
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:
- Material Design (Google)
- Base Design (Uber)
- Lightning Design System (Salesforce)
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.
đĄ TIL, Internet Explorer supported a âquirks modeâ that let developers write non-standard HTML and CSS to appease older browsers that didnât support the standards.
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.
Thereâs a reasonable argument to be made that there has been an over-correction and that the frontend landscape is now oversaturated with tools that are too powerful for most peopleâs needs, but letâs not go there.
This version is extended with interactive snippets on the original post
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.
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.
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
đĄ A quick side note: If you're interested in building your own web component library, then consider checking out my course Component Odyssey. You'll learn how to build and publish a component library that works in any frontend framework.
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.
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.
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.
The original article has a video showing me interact with different checkbox implementations using a screen reader
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.
The original article has a video showing me interact with different combobox implementations using a keyboard
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.
Thanks for reading! If you're interested in building your own web component library, then consider checking out my course Component Odyssey. You'll learn how to build and publish a component library that works in any frontend framework.