Create a Vue.js Component library without losing your mind

Milad Dehghan
3 min readApr 14, 2022

--

Photo by Glen Carrie on Unsplash

Building an extensive reusable and cohesive component library is a challenge for people who have their own custom designs and want to have a custom component library.

Atomic Design Principle is a theory for creating interfaces by Brad Frost and it's getting quite popular for making component libraries.

Atomic design
Atomic Design with Instagram example

In this article, we will not cover atomic design, instead, we will focus on how to design an extensible component library with vue.js, and also we will try to follow SOLID principles in our components.

Atomic design methodology contains five levels: Atoms, Molecules, Organisms, Templates, and Pages.

In my opinion Templates and Pages can be in other directories of the application and it's better not to include them in our shared global component library.

Atoms

Atoms are the smallest units of the component library some of them can be used alone, like Input, and Button, but some of them are parts of Molecules and organisms.

You should be careful with these components to make them as customizable as possible and follow the “Single-responsibility principle” and avoid violating the “Open–closed principle”.

As Kent C. Dodds said:

Unfortunately, truly maintainable, flexible, simple, and reusable components require more thought than: “I need it to do this differently, so I’ll accept a new prop for that.”

For example, you need an Input component and you start with something like this:

I like to prefix my components name with the application first letter it will help avoid conflicts if you like to add any component library in the future.

Seems good yea? but if you wanna scale the application, after a while this component will look like this:

and it will grow by any other use case and get even bigger than this.

So we will try to make it more customizable and follow the Open–closed principle and Single responsibility principle.

Take a look at this:

First of all, having a label is not the responsibility of an Input. So it can be a separate component. also, v-bind="$attrs" we can have all the props and attributes that the element supports also it will send back all the events to the parent. (you also need v-on="$listeners" it if you are using Vue 2) .

Molecules

Sometimes you need a combination of responsibilities so then you can make components in the molecules directory.

For example, if you need a combination of label and input to have a certain style all over the application. you can do it by creating a molecule component.

There is some consideration for Molecule components. you should make it as customizable as possible from the parent and follow Open–closed principle.

for that reason, I used a slot with the default value of the label prop. So it can be used with both slots and prop for that matter.

For example, if a developer wants to add a picture as the label or an SVG it's now possible.

Also, I put the input component inside another slot’s default value and added v-bind="$attrs" it to it because the main purpose of the component is to be input so all the attributes should be attached to the input.

We can use this component in many ways now.

Organism

If you need a combination of molecules(which will happen less often) you can use this directory.

For example, in the above example, we can make a component out of the comment form.

Then we can use it like this:

You see that the submit event worked here because it supports all the features of the <form> tag.

You can see everything and play with it in this sandbox

What are your recommendations and tips for a good component library? you can write those in the comments.

--

--

Milad Dehghan

I Develop Webapps using Javascript mostly on browsers. I worked with Javascript for the past 6+ years, and I think i'm addicted to it. https://dehghan.net