Using Other Libraries

This guide summarizes options to use component libraries other than the recommended Lit to implement widgets.

Choose your own web component library

There are many approaches to create web components other than Lit. While those are technically supported, you may run into unknown issues employing these.

For some possibilities, refer to this table:

ApproachKey AdvantageLibraries
HTMLElement*Minimum bundle size and no dependencies (no library needed)HTMLElement
Class/Object-basedBalance between easy development and being lightweightLit, Slim, HyperHTML, Hybrids
Hook-basedAllows using the hook-based API popularized by ReactHaunted, Atomico
CompiledLots of syntactic sugar possible due to compilation stepStencil, Svelte, Solid
Wrapped**Use known non-standard components (Vue, React/Preact)Vue3, preact-custom-element, react-to-webcomponent

* A more DIY approach, other libraries such as lit can be mixed in for features like templating

** Not recommended: Large bundle size since whole Vue/React/… runtime must be bundled

Implement the basics of a widget

When using the recommended approach, we use the LitElementWw base class like so:

import {LitElementWw} from "webwriter-lit"

export default class CoolWidget extends LitElementWw  {
  // Implementation depending on your web component approach (Lit in this example)

What does this actually provide? LitElementWw is a class saving you some boilerplate code by including useful features:

  1. Core properties as attributes: The core properties of webwriter.Widget are boolean attributes of the custom element.
  2. Rehydration: Custom elements based on LitElementWw will be set to the state of their attributes when loaded.
  3. Scoped Custom Element Registry: ScopedElementsMixin is used to avoid name collisions between two widgets using the same third-party web components. This is a technical issue with the current specification of custom elements. To put it shortly: Custom elements must be registered globally by their tag (e.g. my-button). Now, the name is taken and trying to register the element again throws an error. This makes having different versions of the same element in the same page very difficult. Essentially, this is a typical global namespace issue. You can read more about it here.

Why is this important? You need to implement these features with the web component library you want to use. (1) is usually very simple, almost any library provides this. (2) is also straightforward: Some libraries may do this automatically, otherwise, you can implement it with the connectedCallback method, which is standardized and thus available with any library. (3) is probably the most difficult. You can check the page for the solution in Lit here. This will hopefully become much easier once standardization progresses.

Unfinished section…

The minimum requirement for a widget is the HTMLElement interface. This would be an uneditable and stateless widget:

export default class CoolWidget extends HTMLElement {
  // Implementation depending on your web component approach
  • Widget is the interface widgets should support. It defines three core boolean properties that widgets may support:
  1. editable: If true, the widget should render UI elements so that authors can edit the widget. If false, no such UI elements should be rendered.
  2. printable: If true, the widget should render itself so that it may be printed easily.
  3. analyzable: Not implemented yet…