Skip to content

Custom Elements

Most of the time, you’ll use named element functions like div(), button(), and input(). But when you need a tag that isn’t in the standard set — a web component, an SVG element, or a custom tag — use h().

h() creates any HTML element by tag name:

import { h } from "@whisq/core";
// Standard element (same as using div())
h("div", { class: "card" }, "Hello");
// Web component
h("my-dropdown", { value: "option1" },
h("my-option", { value: "option1" }, "Option 1"),
h("my-option", { value: "option2" }, "Option 2"),
);
// Custom element
h("app-header", { class: "main-header" },
h("app-logo"),
h("app-nav"),
);

Whisq works with any web component registered via customElements.define():

import { h, signal, mount } from "@whisq/core";
// Assume a <color-picker> web component is registered
const selectedColor = signal("#4f46e5");
mount(
h("color-picker", {
value: () => selectedColor.value,
onchange: (e) => selectedColor.value = e.target.value,
}),
document.getElementById("app")!,
);

Reactive props and event handlers work the same way as with built-in elements.

Use h() for SVG elements that aren’t covered by the standard element functions:

import { h } from "@whisq/core";
const icon = h("svg", { viewBox: "0 0 24 24", width: "24", height: "24" },
h("circle", { cx: "12", cy: "12", r: "10", fill: "none", stroke: "currentColor" }),
h("path", { d: "M12 6v6l4 2", stroke: "currentColor", fill: "none" }),
);

Create a typed wrapper around a web component for better ergonomics:

import { h } from "@whisq/core";
interface DatePickerProps {
value?: () => string;
onchange?: (e: Event) => void;
min?: string;
max?: string;
}
function DatePicker(props: DatePickerProps, ...children: any[]) {
return h("date-picker", props, ...children);
}
// Now use it like a native Whisq element
DatePicker({
value: () => selectedDate.value,
onchange: (e) => selectedDate.value = e.target.value,
min: "2024-01-01",
});
Use caseApproach
Standard HTML (div, button, input)Named functions — div(), button()
Web components (my-component)h("my-component", ...)
SVG elements (circle, path)h("circle", ...)
Dynamic tag namesh(tagName, ...)