Skip to content

Coordinators API

API Reference: Engine · Types · Storage · Events · Security · Servers · Placement · Lightbox · Lens · Embeds · This Page · Config Registry

Two coordinators manage how renderers interact: one orchestrates transitions between renderer types (menu, lightbox, lens), the other ensures only one instance of a type is open at a time.

RendererCoordinator

Orchestrates transitions between renderers. Manages a state stack so back() restores the previous renderer. Uses the View Transitions API for smooth animations when available.

typescript
import { RendererCoordinator } from 'alap';

const coordinator = new RendererCoordinator();
coordinator.register(menu);
coordinator.register(lightbox);
coordinator.register(lens);
coordinator.bindKeyboard();

Constructor

typescript
new RendererCoordinator(options?: RendererCoordinatorOptions)
OptionTypeDefaultDescription
reduceMotionbooleantrueRespect prefers-reduced-motion
viewTransitionsbooleantrueUse View Transitions API when available

Methods

MethodSignatureDescription
register()(renderer: CoordinatedRenderer) => voidRegister a renderer
unregister()(type: RendererType) => voidUnregister a renderer by type
transitionTo()(target: RendererType, payload: OpenPayload) => voidTransition to target, pushing current state onto stack
back()() => voidGo back one step, or close all if stack is empty
closeAll()() => voidClose everything and clear the stack
bindKeyboard()() => voidBind capture-phase Escape handler for back()
unbindKeyboard()() => voidRemove keyboard listener
destroy()() => voidFull cleanup: close all, unbind keyboard, clear registrations

State queries

Property / MethodTypeDescription
depthnumberCurrent stack depth (read-only)
isTransitioningbooleanWhether a transition is in progress (read-only)
hasOpenRenderer()booleanWhether any registered renderer is currently open

View Transitions

When the View Transitions API is available and not disabled:

  • Outgoing and incoming content gets viewTransitionName for shared-element animation
  • Back navigation adds alap_vt_back class to document.documentElement for CSS direction
  • Duration reads from --alap-coordinator-transition CSS property (fallback: 300ms)
  • Falls back to instant swap when reduced motion is preferred or API is unavailable
Example: menu → lightbox → back
typescript
// User clicks a menu item that should open in lightbox
coordinator.transitionTo('lightbox', {
  links: resolvedLinks,
  triggerElement: menuItem,
  initialIndex: 0,
});

// User presses Escape — back to menu
coordinator.back();

// Escape again — closes menu (stack empty)
coordinator.back();

InstanceCoordinator

Global singleton that ensures only one menu (or one lightbox, etc.) is open at a time across all framework adapters.

typescript
import { getInstanceCoordinator } from 'alap';

const coordinator = getInstanceCoordinator();

getInstanceCoordinator()

Returns the global singleton. All adapters (DOM, Web Component, React, Vue, Svelte, Solid, Alpine, Qwik) share this instance.

Methods

MethodSignatureDescription
subscribe()(id: string, type: RendererType, close: () => void) => () => voidRegister an instance; returns unsubscribe function
notifyOpen()(id: string) => voidNotify that this instance opened; closes all others of the same type
closeAll()(type?: RendererType) => voidClose all instances of given type, or all if type omitted
has()(id: string) => booleanWhether a specific instance is registered
destroy()() => voidRemove all subscriptions

Properties

PropertyTypeDescription
sizenumberNumber of registered instances (read-only)
Example: custom adapter integration
typescript
const coordinator = getInstanceCoordinator();

// Register this menu instance
const unsubscribe = coordinator.subscribe(
  'menu-123',
  'menu',
  () => { closeMyMenu(); },
);

// When this menu opens, close all other menus
coordinator.notifyOpen('menu-123');

// Cleanup on unmount
unsubscribe();

CoordinatedRenderer interface

Any renderer that wants to participate in coordinator transitions must implement this interface.

typescript
interface CoordinatedRenderer {
  readonly rendererType: RendererType;
  readonly isOpen: boolean;
  openWith(payload: OpenPayload): void;
  close(): HTMLElement | null;
}

AlapLightbox and AlapLens both implement this interface. Custom renderers can too.

Types

RendererType

typescript
type RendererType = 'menu' | 'lightbox' | 'lens';

Constants

typescript
const RENDERER_MENU = 'menu';
const RENDERER_LIGHTBOX = 'lightbox';
const RENDERER_LENS = 'lens';

OpenPayload

typescript
interface OpenPayload {
  links: ResolvedLink[];
  triggerElement?: HTMLElement;
  initialIndex?: number;
}

RendererStackEntry

Internal stack state saved by the coordinator for back() navigation.

typescript
interface RendererStackEntry {
  renderer: RendererType;
  links: ResolvedLink[];
  activeIndex: number;
  triggerElement: HTMLElement | null;
}