Skip to content

React Components

All components are exported from @doodle-engine/react.

Context provider that wraps the game UI. Holds the engine instance and manages state updates.

import { GameProvider } from '@doodle-engine/react';
<GameProvider engine={engine} initialSnapshot={snapshot}>
{children}
</GameProvider>;
PropTypeDefaultDescription
engineEnginerequiredEngine instance (already initialized)
initialSnapshotSnapshotrequiredInitial snapshot (from newGame or loadGame)
childrenReactNoderequiredChild components
devToolsbooleanfalseEnable window.doodle console API. Pass import.meta.env.DEV.
interface GameContextValue {
snapshot: Snapshot;
actions: {
selectChoice: (choiceId: string) => void;
talkTo: (characterId: string) => void;
takeItem: (itemId: string) => void;
travelTo: (locationId: string) => void;
writeNote: (title: string, text: string) => void;
deleteNote: (noteId: string) => void;
setLocale: (locale: string) => void;
saveGame: () => SaveData;
loadGame: (saveData: SaveData) => void;
dismissInterlude: () => void;
};
}

Access via useGame() hook.

Batteries-included full-screen renderer. Provides a complete game UI with all components pre-wired.

import { GameRenderer } from '@doodle-engine/react';
<GameProvider engine={engine} initialSnapshot={snapshot}>
<GameRenderer className="my-game" />
</GameProvider>;
PropTypeDefaultDescription
classNamestring''CSS class
  • Main area: Location view with banner, dialogue box, choices, or character list
  • Sidebar: Save/load, resources (visible variables), party, inventory, journal, map
  • Auto-filters underscore-prefixed variables from the Resources panel
  • Integrates useAudioManager for automatic audio playback
  • Shows notifications as transient overlays

Displays the current dialogue node with speaker name, portrait, and text.

import { DialogueBox } from '@doodle-engine/react';
<DialogueBox dialogue={snapshot.dialogue} />;
PropTypeDefaultDescription
dialogueSnapshotDialoguerequiredCurrent dialogue data
classNamestring''CSS class

Displays available dialogue choices as clickable buttons.

import { ChoiceList } from '@doodle-engine/react';
<ChoiceList choices={snapshot.choices} onSelectChoice={actions.selectChoice} />;
PropTypeDefaultDescription
choicesSnapshotChoice[]requiredAvailable choices
onSelectChoice(choiceId: string) => voidrequiredChoice selection handler
classNamestring''CSS class

Displays the current location with banner image, name, and description.

import { LocationView } from '@doodle-engine/react';
<LocationView location={snapshot.location} />;
PropTypeDefaultDescription
locationSnapshotLocationrequiredLocation data
classNamestring''CSS class

Displays characters at the current location as clickable cards with portraits.

import { CharacterList } from '@doodle-engine/react';
<CharacterList
characters={snapshot.charactersHere}
onTalkTo={actions.talkTo}
/>;
PropTypeDefaultDescription
charactersSnapshotCharacter[]requiredCharacters to display
onTalkTo(characterId: string) => voidrequiredTalk handler
classNamestring''CSS class

Displays the map with clickable location markers.

import { MapView } from '@doodle-engine/react';
<MapView map={snapshot.map} onTravelTo={actions.travelTo} />;
PropTypeDefaultDescription
mapSnapshotMap | nullrequiredMap data (null hides component)
onTravelTo(locationId: string) => voidrequiredTravel handler
classNamestring''CSS class

Displays the player’s items in a grid with click-to-inspect modal.

import { Inventory } from '@doodle-engine/react';
<Inventory items={snapshot.inventory} />;
PropTypeDefaultDescription
itemsSnapshotItem[]requiredInventory items
classNamestring''CSS class
  • Grid layout with item icons
  • Click an item to open inspection modal
  • Modal shows full image, name, description, and close button
  • Click overlay or close button to dismiss

Displays active quests and unlocked journal entries.

import { Journal } from '@doodle-engine/react';
<Journal quests={snapshot.quests} entries={snapshot.journal} />;
PropTypeDefaultDescription
questsSnapshotQuest[]requiredActive quests
entriesSnapshotJournalEntry[]requiredUnlocked journal entries
classNamestring''CSS class
  • Quests shown first with name, description, and current stage
  • Journal entries shown below, with category used as CSS class (journal-category-{category})

Displays transient notifications.

import { NotificationArea } from '@doodle-engine/react';
<NotificationArea notifications={snapshot.notifications} />;
PropTypeDefaultDescription
notificationsstring[]requiredNotification messages
classNamestring''CSS class

Notifications are transient. They appear in one snapshot and are automatically cleared by the engine.

Save and load game state via localStorage.

import { SaveLoadPanel } from '@doodle-engine/react';
<SaveLoadPanel
onSave={actions.saveGame}
onLoad={actions.loadGame}
storageKey="my-game-save"
/>;
PropTypeDefaultDescription
onSave() => SaveDatarequiredSave handler
onLoad(saveData: SaveData) => voidrequiredLoad handler
storageKeystring'doodle-engine-save'localStorage key
classNamestring''CSS class
  • Save button serializes to localStorage
  • Load button disabled when no save exists
  • Shows temporary “Saved!” / “Loaded!” / “No save found” feedback

Full-screen narrative text scene (chapter card, dream sequence, etc.). Displays a background image with auto-scrolling text. Handled automatically by GameRenderer and GameShell. Use this only when building a custom renderer.

import { Interlude } from '@doodle-engine/react';
<Interlude
interlude={snapshot.pendingInterlude}
onDismiss={actions.dismissInterlude}
/>;
PropTypeDescription
interludeSnapshotInterludeInterlude data from the snapshot
onDismiss() => voidCalled when the player skips or finishes reading

The player can dismiss via click, Skip button, Space, Enter, or Escape. Mouse wheel and arrow keys scroll manually and pause auto-scroll.

Fullscreen video/cutscene overlay with a visible Skip button. Also supports skip via keypress (Escape, Space, Enter).

import { VideoPlayer } from '@doodle-engine/react';
<VideoPlayer
src="intro_cinematic.mp4"
basePath="/video"
onComplete={() => console.log('Video done')}
/>;
PropTypeDefaultDescription
srcstringrequiredVideo file name
basePathstring'/video'Base path for video files
onComplete() => voidrequiredCalled when video ends or is skipped
classNamestring''CSS class

Progress screen displayed while game assets load. Used as the default renderLoading UI inside GameShell and AssetProvider.

import { LoadingScreen } from '@doodle-engine/react'
<GameShell
renderLoading={(state) => (
<LoadingScreen state={state} background="/assets/images/loading-bg.jpg" />
)}
...
/>
PropTypeDefaultDescription
stateAssetLoadingStaterequiredLoading state from AssetProvider
backgroundstringBackground image URL (from shell.loading.background)
renderProgress(progress: number, phase: string) => ReactNodeCustom progress bar renderer
classNamestring''CSS class

Style it by targeting .loading-screen, .loading-screen-content, .loading-screen-spinner, .loading-screen-phase, .loading-screen-percent, .loading-screen-bar-track, and .loading-screen-bar-fill in your CSS.

Brief studio/logo screen that auto-advances. Assets and duration come from config.shell.splash in game.yaml.

import { SplashScreen } from '@doodle-engine/react';
<SplashScreen
shell={config.shell?.splash}
onComplete={() => setScreen('title')}
/>;
PropTypeDefaultDescription
shellShellConfig['splash']Splash config from game.yaml
onComplete() => voidrequiredCalled when splash finishes
classNamestring''CSS class

Duration defaults to 2000ms if not set in shell.duration. Click anywhere to skip.

The shell config fields:

FieldTypeDescription
logostringLogo image path
backgroundstringBackground image path
soundstringSound effect played on enter
durationnumberAuto-advance time in ms (default 2000)

Main menu with New Game, Continue, and Settings buttons.

import { TitleScreen } from '@doodle-engine/react';
<TitleScreen
title="My Game"
subtitle="A text-based adventure"
hasSaveData={true}
onNewGame={handleNewGame}
onContinue={handleContinue}
onSettings={handleSettings}
/>;
PropTypeDefaultDescription
shellShellConfig['title']Title config from game.yaml
titlestring'Doodle Engine'Game title text (shown when no logo)
subtitlestringSubtitle text
hasSaveDatabooleanrequiredWhether Continue button is shown
onNewGame() => voidrequiredNew Game handler
onContinue() => voidrequiredContinue handler
onSettings() => voidrequiredSettings handler
classNamestring''CSS class

In-game overlay with Resume, Save, Load, Settings, and Quit to Title buttons.

import { PauseMenu } from '@doodle-engine/react';
<PauseMenu
onResume={handleResume}
onSave={handleSave}
onLoad={handleLoad}
onSettings={handleSettings}
onQuitToTitle={handleQuit}
/>;
PropTypeDefaultDescription
onResume() => voidrequiredResume gameplay
onSave() => voidrequiredSave game
onLoad() => voidrequiredLoad saved game
onSettings() => voidrequiredOpen settings
onQuitToTitle() => voidrequiredQuit to title screen
classNamestring''CSS class

Settings UI with volume sliders and language selection.

import { SettingsPanel } from '@doodle-engine/react';
<SettingsPanel
audioControls={audioControls}
uiSoundControls={uiSoundControls}
availableLocales={[{ code: 'en', label: 'English' }]}
onLocaleChange={actions.setLocale}
onBack={handleBack}
/>;
PropTypeDefaultDescription
audioControlsobjectrequiredAudio volume setters
uiSoundControlsUISoundControlsUI sound controls
availableLocales{ code: string; label: string }[]Language options
currentLocalestringCurrent language code
onLocaleChange(locale: string) => voidLanguage change handler
onBack() => voidrequiredBack/close handler
classNamestring''CSS class

Complete game wrapper that manages the full lifecycle: splash screen → title screen → gameplay, with pause menu, settings, and video playback built in.

import { GameShell } from '@doodle-engine/react';
<GameShell
registry={registry}
config={config}
manifest={manifest}
title="My Game"
subtitle="A text-based adventure"
availableLocales={[{ code: 'en', label: 'English' }]}
devTools={import.meta.env.DEV}
/>;
PropTypeDefaultDescription
registryContentRegistryrequiredContent registry from /api/content
configGameConfigrequiredGame config from /api/content
manifestAssetManifestrequiredAsset manifest from /api/manifest
assetLoaderAssetLoaderCustom asset loader (for non-browser environments)
titlestring'Doodle Engine'Game title text
subtitlestringSubtitle text
uiSoundsUISoundConfig | falseUI sound config, or false to disable
audioOptionsAudioManagerOptionsGame audio options
storageKeystring'doodle-engine-save'localStorage key for saves
availableLocales{ code: string; label: string }[]Language options for settings
videoBasePathstring'/video'Base path for video files
classNamestring''CSS class
renderLoading(state: AssetLoadingState) => ReactNodeOverride the loading screen
devToolsbooleanfalseEnable window.doodle console API. Pass import.meta.env.DEV.

Splash screen, loading background, title logo, and UI sounds are configured in game.yaml under shell:. See Asset Loading for the full shell config reference.

  • Asset loading with progress screen before any game content renders
  • Splash screen (shown when config.shell.splash is configured)
  • Title screen with New Game, Continue (if save exists), Settings
  • In-game pause menu (Menu button or Escape key)
  • Settings panel with volume sliders and language select
  • Automatic video/cutscene playback from pendingVideo
  • Save/load via localStorage
  • UI click sounds (configurable)