Getting Started

Installation

SHELL

npm install @efflore/ui-element

Your First Component

JavaScript

index.js JS

import UIElement from '@efflore/ui-element';

customElements.define('show-appreciation', class extends UIElement {
  static observedAttributes = ['count'];

  attributeMapping = { count: 'integer' };

  connectedCallback() {
    this.querySelector('button').onclick = () => {
      this.set('count', v => v + 1);
    };

    this.effect(() => {
      this.querySelector('.count').textContent = this.get('count');
    });
  }
});

Important: When using multiple components, make sure you either bundle JavaScript on the server side or reference the same external module script for UIElement from the client side!

Inter-component reactivity won't work if UIElement is a different instance in multiple modules.

CSS

index.css CSS

:root {
  /* Define neccessary CSS custom properties */
}

show-appreciation {
  display: inline-block;

  button {
    display: flex;
    flex-direction: row;
    gap: var(--space-s);
    border: 1px solid var(--color-border);
    border-radius: var(--space-xs);
    background-color: var(--color-secondary);
    color: var(--color-text);
    padding: var(--space-xs) var(--space-s);
    cursor: pointer;
    font-size: var(--font-size-m);
    line-height: var(--line-height-xs);
    transition: transform var(--transition-short) var(--easing-inout);

    &:hover {
      background-color: var(--color-secondary-hover);
    }

    &:active {
      background-color: var(--color-secondary-active);

      .emoji {
        transform: scale(1.1);
      }
    }
  }
}

HTML

Combine markup, styles and scripts:

index.html HTML

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>My First Web Compoment with UIElement</title>
    <link href="index.css" rel="stylesheet">
    <!-- more meta -->
  </head>
  <body>
    <main>
      <!-- main content -->
      <show-appreciation count="42">
        <button>
          <span class="emoji">💖</span>
          <span class="count">42</span>
        </button>
      </show-appreciation>
    </main>
    <script type="module" src="index.js"></script>
  </body>
</html>

Result

Okay, this is a very simple "Hello World" example. But you can build complex applications with simple components like this one. To understand how to unleash the magic, we have to dive a bit deeper into the core concepts behind.

What's the Magic Behind?

If most of it looks like pretty normal HTML, CSS and JavaScript to you, you are absolutly right. Because it is!

You may have noticed a few things in JavaScript, which you normally don't see:

  • a property attributeMapping in the class definition of your custom element
  • a method call this.set() in the click event handler of the button
  • a method call this.effect() in the connectedCallback() of your custom element
  • a method call this.get() in the this.effect() callback handler

These are what UIElement adds on top of a regular custom element to extend HTMLElement. The property tells UIElement what to do with your observed attributes. The methods provide reactivity.

Learn how this works ➔