Why We Made a New Component Library Instead of Buying One
By: Alessandro Grosselle
Tags: Vuejs, JavaScript, Programming, Software Engineering, UX

We have been working on our web platform and its components for several years, from the simplest ones such as buttons to the more complex ones like accordions.

In THRON we prefer to implement our components rather than using ready-to-use solutions such as bootstrap, because we want the total control over usability and design, a very important aspect for us and our team of designers.

Over the years, we developed more than 60 components.

The problems with old components

In recent years we have focused our development activity on implementing completely new web applications (our PIM for example), all with style and design similar to the one of our DAM.

We tried to find a method to export and reuse the UX components from past applications, but after much time and several attempts, we threw in the towel:

Exporting the components was tremendously complicated; too cohesive to the monolithic solution. Older components had no complete documentation; without it, we cannot fully understand the parameters and methods. Too many compatibility issues between our Knockout.js based components and other latest and hottest technologies that we want to use for our new application.

New components objectives

In the end, we accepted the idea of completely rewriting the components that we need (not all of the past ones), and we aimed to solve the achieve the following results:

1. Include all components in a single library

We decided to collect all new components within an external library, becoming our UI toolkit for all our web projects, publishing it through the NPM repository.

Having just one library means having only one place where looking for which components have been created and which ones are missing, reducing the change to implement the same (or similar) one in different projects.

The library is built with particular attention to the performance, dividing it into different modules.

Each module may contain one or more components; It has a specific purpose and cannot exceed a specific weight (KB). If the module exceeds, it is divided into smaller modules.

As an example, we have “Basic” that collects all the components that most likely will be part of any project (e.g checkbox, button, input) and “Chart” that collects all chart components.

You can just include the group you need instead of including them avoid to include all, but only those are necessary:

// import Basic components:

import Basic from "@thron/vuecomponents/dist/modules/basic.esm";

// import Chart components:

import Basic from "@thron/vuecomponents/dist/modules/charts.esm";

Finally, thanks to NPM, we can publish different versions of our library and so, each project can decide to use any version; it is not mandatory to update.

2. Create a good documentation

Good documentation for UI components should provide a quick and exhaustive answer to the following questions:

“Does this component do exactly what I need? Has it the features I need?”

If you don’t create good documentation, the only way to answer is to read the component code and look at examples, which takes time and skills the reader might not have. It’s safe to assume developers are always time-constrained and if they cannot find a quick answer during their scouting phase you might lose the chance to reuse old code and they might fall into the trap of “It’s easier for me to write it!”

We wrote an article about our documentation tool choice, you might be interested in it.

3. Use UX components in different ecosystems

What is the best technology or library to build reusable components?

How can we use these components in all major ecosystems, from a simple web site with Jquery to a more complex single page application?

The first solution that came to mind was to use web component, a set of standard web technologies created to build complex UI elements.

These, in a very simple manner, allows us to implement a custom HTML tag and to give its logic and style.

For example, I could define the todo-list HTML tag that implements a simple to-do list:

<todo-list></todo-list>

We decided against web component

We tried web component, implemented some basic elements, but we weren’t very satisfied with the result for some limitations that were too strict for our needs:

Web component style encapsulation: Shadow DOM, is a part of its technology which avoids the collision of the style of the component with the style of the page.

It means that if within our web component we have defined that all the links have the red text; thanks to the Shadow DOM, this component style property will never be applied to the page’s link elements.

All the defined style of the web component never collide with the rest of the page!

This, which looks fantastic, has a downside:

it is impossible (or very difficult) to override the web component style from the page, such as changing link text color.

But we want to be able, from the page, by writing CSS, to change the style of the component; Shadow DOM presents itself as a limitation to achieving this.

It is important to state that, to solve the collision problem from component style, all our components have always been using BEM, a methodology which is based on creating CSS classes used only by the specific component.

It means that if within our web component we have defined that all the links have the red text; thanks to the Shadow DOM, this component style property will never be applied to the page’s link elements. All the defined style of the web component never collide with the rest of the page! This, which looks fantastic, has a downside: it is impossible (or very difficult) to override the web component style from the page, such as changing link text color. But we want to be able, from the page, by writing CSS, to change the style of the component; Shadow DOM presents itself as a limitation to achieving this. It is important to state that, to solve the collision problem from component style, all our components have always been using BEM, a methodology which is based on creating CSS classes used only by the specific component. Web component has no template engine: to make the components development process smarter, we want to use an HTML-based template engine, that allows us to bind the rendered DOM to the underlying data (from javascript) and implement some logic directly in the HTML.

Any important UI library like Vue.js or React, have its template engine; but web components don’t.

Template engine makes the HTML much easier to read and to write, greatly reducing the effort for the developer and for people that need to review the code, here is an example of a loop that renders all items of the items array:

<ul>

<li v-for="item in items">

{{item}}

</li>

</ul>

The alternative: components written in Vue.js

Vue.js (and its ecosystem) is a fantastic library for developing user interface; our new web applications are build using it.

Like all major UI libraries, it has its template engine, but, the most interesting thing about Vue.js, is that once you have implemented the component and registered it, you can embed it like a web component (between HTML tags):

<example-vue-component></example-vue-component>

This leads us to a question:

“Can we build our components using Vue.js and its template engine embedding them in a simple way, as if they were a web components?”

The answer is yes, and we did it by implementing a library that contains and registers all of our Vue.js components and exports an “embed” method to be able to include them on a webpage:

This code creates a fully functioning to-do list editor

You can test this code and see the result here.

Despite it being a Vue.js component it can easily be used in any AngularJs project:

The AngularJs application uses the Vue.js component

you can test this code here.

Including Vue.js components via a javascript method, as we did, is not the only way to embed them.

Vue.js creators implemented an automatic way to convert Vue.js components into real web components:

https://cli.vuejs.org/guide/build-targets.html#web-component

But, as written before, we prefer to not use web component for its style encapsulation property.

Keep in mind that it is not important how you will embed your Vue.js component (via method or via web component wrapper) because you can change it at any time with very low effort.

In case you are interested, we shared the library used for the previous examples here.

Buy or make?

Our library is constantly growing and we are proud to see how development times are getting shorter, both for new projects and for small customizations on our products that customers ask us to do.

We are just at the beginning, we expect to improve more and more!

We also want it to become a toolkit for our design team; it will no longer be necessary to create an entire and expensive PSD file to present the desired aesthetics of the project, but a simple mockup that will show how to fit the various pieces already created.

Using those components in the Design-Dev communication allows us to reduce errors and keep consistency over time, ensuring everyone is always on the same page in detecting when to change a component.

Another positive aspect that brought the components library is the satisfaction of ourselves, frontend developers: technically, creating our component library is challenging, measuring against other existing libraries and trying to do it better; It’s difficult but it is also fun and rewarding!

But, how much does it cost to create your library?

It costs a lot, both in terms of hours and energy.

The activities that revolve around it are many; I mention some of them:

In our workflow, to implement a new feature or an entire application, developers start from a mockup or a PSD file, understand which components could be added to the library and which are instead specific to the project. We always try to answer the question:

“Could this component also be useful in other projects? What should be the core elements of this component that are not specific of just a few use-cases?”

It is not easy to answer; often we decide it together, with a mix of “frontend devs” and the “design” team.

“Could this component also be useful in other projects? What should be the core elements of this component that are not specific of just a few use-cases?” It is not easy to answer; often we decide it together, with a mix of “frontend devs” and the “design” team. For a new component, which features do we want to introduce?

Typically we use the approach “only do what is necessary”, but it doesn’t always provide the result you expect, sometimes there are “options” that make all the difference because they solve very common pains for the developer.

Typically we use the approach “only do what is necessary”, but it doesn’t always provide the result you expect, sometimes there are “options” that make all the difference because they solve very common pains for the developer. Each new component undergoes an important review phase by our designers; this often causes continuous and “intense” comparisons that might lengthen the development process.

When does it make sense to implement your own UX component library instead of using available solutions?

We have our product with an established and bespoken design system, it is extensible and many projects need to be able to use the same style and ergonomics, for this reason, we as a company want to be able to have fine control over components behavior and optimize for the specific use cases that are part of this domain. We don’t aim to create general-purpose components.

If you don’t have a deep understanding of how your domain should drive the ergonomics of your components and, generally if you don’t care about it, we strongly suggest trying to understand if one of many existing fantastic design systems (e.g material design or ant design) or component libraries (e.g bootstrap, tailwind, materializecss) are sufficient and suitable for your projects. This will also save you huge maintenance costs over time and save a lot of security headaches (example): input components are one of the vectors for attacks.

As a rule of thumb, if you don’t have a team of UI designers who can guide you, rely on a design system!