Skip to content

Custom Elements

Quantum is part of the DNA project and its design is largely connected to Custom Elements.

Quantum interface is similar to the Shadow DOM, in that it aims to offer the same developer experience but with a different technology.

Define an element

In the example below, we define a custom element that uses a realm to render its internal template. We are going to use µhtml to render the template, but you can use any other view library.

ts
import { attachRealm } from '@chialab/quantum';
import { html, render } from 'uhtml';

export class MyElement extends HTMLComponent {
    readonly realm = attachRealm(this);

    connectedCallback() {
        this.realm.observe(() => {
            // render internal template
            render(this.realm.root, html`<div class="my-element__wrapper"> ${this.realm.childNodes} </div>`);
        });
    }
}

customElements.define('my-element', MyElement);

TIP

Shadow DOM encapsulates styles, but Quantum does not. This is because Quantum render nodes in the light DOM, so you need a good styling strategy like CSS-in-JS or BEM to avoid collisions.

Customized built-in elements

Differently from Shadow DOM, we can use Quantum with built-in elements such as <button>, <a> and <ul>:

ts
import { render, html } from 'uhtml';
import { attachRealm } from '@chialab/quantum';

export class MyButton extends HTMLButtonElement {
    readonly realm = attachRealm(this);
    icon = 'home';

    connectedCallback() {
        this.realm.observe(() => {
            // render internal template
            render(this.realm.root, html`
                <i class="button__icon">${this.icon}</i>
                <span class="button__label">${this.realm.childNodes}</span>
            `));
        });
    }
}

customElements.define('my-button', MyButton, {
    extends: 'button',
});

Released under the MIT License.