Plain Web
Selected Lathe components in ordinary HTML, CSS and JavaScript. Copy the source, use browser modules, or download a complete working example.
Available components
Open a component and choose HTML / CSS / JS beside its React preview. Each format has a working example and source.
| Component | Initializer | Options |
|---|---|---|
| Precision Scrub Field | createPrecisionScrubField | value, defaultValue, min, max, step, units, disabled, onValueChange, onValueCommit |
| Animated Number | createAnimatedNumber | value, duration (ms), format |
| Image Compare | createImageCompare | value (0–100), disabled, onValueChange |
| Line Draw | createLineDraw | duration (ms), stagger (ms) |
| Marquee | createMarquee | speed (px/s), paused |
Complex overlays, data editing and assemblies currently use React. Plain-web support expands component by component.
Use browser modules
Save lathe-web.js, interaction-math.js and lathe-web.css beside your page. Keep both JavaScript files in the same directory. Copy the markup from the component's example.
<link rel="stylesheet" href="./lathe-web.css">
<script type="module">
import { createImageCompare } from "./lathe-web.js"
const comparison = createImageCompare(document.querySelector("[data-component]"), { value: 50 })
// comparison.update({ value: 75 })
// comparison.destroy() before removing or reinitializing the component.
</script>Browser modules need an HTTP server. The Download working HTML link produces one self-contained file with embedded CSS, JavaScript and demo images that also opens offline.
Lifecycle and state
- Initialize each root once. Initializers return update(options) and destroy(). After destruction, updates do nothing; create a new controller to initialize again.
- update() merges options. Keep application state in your own code and use change/commit callbacks when a control exposes them. Programmatic updates do not emit user-change callbacks.
- destroy() removes the initializer's listeners, observers and active animations. It does not remove your HTML or event listeners that you add in application code.
- Pass individual DOM roots so multiple instances can coexist. Use unique input ids and matching labels in your markup.
- Keep visible labels and native inputs. Reduced-motion preferences stop decorative drawing and counting; marquee motion also has an explicit pause control.
Use your theme
The stylesheet includes Lathe's generated color tokens and follows the device's dark-mode preference. Override the semantic CSS variables to match your site. No Tailwind compiler or React runtime is needed.
:root {
--radius: 0.5rem;
/* Override --background, --foreground, --primary and other semantic tokens. */
}The animation runtime
Lathe's existing animate() API is also available as a standalone JavaScript module. It is built from the same TypeScript implementation used by the Animation Lab.
import { animate } from "./animate.js"
const animation = animate(".target", {
to: { x: 120, rotate: 90 },
curve: { type: "spring", stiffness: 180, damping: 16 },
})
// animation.cancel() during teardown.Source and downloads
The plain-web manifest lists previews, offline downloads and source JSON for every supported component. React components remain available through the shadcn registry. Precision scrubbing shares its numeric calculations across both formats.
Download example markup uses sample images; replace them and their alternative text with your own assets. format, validation and application callbacks remain your code.