Skip to content

domkit

@johnhenry/domkit is a set of custom elements and DOM utilities for people writing HTML without a build step. Add one <script> tag, write the element, and it behaves like a native one: attributes, properties, events, forms, hidden, keyboard, and accessibility all work the way they do for built-in elements. Each is tested in Chromium, Firefox, and WebKit.

<script type="module" src="https://esm.sh/@johnhenry/domkit/tabbed-ui/global.mjs"></script>
<tabbed-ui>
<div><button>One</button><button>Two</button></div>
<section>First panel</section>
<section>Second panel</section>
</tabbed-ui>

New here? Start with Getting started, then browse the Recipes. The Reference lists every attribute, property, and event, and Principles explains the contract every element keeps.

No install is needed: every module loads from a CDN as https://esm.sh/@johnhenry/domkit/<module>/global.mjs. With npm:

Terminal window
npm install @johnhenry/domkit

Latest on npm: @johnhenry/[email protected].

No CDN snippet yet. Source ESM. These docs describe domkit 0.1.0, whose module layout differs from the 0.0.4 on npm, so no CDN snippet is generated until 0.1.0 is published.

import "@johnhenry/domkit/tabbed-ui/global.mjs"; // registers <tabbed-ui>
import TabbedUI from "@johnhenry/domkit/tabbed-ui"; // or just the class

domkit has no dependencies, so no import map is needed. It ships TypeScript declarations, a custom-elements.json manifest (which also says which module registers each tag, so page builders can load just the elements a page uses), and VS Code autocomplete data (vscode.html-custom-data.json).

Element What it’s for
<tabbed-ui> Accessible tabs from plain children
<stylable-select> A listbox you can fully style, with a native <select>’s API, forms, and keyboard
<infinite-combo-box> Autocomplete: filters its own options, or searches a URL or function as you type, paging in more results as you scroll
<swipe-input> Swipe gestures that send invoker commands, one per direction (to commandfor, or bubbling up to the element it’s inside)
<gamepad-input> Game controller buttons that send invoker commands (to commandfor, or bubbling up to the element it’s inside)
<hot-key> Keyboard shortcuts that toggle a native <dialog> or popover, or run any invoker command (to commandfor, or bubbling up to the element it’s inside)
<drill-menu> A list that drills into sub-screens and back, optionally synced to the URL
<code-color> Syntax highlighting that never changes your markup
Element What it’s for
<query-container> Change the element that wraps content (ul → ol) by media query, or by its container’s size
<attribute-provider> Add classes, styles, and attributes to children by media or container query, and restore them
Element What it’s for
<attribute-cycler> Theme and density switches: buttons that cycle a persisted class or attribute, synced across tabs
<define-component> Register a custom element in HTML, from a module’s export or from a <template>
<polyfill-window> Load a module onto window unless it’s already there
<frame-timer> A clock: steady tick events with play()/pause()

live-query-selector, delay (milliseconds, or one frame at a given fps), clamp, until-window-load, hydratable and mounts (app bootstrap), and the localstorage-cycler engine behind <attribute-cycler>.

Plots (<scatter-plot>, now <data-plot>) and <chernoff-face> moved to their own package: see data-plot.

Element What it’s for
<draw-svg> SVG strokes that draw themselves in, CSP-safe and reduced-motion aware

<pixel-canvas>, <pixel-sprite>, and the pixel effects moved to their own package: see canvas-fx.

Every module follows semver from 0.1.0: while the version is 0.x, breaking changes only land in a minor release, and are always listed in the changelog. The repo’s live gallery (demo/) runs every module, and examples/ holds the recipes.

  • domable converts between HTML text, DOM nodes, and React-element-shaped objects. domkit used to depend on it, and is now dependency-free.

github.com/johnhenry/domkit · MIT