martian-ui: The Game Engine Hiding in the DOM: Inside Martian UI
How Cheng Lou’s experimental toolkit abandons declarative state for continuous physics, treating the browser like a low-level rendering target.
- Martian UI rejects the declarative, event-driven paradigm in favor of a continuous, frame-based scheduler akin to a game engine.
- By decoupling the physical simulation clock from the monitor's refresh rate, it ensures deterministic animations across 60Hz and 120Hz displays.
- The project serves as a forensic textbook of browser quirks, documenting the undocumented workarounds required for Apple-grade UI fidelity.
- It actively opposes opaque UI abstractions, demanding that raw physics variables like velocity remain exposed to the developer.
The web has spent a decade perfecting the reactive paradigm. State A transitions to State B, and the framework figures out the rest. But for developers chasing the frictionless, sub-pixel perfection of native macOS or iOS interfaces, this declarative playbook often feels like driving a sports car through molasses. Martian UI, an experimental toolkit authored by React Motion creator Cheng Lou, throws out the declarative playbook entirely.
It reveals a slightly uncomfortable truth: to achieve true, uncompromised fidelity, you must treat the browser not as a document viewer, but as a low-level input stream and rendering target. It is a continuous simulation, a “game loop” for the web, and a forensic textbook of invisible browser quirks.
The Death of the Event Listener
In a standard web application, logic fires directly inside an `onClick` or `mousemove` callback. When a user interacts rapidly, or when multiple inputs collide in a single 8ms window, the resulting state updates often conflict, leading to dropped frames or jittery animations. Martian UI’s core engine, located in `src/core.ts`, addresses this by fundamentally changing how inputs are handled via the `makeScheduler` function.
Instead of executing logic immediately, the scheduler decouples the input from the render cycle. It buffers all incoming events—clicks, touches, keystrokes—into a queue and processes them holistically during a single `requestAnimationFrame` (rAF) loop. This allows the system to resolve conflicting inputs before anything hits the screen, ensuring that a frantic user interaction doesn't tear the UI apart.
Decoupling the Physical Clock
A persistent headache in web animation is the hardware clock. Animations tied directly to `requestAnimationFrame` behave differently on a 60Hz monitor than they do on a 120Hz ProMotion display. Martian UI’s physics engine, `src/spring.ts`, solves this by severing the link between the physical simulation and the logical render clock.
The engine runs multiple simulation steps per frame if necessary, defined by `msPerAnimationStep = 6`. This means that regardless of the monitor's refresh rate, the physics simulation—governed by stiffness (`k`) and damping (`b`)—remains perfectly deterministic. The UI moves exactly as intended, every single time, everywhere.
UI Engineering as Forensics
Building high-fidelity UI requires fighting decades of browser cruft. Martian UI’s `docs/` folder acts as a living textbook of this battle. It details the undocumented quirks that separate a good interface from a great one: how Chrome and Safari round `scrollTop` differently, or why pointer events silently fail on certain Android devices.
This repository frames UI excellence as an act of archeology. It’s not just about writing clean TypeScript; it’s about understanding the deep, often contradictory behaviors of the underlying rendering engines.
The Anti-Abstraction Mandate
The modern component library ecosystem—tools like shadcn/ui or Mantine—prioritizes developer velocity. They wrap complex behaviors in opaque, batteries-included abstractions. Martian UI takes the exact opposite approach.
In Martian UI, abstractions that hide physics are considered harmful. The library actively exposes raw variables like velocity (`v`). If you want to build complex, interruptible gestures where one animation seamlessly feeds into another, you cannot have the physics engine hidden behind a black box. You need access to the raw math.
| Feature | Declarative Paradigm (e.g., Mantine) | Continuous Paradigm (Martian UI) |
|---|---|---|
| State Handling | Immutable, discrete state updates | Mutable, continuous state simulation |
| Event Processing | Inline callbacks (onClick) | Buffered, frame-based scheduler |
| Animation | Opaque CSS/JS wrappers | Exposed raw velocity vectors (v) |
| Target Audience | Product engineers optimizing for speed | UI engineers optimizing for absolute fidelity |