Triggers
A trigger is the signal that moves a feature between states. mountly ships seven built-in trigger modes in attach() and lets you register more as plugins.
You rarely call the trigger setup directly. You describe intent through feature.attach({ preloadOn, activateOn }) and the runtime wires the right listeners for you.
Built-in trigger modes
Section titled “Built-in trigger modes”Preloads on mouseenter, mounts on click. The default for discoverable controls: buttons, menu items, link previews. The 100 ms delay before fire suppresses fly-over hovers. If the user leaves before the delay elapses, mountly cancels the load.
feature.attach({ trigger: btn, preloadOn: "hover", activateOn: "click" });Mounts on click without preloading. Use when intent is committed rather than exploratory: modal openers, save buttons, anything where you’d rather pay the load cost on click than on every passing hover.
feature.attach({ trigger: btn, preloadOn: false, activateOn: "click" });Preloads on focus, mounts on commit. The keyboard counterpart to hover. Pair both so mouse and keyboard users get parity.
feature.attach({ trigger: input, preloadOn: "hover", activateOn: "focus" });viewport
Section titled “viewport”Mounts when the trigger element enters the viewport. Backed by IntersectionObserver with a configurable threshold (default 0.1). The default for below-the-fold widgets: analytics dashboards, embedded media, anything the user might never scroll to.
feature.attach({ trigger: section, preloadOn: "viewport", activateOn: "viewport" });Uses requestIdleCallback to preload during quiet moments. Reach for it rarely, since every idle preload is bytes the user might never need. Pair with predictive prefetch for the smarter version that scores against interaction history.
feature.attach({ trigger: el, preloadOn: "idle", activateOn: "click" });You can also mount on idle directly (Astro-like client:idle behavior):
feature.attach({ trigger: el, preloadOn: false, activateOn: "idle", idleTimeout: 500 });Mounts when a CSS media query matches (Astro-like client:media).
feature.attach({ trigger: el, preloadOn: false, activateOn: "media", activateOnMediaQuery: "(max-width: 50em)",});url-change
Section titled “url-change”Mounts when the URL matches a pattern. Listens to popstate, hashchange, and (via patched method) pushState / replaceState. Useful for route-driven content in non-SPA hosts.
feature.attach({ trigger: container, activateOn: "url-change", activateOnUrlEvents: ["popstate", "pushstate"],});Combining preload and activate
Section titled “Combining preload and activate”The two stages are independent. You can preload aggressively but mount conservatively, or vice versa.
| Goal | preloadOn |
activateOn |
|---|---|---|
| Discoverable button | "hover" |
"click" |
| Form-only action | "hover" |
"focus" |
| Below-fold reveal | "viewport" |
"viewport" |
| Below-fold with early wakeup | "viewport" + viewportRootMargin: "200px" |
"viewport" |
| Below-fold but only after explicit interest | "viewport" |
"click" |
| Route-driven panel | "idle" |
"url-change" |
| Responsive-only widget | false |
"media" |
| Idle auto-mount | false |
"idle" |
| Fully imperative | false |
(you call feature.mount yourself) |
The toggle flag
Section titled “The toggle flag”By default attach() toggles: a second activateOn event unmounts the feature. Set toggle: false for one-way mount.
feature.attach({ trigger: btn, activateOn: "click", toggle: false });Cancellation
Section titled “Cancellation”Hover, focus, and idle all cancel automatically if the user backs out before the delay fires (mouseleave, blur, idle slot withdrawn). Once a request is in flight, you can abort it manually:
feature.abort();// state → "aborted", any in-flight load DOMException("AbortError")sCustom triggers via plugins
Section titled “Custom triggers via plugins”Anything not covered by the built-ins can be added as a plugin. Three are provided out of the box:
createSwipeTriggerfor touch swipe gestures.createLongPressTriggerfor touch / mouse long-press.createKeyboardTriggerfor single keys or chord shortcuts.
See Trigger plugins for the full API and how to register your own.
When the trigger isn’t a DOM event
Section titled “When the trigger isn’t a DOM event”Skip attach() entirely and drive the feature programmatically:
await feature.preload(); // start the load when you wantawait feature.activate(); // commit once data is readyconst handle = await feature.mount(container, context, props);// later:handle.unmount();Use this when the host owns timing (route changes, server-driven flags, wizard steps, batch operations).
Astro parity scope
Section titled “Astro parity scope”mountly can match Astro’s client-side timing directives (load, idle, visible, media) at runtime.
It does not implement Astro compile-time/server directives (client:only, server:defer, set:html, is:inline, etc.), which belong to Astro’s compiler/runtime model.