Skip to content

Interface: ModeSpec<M>

Defined in: modal/mode.ts:33

The mode machine as data (modal-interaction-lessons §4.1).

A modal surface's modes, their Esc ladder, and their entry/exit effects are declared in one serializable table instead of scattered booleans and hand-written stepOut() logic. The kit deliberately does NOT own the mode value: the app stores it wherever its architecture keeps state (an engine field, a signal, an event in its stream — mode changes SHOULD be events so traces show them and replay reproduces them). What the table gives you mechanically:

  • escTarget — the escape ladder as a column, not code. The convention it encodes (hold constant across apps; users build muscle memory): Esc steps out one level / aborts the current scope, and is never destructive beyond that scope. Enter commits the current scope and never reaches through to an outer scope's destructive action.
  • runTransition — fires the old mode's onExit and the new mode's onEnter in order, so entry/exit effects have exactly one home.
  • per-mode cursor — cursors are part of the mode contract (lessons §3 rule 10); the reconciler asserts them from here rather than surfaces toggling them ad hoc.
  • blurExits — whether leaving the window ends the mode (blurExitTarget reads it). Modes whose purpose is a round-trip out of the page (a jump-to-editor mode) declare it here instead of hand-writing a blur listener per mode.

Keymap layers are deliberately not a column: a layer (a config strip, a dialog) claims a few keys while every other key keeps its meaning — that is a different thing from a mode, and conflating them is how "the strip is open" becomes a seventh scattered boolean. See ./keys.ts.

Type Parameters

M

M extends string

Properties

blurExits?

optional blurExits?: boolean

Defined in: modal/mode.ts:49

True when leaving the window ends this mode: on window blur the app should step out (to escParent, the same one-level transition Esc takes — blurExitTarget resolves it). For modes whose purpose is a round-trip out of the page — a jump-to-editor mode — coming back must not resume the mode; a gesture left armed across the excursion is a trap the user has forgotten about.


cursor?

optional cursor?: string

Defined in: modal/mode.ts:40

CSS cursor this mode asserts on its owning surface (via the reconciler).


escParent

escParent: M | null

Defined in: modal/mode.ts:38

Where Esc steps out to from this mode; null when Esc means nothing here (the root mode). One column instead of a hand-written ladder.


onEnter?

optional onEnter?: (from) => void

Defined in: modal/mode.ts:51

Entry effect — dispatch commands / start effects; never mutate state directly.

Parameters

from

M

Returns

void


onExit?

optional onExit?: (to) => void

Defined in: modal/mode.ts:53

Exit effect — release what onEnter acquired. Must be idempotent.

Parameters

to

M

Returns

void