Overview
Global events are used for cross-component communication without React context dependencies, allowing for simple function calls to trigger events across different parts of the application.
Global Events Guidelines
Global events are used for cross-component communication without React context dependencies, allowing for simple function calls to trigger events across different parts of the application.
Overview
The global events system lives at global-event.tsx and is built on a typed Event subclass (XCustomEvent).
It exposes:
global_event_Event: the canonical type map of event keys →detailpayload typesglobal_event_dispatch(event, payload): dispatch a typed event (works outside React)global_event_listen(event, handler, options?): listen with typed handler (works outside React)useGlobalEvent(event, handler): React hook for subscriptions with stale-closure protection
Event key naming
Event keys are string literals using the pattern:
(module::event_name), for example ai_chat::open_canvas.
How to add or modify an event
When the user requests a new global event, you must:
Update the event map
Add the new event key to the global_event_Event map in global-event.tsx.
Example:
ts1export class global_event_Event extends XCustomEvent<{ 2 "ai_chat::open_canvas": { 3 pageId: app_convex_Id<"pages">; 4 mode: "diff" | "editor"; 5 modifiedContent?: string; 6 threadId: string; 7 }; 8 "ai_chat::open_canvas_by_path": { 9 path: string; 10 }; 11 "docs::focus_path": { 12 path: string; 13 }; 14}> {}
Keep all event keys centralized
All supported global event keys must be declared in that global_event_Event type map. Do not introduce ad-hoc stringly-typed events elsewhere.
Use the exported helpers
Prefer global_event_dispatch / global_event_listen / useGlobalEvent rather than calling window.dispatchEvent(new CustomEvent(...)) directly.
Usage patterns
React components
Use useGlobalEvent(eventName, handler) to subscribe. The handler receives a typed event object, and the payload is on event.detail.
Example (from canvas.tsx):
ts1useGlobalEvent("ai_chat::open_canvas", (e) => { 2 const payload = e.detail; 3 // payload.pageId, payload.mode, payload.modifiedContent, payload.threadId 4});
Non-React code (or manual lifecycle control)
Use global_event_listen directly when you need to wire AbortController, or you are outside React.
ts1const controller = new AbortController(); 2 3const cleanup = global_event_listen( 4 "ai_chat::open_canvas_by_path", 5 (e) => { 6 console.info("path:", e.detail.path); 7 }, 8 { signal: controller.signal }, 9); 10 11// later: 12controller.abort(); 13cleanup();
Dispatching
Use global_event_dispatch(eventName, payload) from anywhere client-side.
Example (from app-ai-chat.tsx):
ts1global_event_dispatch("ai_chat::open_canvas_by_path", { path: args.path });
Handler typing and payload access
Handlers receive the typed event object, not the payload directly:
ts1useGlobalEvent("ai_chat::open_canvas", (e) => { 2 const payload = e.detail; 3});
Files and references
- Core implementation: global-event.tsx
- Typed event base:
XCustomEventin utils.ts - Hook helper:
useLiveRefin utils-hooks.ts - Example consumers: app-ai-chat.tsx, canvas.tsx