Skip to content

Trigger plugins

The five built-in triggers (hover, click, focus, viewport, idle) cover most cases. For everything else, mountly ships a small trigger plugin API and four ready-made plugins.

import {
registerTriggerPlugin,
unregisterTriggerPlugin,
getTriggerPlugin,
getAllTriggerPlugins,
createPluginTrigger,
registerBuiltInPlugins,
// Built-ins:
createSwipeTrigger,
createLongPressTrigger,
createKeyboardTrigger,
createUrlChangeTrigger,
} from "mountly";

createSwipeTrigger(element, callback, options?)

Section titled “createSwipeTrigger(element, callback, options?)”

Touch swipe gesture detection. Returns a cleanup function.

const cleanup = createSwipeTrigger(
panelElement,
() => panelFeature.activate(),
{ direction: "left", threshold: 60 }
);
OptionTypeDefaultNotes
direction"up" · "down" · "left" · "right""left"Required swipe direction.
thresholdnumber px40Minimum distance for a swipe.
velocitynumber px/ms0.3Minimum velocity.

createLongPressTrigger(element, callback, options?)

Section titled “createLongPressTrigger(element, callback, options?)”

Mouse / touch long-press. Cancels on movement past tolerance px.

const cleanup = createLongPressTrigger(
contextMenuTarget,
() => menuFeature.activate(),
{ duration: 600, tolerance: 8 }
);
OptionTypeDefaultNotes
durationnumber ms500Hold time before firing.
tolerancenumber px10Cancel if pointer moves further than this.

Single key or chord shortcut. Listens at the document level.

const cleanup = createKeyboardTrigger(
() => commandPaletteFeature.activate(),
{ key: "k", meta: true } // Cmd+K / Ctrl+K
);
OptionTypeDefaultNotes
keystringrequiredMatches event.key.
metabooleanfalseRequire Meta on macOS, Ctrl on others.
shiftbooleanfalseRequire Shift.
altbooleanfalseRequire Alt.
preventDefaultbooleantrueCall event.preventDefault() on match.

createUrlChangeTrigger(element, callback, options?)

Section titled “createUrlChangeTrigger(element, callback, options?)”

Listens for URL changes and fires when one matches.

const cleanup = createUrlChangeTrigger(
pageContainer,
() => billingFeature.activate(),
{ events: ["popstate", "pushstate"] }
);
OptionTypeDefaultNotes
events("popstate" | "hashchange" | "pushstate" | "replacestate")[]all fourWhich URL events to listen for.

A trigger plugin is an object that knows how to wire and unwire itself for an element.

interface TriggerPlugin {
name: string;
setup(
element: HTMLElement,
onTrigger: (ctx: TriggerContext) => void,
options?: Record<string, unknown>
): () => void;
}

Register with registerTriggerPlugin:

registerTriggerPlugin({
name: "double-tap",
setup(element, onTrigger, options) {
let lastTap = 0;
const handler = () => {
const now = Date.now();
if (now - lastTap < (options?.window ?? 300)) onTrigger({ element, triggerType: "programmatic" });
lastTap = now;
};
element.addEventListener("pointerup", handler);
return () => element.removeEventListener("pointerup", handler);
},
});

Then wire it via createPluginTrigger:

const cleanup = createPluginTrigger("double-tap", element, () => feature.activate(), {
window: 250,
});
getTriggerPlugin("double-tap"); // → TriggerPlugin | undefined
getAllTriggerPlugins(); // → TriggerPlugin[]
unregisterTriggerPlugin("double-tap");

Convenience to register the four shipped plugins under a known set of names. Call once if you want them discoverable via getTriggerPlugin. The standalone createSwipeTrigger etc. work without it.

  • Triggers — the conceptual overview, including the built-in five.