Skip to content
Ilha
Esc
↑↓navigate↵open⌘Jpreview

Custom elements

Register a component as a custom element in a few lines.

You register a component as a custom element with mount(). Copy this helper into your app:

import { const mount: (el: Element, fn: Component, opts?: MountOptions) => (() => void)mount } from "ilha";
import type { type Component = (() => View | undefined | Promise<View | undefined>) | GeneratorFnComponent } from "ilha";

/** Mount `component` in every `<name>` element; hydrate when it has `data-ilha`. */
export const const define: (name: string, component: Component) => void
Mount `component` in every `<name>` element; hydrate when it has `data-ilha`.
define
= (name: stringname: string, component: Componentcomponent: type Component = (() => View | undefined | Promise<View | undefined>) | GeneratorFnComponent): void => {
var customElements: CustomElementRegistry
The **`customElements`** read-only property of the Window interface returns a reference to the CustomElementRegistry object, which can be used to register new custom elements and get information about previously registered custom elements. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/customElements)
customElements
.CustomElementRegistry.define(name: string, constructor: CustomElementConstructor, options?: ElementDefinitionOptions): void
The **`define()`** method of the CustomElementRegistry interface adds a definition for a custom element to the custom element registry, mapping its name to the constructor which will be used to create it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/CustomElementRegistry/define)
define
(
name: stringname, class extends
var HTMLElement: {
    new (): HTMLElement;
    prototype: HTMLElement;
}
The **`HTMLElement`** interface represents any HTML element. Some elements directly implement this interface, while others implement it via an interface that inherits it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement)
HTMLElement
{
#unmount: (() => void) | undefined; function (Anonymous class).connectedCallback(): voidconnectedCallback(): void { this.#unmount = function mount(el: Element, fn: Component, opts?: MountOptions): (() => void)mount(this, component: Componentcomponent, { MountOptions.hydrate?: boolean | undefinedhydrate: this.Element.matches(selectors: string): boolean (+3 overloads)
The **`matches()`** method of the Element interface tests whether the element would be selected by the specified CSS selector. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/matches)
matches
("[data-ilha]"),
}); } function (Anonymous class).disconnectedCallback(): voiddisconnectedCallback(): void { this.#unmount?.(); this.#unmount = var undefinedundefined; } } ); };

Then register components with it:

import { const atom: AtomFnatom } from "ilha";
import { const define: (name: string, component: Component) => voiddefine } from "./define";

function define(name: string, component: Component): voiddefine("ilha-counter", () => {
  const const count: AtomHandle<number>count = atom<number>(init: number | Atom<number>, options?: AtomOptions<number> | undefined): AtomHandle<number> (+1 overload)
An existing Effect atom, or a plain value. Store a function with `atom.lazy(() => fn)`; the `ilha/oxlint` rule `function-in-atom` flags `atom(fn)`.
atom
(0);
return ( <JSX.IntrinsicElements.button: ButtonHTMLAttributesbutton type?: string | undefinedtype="button" EventProps<HTMLButtonElement>.onclick?: ((event: Targeted<HTMLButtonElement, MouseEvent>) => void) | undefinedonclick={() => const count: AtomHandle<number>count.AtomHandle<number>.update: (f: (current: number) => number) => voidupdate((n: numbern) => n: numbern + 1)}> {const count: AtomHandle<number>count} </JSX.IntrinsicElements.button: ButtonHTMLAttributesbutton> ); });
<ilha-counter></ilha-counter>

Connecting the element mounts the component; disconnecting unmounts it. Add data-ilha to a server-rendered element to hydrate its markup.

Was this page helpful?