This tutorial shows how the message system is composed: a MessageProvider orchestrates pages and choices, Typewriter renders text with per‑character reveal and effects, and SpecialCodeRenderer draws RPG‑style escape codes (icons, variables, currency, etc.).
Files
menus/src/components/Message.tsx — provider + portal that displays message windows and routes input
menus/src/components/Typewriter.tsx — the typewriter text engine
menus/src/components/SpecialCodeRenderer.tsx — visualizes special codes from the parser
Showing a message
Wrap your app in MessageProvider (this repo already does this in the root). Then call useMessage().show(...) from anywhere.
importReactfrom'react';import{useMessage}from'../../components/Message';constTalkExample:React.FC=()=>{constmessage=useMessage();constonTalk=async()=>{awaitmessage.show({_texts: ["Hello, hero!\\nWelcome to \\C[3]React Town\\C[0].","Take this: \\I[87] Potion x1.\\.\\. Good luck!", ],_choices: [],// optional}); // continues after the player advances all pages};return<buttononClick={onTalk}>Talk</button>;};exportdefaultTalkExample;
Notes
show(input, opts?) accepts the same structure the bridge sends from MZ (_texts, _choices).
The provider handles advancing pages with OK/CANCEL via InputContext.
Message window – A test message with a number of special character codes
Typewriter basics
Typewriter accepts text as a string or string array and emits characters over time.
Useful props
charDelay (ms), lineDelay (ms)
renderLine(visibleNodes, lineIndex) lets you wrap each line, e.g., inside a MessageBox
onDone callback when all text is revealed
Rendering special codes
SpecialCodeRenderer receives parsed “escape code” objects and renders icons, variables, actor names, currency, and triggers toasts (e.g., gold display) when allowed.
Supported visuals (selected)
New line → <br/>
Currency (\G or currencyUnit) → <span class="rpg-currency"> with your currency symbol
Icon (\I[n]) → <Icon> component
Variable (\V[n]), Actor (\N[n]), Party Member (\P[n]) → names/values
Gold display side‑effect → toast event (suppressed when allowEffects={false})
Example inside a custom message line renderer
Integration notes
The stock Message component already wires Typewriter + SpecialCodeRenderer for bridge‑delivered messages. Use the low‑level components only when building highly customized panels.
Set allowEffects={false} in SpecialCodeRenderer when rendering in a log/history view (suppress toasts).
import SpecialCodeRenderer, { SpecialCode } from '../../components/SpecialCodeRenderer';
function renderLine(nodes: React.ReactNode[], i: number) {
return (
<div key={i} className="line">
{nodes.map((n, j) => {
// If the engine provided a SpecialCode object, render it using our renderer
if (typeof n === 'object' && n && (n as any as SpecialCode).c !== undefined) {
return <SpecialCodeRenderer key={j} code={n as any as SpecialCode} />;
}
return <span key={j}>{n as any}</span>;
})}
</div>
);
}