Skip to main content

Overlays & Events

Overlays and the presenter console communicate through a central, typed event bus.

Overlays​

Overlays attach interactive UI widgets over the stage canvas (such as laser pointers, drawing tools, and navigation buttons):

import { Stage, NavigationOverlay, LaserPointer, Annotation } from "stageroutine";

const stage = new Stage();
stage.overlay(LaserPointer());
stage.overlay(Annotation());
stage.overlay(NavigationOverlay());

Built-in Overlays​

  • LaserPointer(): WebGL glowing red laser pointer.
  • Annotation(): Smooth variable-width ink drawn over slides. The ink color follows the active theme primary color.
  • NavigationOverlay(): With a mouse, hover within the bottom 100 CSS pixels to show navigation controls. Move away to hide them. On touch, tap the bottom zone to show controls and tap outside the controls to dismiss them. Escape also dismisses them.

With NavigationOverlay(), swipe left for the next step or right for the previous step. Interactive and scrollable content keeps its own gestures. Add data-prevent-swipe to custom interactive content to exclude it. Pointer controls are hidden on touch-only devices.

The Presenter Pointer Tool​

LaserPointer() and Annotation() share one tool state. Toggle it with P or Escape. While the tool is active, moving shows the laser beam and press-and-drag draws ink. The tools are implemented separately but activate together, so there is no separate draw mode.

KeyAction
PToggle the pointer tool
CClear annotations (150ms dissolve)
Cmd/Ctrl+Z or ZUndo last stroke
Cmd/Ctrl+Shift+Z or Shift+ZRedo stroke
EscapeExit the pointer tool

Event System​

All communication between the stage, overlays, keyboard shortcuts, and the presenter console flows through a single typed event bus using req: (requests) and evt: (notifications):

DomainRequests (req:*)Notifications (evt:*)
nav:req:nav:nextStep, req:nav:prevStep, req:nav:nextScene, req:nav:prevScene, req:nav:gotoStep, req:nav:gotoSceneevt:nav:stepChanged, evt:nav:sceneChanged
stage:req:stage:requestStateevt:stage:resized, evt:stage:stateChanged
pointer:req:pointer:setStateevt:pointer:stateChanged

Listening and Emitting​

// Listen for navigation step changes
stage.on("evt:nav:stepChanged", ({ index, total, scene }) => {
console.log(`Step ${index + 1} of ${total} (${scene})`);
});

// Emit navigation requests programmatically
stage.emit("req:nav:nextStep");

// Toggle pointer mode
stage.emit("req:pointer:setState", { active: true });

Dual-Screen BroadcastChannel​

The event bus transparently bridges across browser windows using the browser's native BroadcastChannel. Opening presenter.html on a second display immediately connects to the stage without network sockets or servers.