A virtual DOM library with focus on simplicity, modularity, powerful features and performance.
—
Snabbdom modules extend the core functionality to handle different aspects of DOM elements. Six built-in modules are provided for common use cases.
Manages HTML attributes on DOM elements with support for boolean attributes and XML namespaces.
/**
* Attributes module for managing HTML attributes
*/
const attributesModule: Module;
type Attrs = Record<string, string | number | boolean>;Usage Example:
import { init, attributesModule, h } from "snabbdom";
const patch = init([attributesModule]);
const vnode = h("input", {
attrs: {
type: "text",
placeholder: "Enter name",
required: true, // boolean attribute
disabled: false // will be removed
}
});Provides dynamic CSS class management with boolean flags for toggling classes.
/**
* Class module for managing CSS classes
*/
const classModule: Module;
type Classes = Record<string, boolean>;Usage Example:
import { init, classModule, h } from "snabbdom";
const patch = init([classModule]);
const isActive = true;
const vnode = h("div", {
class: {
active: isActive,
inactive: !isActive,
"btn-primary": true,
hidden: false // class will be removed
}
});Manages HTML5 data-* attributes through the HTMLElement.dataset property.
/**
* Dataset module for managing data-* attributes
*/
const datasetModule: Module;
type Dataset = Record<string, string>;Usage Example:
import { init, datasetModule, h } from "snabbdom";
const patch = init([datasetModule]);
const vnode = h("button", {
dataset: {
action: "save",
target: "user-form",
userId: "123"
}
});
// Results in: <button data-action="save" data-target="user-form" data-user-id="123">Manages DOM event listeners with efficient listener swapping and array-based handlers.
/**
* Event listeners module for managing DOM events
*/
const eventListenersModule: Module;
type On = {
[N in keyof HTMLElementEventMap]?:
| Listener<HTMLElementEventMap[N]>
| Array<Listener<HTMLElementEventMap[N]>>;
} & {
[event: string]: Listener<any> | Array<Listener<any>>;
};
type Listener<T> = (this: VNode, ev: T, vnode: VNode) => void;Usage Example:
import { init, eventListenersModule, h } from "snabbdom";
const patch = init([eventListenersModule]);
function handleClick(ev: MouseEvent, vnode: VNode) {
console.log("Button clicked!", ev.target);
}
function handleMouseOver(ev: MouseEvent, vnode: VNode) {
console.log("Mouse over button");
}
const vnode = h("button", {
on: {
click: handleClick,
mouseover: handleMouseOver,
keydown: [
(ev: KeyboardEvent) => console.log("Key:", ev.key),
(ev: KeyboardEvent) => console.log("Code:", ev.code)
]
}
}, "Interactive Button");Sets DOM element properties directly (not attributes) for form elements and custom properties.
/**
* Props module for managing DOM element properties
*/
const propsModule: Module;
type Props = Record<string, any>;Usage Example:
import { init, propsModule, h } from "snabbdom";
const patch = init([propsModule]);
const vnode = h("input", {
props: {
type: "checkbox",
checked: true,
value: "option1",
disabled: false
}
});
// For custom elements
const customElement = h("my-component", {
props: {
customProperty: { complex: "object" },
callback: () => console.log("callback")
}
});Manages CSS styles with support for animations, delayed properties, and removal transitions.
/**
* Style module for managing CSS styles with animation support
*/
const styleModule: Module;
type VNodeStyle = ElementStyle &
Record<string, string> & {
delayed?: ElementStyle & Record<string, string>;
remove?: ElementStyle & Record<string, string>;
destroy?: ElementStyle & Record<string, string>;
};
type ElementStyle = Partial<CSSStyleDeclaration>;Usage Examples:
import { init, styleModule, h } from "snabbdom";
const patch = init([styleModule]);
// Basic styling
const styled = h("div", {
style: {
color: "blue",
fontSize: "16px",
backgroundColor: "#f0f0f0"
}
});
// CSS custom properties (variables)
const withVariables = h("div", {
style: {
"--primary-color": "#007bff",
"--font-size": "14px",
color: "var(--primary-color)"
}
});
// Delayed properties (for entrance animations)
const animated = h("div", {
style: {
opacity: "0",
transform: "translateY(-10px)",
transition: "all 0.3s ease",
delayed: {
opacity: "1",
transform: "translateY(0)"
}
}
});
// Remove properties (for exit animations)
const fadeOut = h("div", {
style: {
opacity: "1",
transition: "opacity 0.3s ease",
remove: {
opacity: "0"
}
}
});Modules are objects that implement lifecycle hooks to extend Snabbdom functionality.
interface Module {
pre?: PreHook;
create?: CreateHook;
update?: UpdateHook;
destroy?: DestroyHook;
remove?: RemoveHook;
post?: PostHook;
}
type PreHook = () => any;
type CreateHook = (emptyVNode: VNode, vNode: VNode) => any;
type UpdateHook = (oldVNode: VNode, vNode: VNode) => any;
type DestroyHook = (vNode: VNode) => any;
type RemoveHook = (vNode: VNode, removeCallback: () => void) => any;
type PostHook = () => any;Custom Module Example:
import { Module, VNode, VNodeData } from "snabbdom";
// Custom module for logging
const logModule: Module = {
create: (emptyVnode: VNode, vnode: VNode) => {
console.log("Element created:", vnode.sel);
},
update: (oldVnode: VNode, vnode: VNode) => {
console.log("Element updated:", vnode.sel);
},
destroy: (vnode: VNode) => {
console.log("Element destroyed:", vnode.sel);
}
};
// Use the custom module
const patch = init([logModule, classModule, styleModule]);Install with Tessl CLI
npx tessl i tessl/npm-snabbdom