Mode JS
Mode JS is a low-level interaction engine for the web. It belongs to the Microdom ecosystem.
It does not provide widgets, components, or behaviors. It provides a way to reason about movement, intent, and structure.
Mode JS is designed for developers who want to build interactions, not configure them.
What Mode JS is

- A low-level interaction primitive
- Pointer- and touch-aware
- Minimal by design
- Framework-agnostic
- DOM-friendly
- Data-binding ready
Mode JS helps you express how things move — not what they are.
What Mode JS is not
- A WebComponents library
- A UI framework
- A state machine
- A collection of ready-made behaviors
Those things can be built with Mode JS, but they do not belong inside it.
Install
Zero dependencies. Mode JS ships with no runtime dependencies — the whole core is a single tiny file.
npm install @microdom/mode
Builds
Each entry point ships in three formats — pick the one that matches how you load it:
| File | Format | Load with |
|---|---|---|
dist/mode.js |
ESM | import (bundlers, <script type="module">) |
dist/mode.esm.min.js |
ESM, minified | import when you want the smallest module build¹ |
dist/mode.min.js |
IIFE | classic <script> — exposes the global µ |
¹ The *.esm.min.js builds land in the next release. Remember: an IIFE (*.min.js) has no exports, so it can't be imported — use an ESM build for import, and the IIFE for a plain <script>.
Usage
Bundler / npm — resolves to the ESM build:
import µ from "@microdom/mode"
// or: import { µ } from "@microdom/mode"
Browser — classic <script> (global µ, no build step):
<script src="https://cdn.jsdelivr.net/gh/microdom/mode.js@v1.2.0/dist/mode.min.js"></script>
<script>
µ("body", { /* ... */ })
</script>
Browser — native ES module:
<script type="module">
import µ from "https://cdn.jsdelivr.net/gh/microdom/mode.js@v1.2.0/dist/mode.js"
µ("body", { /* ... */ })
</script>
Mode Move — animation extension
Animations live in a separate, optional extension chained through the same
µ(...) call, so the core stays tiny. Load it and Mode gains slide / fade /
animate / show / hide commands plus the offset / pos getters.
CDN — classic <script> (load after the core; the IIFE build self-registers on µ._ext):
<script src="https://cdn.jsdelivr.net/gh/microdom/mode.js@v1.2.0/dist/mode.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/microdom/mode.js@v1.2.0/dist/move.min.js"></script>
ES module (attach the installer to µ._ext explicitly):
// npm
import µ from "@microdom/mode"
import install from "@microdom/mode/move"
µ._ext = install
// …or straight from the CDN
import µ from "https://cdn.jsdelivr.net/gh/microdom/mode.js@v1.2.0/dist/mode.js"
import install from "https://cdn.jsdelivr.net/gh/microdom/mode.js@v1.2.0/dist/move.js"
µ._ext = install
Usage
µ("#panel", { slideUp: { t: 300 } })
µ("#panel", { fadeIn: { t: 200, fn: () => console.log("done") } })
µ("#box", { animate: { props: { width: 400 }, t: 500, easing: "easeOut" } })
µ("#box", { stop: {} }) // cancel running animation
const off = µ("#box", { offset: null }) // → { top, left }
Migrating from ./movedom
The extension was formerly published as @microdom/mode/movedom. That subpath
still works as a deprecated alias — it resolves to the exact same files as
@microdom/mode/move — and will be removed in v2.0. Update your import:
- import install from "@microdom/mode/movedom"
+ import install from "@microdom/mode/move"
Why Mode JS exists
Most interaction libraries:
- abstract too early
- hide intent behind state
- grow uncontrollably
- break at the edges (touch, empty states, nested structures)
Mode JS takes a different approach:
Movement first.
Intent is explicit.
Structure matters more than features.
Why not X?
Modern UI stacks often require tens of kilobytes of code to express a simple interaction.
Mode JS asks a different question:
How much code do you actually need
to make something feel right?
A complete multi-list sortable with touch support
can be built in **~6 KB total**.
Read the full comparison indocs/why-not-x.md.
Code weight in perspective
Characters Team Cherry

The little one can rule the town.
Repository structure
If you’re looking for examples, start in /demos.
If you’re looking for ideas, start in /docs.
Demos
- Sortable (multi-list + touch)
A complete sortable interaction built with ~6 KB of code. Demonstrates intent gating, empty container handling, and cross-list movement.
Each demo is intentionally self-contained. They are not plugins — they are proofs of thought.
Philosophy
Mode JS is opinionated:
“If an interaction cannot be expressed simply, the abstraction is probably wrong.”
Read more in docs/philosophy.md.
License
MIT