At this point it feels safe to say that component-based design and development is here to stay. Gone are the days of designing and building pages in isolation. Instead, we're building collections of components that all follow a shared design system and can be used anywhere on any page. This is increasing the consistency and predictability of our user experiences. It's also speeding up our development.
We're achieving this with the help of component libraries, the most important tool to emerge from this paradigm. Component libraries allow us to build, test, and browse our components in isolation. They also make prototyping new experiences both easy and fast.
That said, a component library can also introduce friction. They add complexity and there is plenty of room for error. Fortunately, like any technical project, we can ease this friction with proper planning. Answering key questions before building a single component can go a long way towards ensuring the library's success. We'd love to share what we've found to be the most important questions to ask. Specifically:
- What problems will a component library solve?
- Is everyone on the project behind the component library?
- How will the component library be used?
- What tool(s) will be used to build the component library?
- Where should the component library live?
- How granular should the library be? How should it be organized?
- How will component code be scoped? What about page layout?
- What data will the library use? What else should it have?
Component libraries add complexity to a project’s workflow. It’s important to be able to justify that with an explanation of the problems they solve. Don’t build one simply because everyone is talking about them or because it’s another buzzword to throw around. Instead, understand how it will improve your project. We’ll get you started with a bit more about the most common benefits.
In short, component libraries bring consistency to an organization’s brand. Everything in the library follows a defined design system, which does away with ill-informed, one-off designs. This consistency improves the user experience, which increases engagement. This may mean more ad revenue or product sales, or perhaps you're a nonprofit. Regardless, increasing engagement is always the end goal.
Component libraries also result in less time spent on development, as their complexity pays dividends down the road. Once it's built, the development team is armed with an arsenal of components used to prototype and build experiences in a fraction of the time. New features are easily shared across all properties and because bugs are siloed, they’re easier to test and fix.
What about the complexity we mentioned? Well, the component library adds yet another piece to the puzzle, which can be a blessing or a curse. It does allow further separation between front-end and back-end development. This can be really helpful on larger teams, but for smaller teams, that may only mean a tedious extra step.
Everyone has to champion the component library. This includes stakeholders, the design team, and whomever is using the components. Stakeholders won’t appreciate the time and care spent building and maintaining the library if they don’t understand the benefits. If the design team isn’t in tune, it’ll be nearly impossible to componentize their work. Likewise, if the library isn’t properly utilized while implementing its code, many of the benefits will quickly dissolve.
These champions may be spread across entirely different organizations. The less they overlap, the more important this communication and collective buy-in becomes. In any case, everyone has to be on the same page and be committed to the library’s success.
Successful components don’t care how they will be used. They don’t care about what data they’ll be fed or where they’ll end up on the page. They also don’t care about what technologies will use them, but knowing that may help inform the rest of our questions.
If the library lives in a separate repository, which we’ll also discuss more later, how will you update it everywhere it is used? Having the implementations randomly pull from the master branch will likely be an unstable mess. Instead, we recommend creating releases named with the semantic versioning scheme. Implementations can then update when ready, and the release names and notes will let everyone know what they can expect when doing so.
In addition to each component’s HTML, CSS, and JS, component libraries typically provide a user interface. That interface makes it easy for non-developers to visually browse and test the available components. There are many helpful tools that generate the user interface from the organized component code.
We wrote a post about evaluating tools to build a component library. It outlines how we settled on Fractal, but it’s important to remember that different projects have different needs. We revisit that process on every project. Given what we just discussed, if we know Drupal will be our primary consumer, we may use a PHP-based implementation of Pattern Lab instead. That post, in combination with your answers from this one, will help you evaluate which tool(s) will be right for your project.
We’re actually asking a few questions here. Assuming the library’s code is managed with version control, the first question is: which repository will it live in? If only one website or application will use it, and assuming it could be separated later if needed, it may be easiest to store it in the same repository. That would simplify integration by removing the aforementioned need for releases. If the library will support multiple websites or applications, it should probably live in its own repository.
Then there is the user interface. What will its URL be? More importantly, can it be public? Many organizations have public component libraries. This removes any friction from using it and gives potential partners or employees an impressive look behind the scenes. If you’re not able to convince the stakeholders to follow suit, at least be sure that everyone on the project can access it and knows where it is.
Deconstructing and organizing components within a library is an art form. Where do we draw the lines? Is a button a component? Or the form that uses it? How will you group them?
We recommend breaking everything down into the smallest possible bits, such as a button, from the beginning. Then reuse those components within larger components. It’s tedious, but it beats having to separate something later after it was already implemented somewhere. Also, to avoid calling everything a “component”, group them by the level of granularity. You can use Atomic Design’s naming convention for those buckets, or decide on something else that makes sense to your organization.
For this level of granularity and reuse to work, you’ll also have to build in flexibility from the beginning. Hardcode things like classes, labels, or content as little as possible. They’ll need different values at different times, so allow those to be populated with variables passed by whatever is using them instead. Only universal attributes should be hardcoded in a template.
Component code (HTML, CSS, and JS) is typically organized into individual component directories (or in some cases, a single file). This is a refreshing way to work. That said, you still have to ensure that the code in one component won’t affect another. Being able to use any component anywhere and being able to edit one without affecting another is only made possible by properly scoped code. From module patterns to BEM methodology, the solution will depend on preference and the technologies you’re using.
You’ll also want to ensure that any component can be placed anywhere. Don’t assign any outer layout-related styles to the component itself! Have separate elements for the various layout regions and place components within them. Assign styles like dimensions, alignment, and margin to those elements instead.
As with design, it's helpful to populate the component library with realistic data. We would recommend gathering and constructing a collection of sample data that can be used throughout all of the components. Most tools used to build component libraries will have a preferred approach to storing and using this data within the components.
Will you be building page prototypes within the library? We’d recommend it, but that does raise more questions. Should you attempt to link pages together within the markup, or link everything to
#? What about the
<head> tag? Do you attempt to represent the various meta tags stuffed with your favorite keywords, or do you leave that to whatever is implementing them? How many different page layouts do you need to account for?
What about documentation? At the very least, it’s helpful to have documentation that outlines how to use the library and implement the components. Some organizations add even more, such as guidelines for accessibility requirements or voice and tone. If your organization will want to include information like this, it’s important to pick a tool that makes that easy.
Start building components! We’ve spent the whole post stressing the importance of thinking ahead, but don’t let it paralyze you. You don’t have to have the perfect answer to every question. You never will. We’re still learning more with every component. Reading this post already has you ahead of the game, and from here the only path forward is to dive in. Be sure to reach out to @chromatichq if you need any help or advice along the way. Have fun!