Skip to main content

Runtime semantics

Define transition ordering, concurrency, missing targets, and errors.

Runtime semantics

Transition order

Every destination step uses one fixed sequence:

evaluate when()
  -> navigate to route
  -> wait for route settlement
  -> run prepare()
  -> resolve or wait for target
  -> scroll
  -> clean up the previous step
  -> render and position
  -> move focus

The route belongs to the destination step. The same rule applies to start(), next(), previous(), and goTo().

Scrolling centers a target vertically by default. The browser owns smooth scrolling and adapts it to the travel distance. Nuxt Tour starts the reveal when the target is close to its destination and its movement has stayed slow across multiple frames. This removes a separate pause after scrolling while keeping the final card movement small.

An application or browser navigation that happens outside the controller cancels the active tour. This avoids leaving a card attached to a target from a page that no longer exists.

An active card and its application effects stay active while the destination is prepared. The controller leaves and cleans it up only after the destination route, preparation, target, and scrolling have succeeded. This can briefly overlap both steps' application effects, but it prevents a failed or skipped destination from leaving the visible step in a false state. Step-to-step replacement does not call the visual hide path; the old presentation remains mounted until the new presentation replaces it. This prevents a half-applied transition or an unshaded frame between steps.

prepare() can create the target. If it returns a cleanup function, the engine runs that cleanup exactly once when the step ends, the tour ends, replacement starts, or the transition fails. The context contains an AbortSignal.

Promise meaning

All controller commands return promises. A successful navigation promise resolves after the destination card is active and its focus behavior has completed. It does not resolve after only changing an index.

Concurrency

The controller permits one transition at a time. A repeated identical command shares the in-flight promise. A conflicting navigation command fails with TOUR_BUSY. cancel() aborts an in-flight transition, runs cleanup, restores focus when possible, and ends safely.

One application can have one active tour. Starting another tour fails unless the caller passes replace: true. Replacement completes old-tour cleanup before the new tour starts.

Conditional and missing steps

A false when() result is expected control flow for next() and previous(). The engine performs no route, prepare, target, or render work for that step and continues in the current direction. goTo(id) and an explicit start({ at }) are exact: an unavailable destination rejects with STEP_UNAVAILABLE and never lands on a different step.

Target waiting is bounded. The default timeout and missing behavior belong to one module-level configuration source. A target can override them.

The v1 default timeout is 5000 ms. The v1 default missing behavior is error.

  • missing: 'skip' emits target:missing and continues.
  • missing: 'error' emits target:missing, ends safely, and rejects with TARGET_NOT_FOUND.

The resolver ignores disconnected and hidden candidates. Two visible candidates for the same semantic ID reject with TARGET_AMBIGUOUS. The engine does not select one based on DOM order.

Development diagnostics include the tour ID, step ID, target, route, timeout, and currently registered semantic target IDs.

Errors and events

Expected user outcomes are not errors: completion, skip, cancel, a false condition, and a configured missing-target skip.

Stable initial error codes are:

INVALID_DEFINITION
TARGET_NOT_FOUND
TARGET_AMBIGUOUS
ROUTE_FAILED
ROUTER_NOT_CONFIGURED
PREPARE_FAILED
STEP_UNAVAILABLE
HOST_NOT_FOUND
TOUR_ALREADY_ACTIVE
TOUR_BUSY

The initial event map is:

tour:start
step:before
step:show
step:leave
target:missing
tour:end
tour:error

tour:end reports completed, skipped, or cancelled. Consumers do not parse message strings. Event subscriptions return an unsubscribe function and also stop with their Vue effect scope when one exists. Event listeners are observational: synchronous throws and rejected listener promises are reported without changing tour state.