Looking for the current Rivet documentation? View the v1 site.

Vanilla JavaScript Components

This RFC proposes a fundamentally new strategy for the way Rivet JavaScript is written

Chat icon Comment on this document

Log in to GitHub to comment on this RFC.


This RFC proposes a fundamentally new strategy for the way Rivet JavaScript is written that will hopefully solve some of the recurring issues we’ve seen with the way the Rivet 1.x.x JavaScript was originally written. By Vanilla JavaScript components here we mean JavaScript components that:

  • are written in plain JavaScript and that don’t depend on UI libraries like React, Vue, etc., but that can work alongside those libraries if needed.
  • are written as ES6 modules and are distributed as a bundle usable with modern build tools (Webpack, Rollup, etc.), or in a <script> tag as a browser bundle.
  • provide developer conveniences found in other UI component-based models e.g. callback functions and custom events that can be used as hooks to extend functionality


The original design of the Rivet JavaScript components/widgets was focused on ease of use. The goal was to make it so that if developers dropped the script into their page and added the correct markup then everything would just work. After the initial release it soon became obvious that developers needed/wanted to be able to use Rivet’s JavaScript components along side other libraries and control them via their own scripts. Rivet’s original set of JavaScript widgets failed pretty noticeably at this.

While they were mostly rewritten in the 1.1.0 release to help fix some of these issues, there are still many areas where they fall short when trying to use them alongside other scripts—especially in situations where the DOM is changing and updating without a full page refresh as is common in most single page applications. This proposal outlines a new strategy for writing Rivet JavaScript components that will bring a number of the following benefits.

  • More resilient and predictable functionality in browser environments where the component doesn’t have any kind of exclusive knowledge of the DOM. For example, where DOM nodes are added after initial page load, or where the DOM is built by another JS library.
  • The ability to create multiple instances of any component e.g. const myDropdownInstance = new Dropdown(), allowing components to maintain their own state (if needed) and developers to have access to life-cycle methods for each instance, e.g. myDropdownInstance.destroy(), myDropdownInstance.init()
  • The ability to pass event-based callback functions as options to the instance:
    const myDropdownInstance = new Dropdown(element, {
      onOpen: function onOpenCallback() {
        // Do stuff when dropdown opens
  • More modularity and flexibility so that developers can use components however they like. We can ship a bundle of ES6 modules that developers can import on a component-by-component basis if they are using module bundlers like Webpack, Rollup, etc. For example, import Dropdown from 'rivet-components';. We can also ship a browser bundle that developers can use in a normal script tag e.g. <script src="./path/to/rivet-components.js"></script>.

Read more in the full RFC text.

Chat icon Comment on this document

Log in to GitHub to comment on this RFC.