Create custom, distributable web components with VueJS

Published on – 4 minute read

I am currently in the middle of working on a new BotMan feature - a frontend widget that you can embed into your website to make it easier to connect your website visitors with your own self-hosted chatbot solution. The backend / PHP side is already working and leverages the BotMan web driver, which is basically just an API that you can use to interact with your chatbot.

As the widget solution should work in as many different scenarios as possible, I was thinking about how I can implement this feature. I want an embeddable piece of HTML, CSS and Javascript that other people can just pull into their websites.

The default layout might look something like this - but things like the colors, headline or the onboarding screen should be configurable. The most common approach would probably be, to create a Javascript object that accepts an options object that can be extended by the user:

let BotManWidget = new BotManWidget({
  headline: 'BotMan Widget',
  color: '#e84423'
});

While this approach is perfectly fine, I feel like this is not very semantic. The configuration is not on the DOM element. And how do we deal with larger HTML snippets, like the onboarding screen? You know what would be cool? If we could create a custom HTML element that other people can use on their website... Wait a minute!

Web Components - Hooray!

There is a complete [W3C specification] that takes care of the so called "web components". A web component is basically just a custom HTML tag that you can embed into your website - think of it like Vue components (just slightly less powerful).

Or to quote the webcomponents.org website:

Web components are a set of web platform APIs that allow you to create new custom, reusable, encapsulated HTML tags to use in web pages and web apps. Custom components and widgets build on the Web Component standards, will work across modern browsers, and can be used with any JavaScript library or framework that works with HTML.

Wow - that sounds nice, right? Well, the bad news is, that web components are not there yet.

This is the result of the Can I Use results for the web components specifications.

Vue JS Custom Elements

Luckily enough, there is already a very nice open source repository that allows to create custom HTML elements with VueJS. And by using a polyfill, they even work in the beloved IE9.

So what is going to change? This allows me to create an embeddable widget that has the full VueJS power!

<botman-widget api-endpoint="/botman/" color="#e84423" headline="BotMan Widget" />

Isn't this easier to understand?

In addition to custom properties for our element, we can also make use of a very useful VueJS feature called Slots. Slots allow us to place static content inside our custom VueJS widget - from the outside.

So if we want to modify the HTML of the onboarding screen, just add it as a slot inside your widget element:

<botman-widget api-endpoint="/botman/" color="#e84423">
  <div vue-slot="onboarding" class="text-center text-white mt-8">
    Custom div goes here<br>
    <a data-botman-action="finishOnboarding">Finish Onboarding</a>
  </div>
</botman-widget>

This not only gives semantics back to the HTML element, but it makes our development life a lot easier, as we can use the custom widget as if it would be a regular HTML element on our website.

Where to go from here?

I really think that the VueJS Custom Element package is great - especially if you want to inject your custom VueJS component into websites that are not under your control - so you don't know if they are using VueJS at all.