📘 Introduction
A lightweight solution to bring signals-based reactivity and state management to vanilla Web Components without the need for a complex framework.
What is UIElement?
UIElement is a lightweight JavaScript library that extends the native HTMLElement class to bring efficient state management and reactivity to your Web Components without client-side rendering or the overhead of a larger framework.
- Minimalist & Lightweight: Only what you need to manage state and reactivity.
- Signals-Based Reactivity: Fine-grained updates based on state changes.
- Server-Rendered HTML Updates: Designed to work seamlessly with HTML rendered on the server, only updating what's necessary on the client side.
Why Use UIElement?
If you're looking for:
- Efficient State Management: No need for large frameworks—just manage client-side state and update HTML efficiently.
- Full Control with Web Standards: Build fully functional components with standard Web Components, no special syntax or magic.
- Fine-Grained Reactivity: Update exactly what's needed when state changes, reducing re-renders and keeping components performant.
- Flexibility to Work with Existing HTML: Update server-rendered HTML dynamically without re-rendering the entire page.
When Should You Use UIElement?
Best Use Cases:
- Enhancing Server-Rendered Pages: When you want to add interactivity to server-rendered pages without doing client-side rendering.
- Building Web Components with State: When creating custom elements that require easy state management.
- Projects Prioritizing Performance & Simplicity: When you want to maintain a simple, fast project without the need for a full JavaScript framework like React, Vue, or Angular.
Example Scenarios:
- Enhancing form interactions without reloading the page.
- Adding client-side features like counters, tabs, or toggles to a server-rendered app.
- Managing shared state between multiple components on the client.
How UIElement Works
UIElement relies on signals—small pieces of reactive state that notify your components when changes occur. This allows for efficient updates to HTML content, handling reactivity only when necessary.
Signals & Auto-Effects: Signals automatically trigger updates to the DOM when they change.
this.set('count', 0); // Define a signal for 'count'
this.first('.count').map(setText('count')); // Automatically update content when 'count' changes
Benefits of UIElement over Traditional Frameworks
- No Virtual DOM: Unlike React or Vue, UIElement updates HTML directly, avoiding unnecessary renders.
- Minimal Overhead: Since it builds on Web Components, it has minimal impact on performance and bundle size.
- Simple API: Few, clear concepts (signals, effects, context) allow developers to quickly build interactive components.
Quick Start Guide
A simple example to get started:
Count: Parity:
Source Code
HTML
<my-counter count="42">
<p>
Count: <span class="count"></span>
Parity: <span class="parity"></span>
</p>
<button id="increment">+</button>
<button id="decrement">-</button>
</my-counter>
CSS
my-counter {
display: flex;
gap: 0.5rem;
margin-block: 1rem;
p {
display: inline-block;
margin: 0;
}
span {
margin-right: 0.5rem;
}
}
JavaScript
import { UIElement, asInteger, on, setText } from '@efflore/ui-element'
class MyCounter extends UIElement {
static observedAttributes = ['count']
static attributeMap = {
count: asInteger
}
connectedCallback() {
this.set('parity', () => this.get('count') % 2 ? 'odd' : 'even')
this.first('.increment').map(on('click', () => this.set('count', v => ++v)))
this.first('.decrement').map(on('click', () => this.set('count', v => --v)))
this.first('.count').map(setText('count'))
this.first('.parity').map(setText('parity'))
}
}
MyCounter.define('my-counter')
For a full setup, see the Installation & Setup page, or jump into the Detailed Walkthrough to learn how to build your first component.
Next Steps
Continue to the Installation & Setup to get started, or dive into Core Concepts to learn more about signals and reactivity.