Lit
A custom element built with elements-kit is just class extends HTMLElement registered via customElements.define. Lit renders it fine in html template literals — no configuration needed. Because Lit uses tagged templates rather than JSX, there is no IntrinsicElements to augment. The main integration point is getting typed element references in @query decorators and this.renderRoot.querySelector calls.
// shared element — built once, used anywhereimport { defineElement } from "elements-kit/custom-elements";import { reactive } from "elements-kit/signals";
export class XCounter extends HTMLElement { @reactive() count = 0;}
defineElement("x-counter", XCounter);Source the prop shape from the class
Two helpers exported from elements-kit/jsx-runtime:
| Helper | Shape | Use when |
|---|---|---|
InstanceProps<I> | Public instance fields only (drops the HTMLElement surface) | Annotating setters, wrapper props, or helper functions |
ElementProps<C> | Full elements-kit JSX surface — attrs, fields, events from static events, slots from [SLOTS], children | When you need the full declared surface |
Typed element queries
Augmenting HTMLElementTagNameMap narrows the return type of @query, this.renderRoot.querySelector, and document.querySelector:
import { defineElement } from "elements-kit/custom-elements";import { reactive } from "elements-kit/signals";
export class XCounter extends HTMLElement { @reactive() count = 0;}
defineElement("x-counter", XCounter);
declare global { interface HTMLElementTagNameMap { "x-counter": XCounter; }}Inside a Lit host element:
import { LitElement, html } from "lit";import { customElement, query } from "lit/decorators.js";import "./x-counter"; // brings in the HTMLElementTagNameMap augmentation
@customElement("my-host")export class MyHost extends LitElement { // @query narrows to XCounter because of HTMLElementTagNameMap @query("x-counter") counter!: XCounter;
render() { return html`<x-counter></x-counter>`; }
updated() { this.counter.count = 10; // typed }}InstanceProps as a type annotation
InstanceProps<I> is useful when you need to describe the settable surface of an elements-kit element — for example, inside a factory or test helper:
import type { InstanceProps } from "elements-kit/jsx-runtime";import { XCounter } from "./x-counter";
function applyProps(el: XCounter, props: InstanceProps<XCounter>) { Object.assign(el, props);}