Custom NVL Dialog
Choose a Customization Level
NVL (Novel) mode displays multiple dialogue entries in a scrollable list, suitable for novel-style narration. You can replace the default NvlContainer via the nvlDialog option in game.configure to fully customize the NVL dialogue appearance.
There are two useful levels: replace the whole container with NvlContainer, or keep DefaultNvlContainer and change only renderDialogItem.
1. Fully Custom NVL Container
Use NvlContainer as the outer wrapper, receive the dialogs array, and render each dialogue yourself. INvlContainerProps includes dialogs and an optional renderDialogItem.
import {
NvlContainer,
Nametag,
Texts,
type INvlContainerProps,
} from "narraleaf-react";
function CustomNvlContainer({ dialogs = [] }: INvlContainerProps) {
return (
<NvlContainer className="bg-black/80 text-white p-16">
{/* NvlContainer: handles visibility, transitions, aspect-ratio scaling */}
{dialogs.map((d) => (
<div key={d.entry.id} className="space-y-2 mb-4">
{/* d.entry: NvlDialogEntry with character, sentence, etc. */}
{d.entry.character && (
<Nametag entry={d.entry} className="text-amber-400 font-bold" />
)}
<Texts
entry={d.entry}
gameState={d.gameState}
words={d.words}
useTypeEffect={d.useTypeEffect}
isActive={d.isActive}
/>
</div>
))}
</NvlContainer>
);
}
2. Customize Per-Dialogue with renderDialogItem
If you only need to adjust how each dialogue is displayed (e.g. border, opacity), keep using DefaultNvlContainer and pass renderDialogItem to customize the layout:
import {
DefaultNvlContainer,
useGame,
type INvlContainerProps,
} from "narraleaf-react";
function CustomNvlWithRenderer({ dialogs, renderDialogItem }: INvlContainerProps) {
return (
<DefaultNvlContainer
dialogs={dialogs}
renderDialogItem={({ entry, index, isActive, nametag, texts }) => (
// nametag, texts: pre-rendered by DefaultNvlContainer
<div className={`mb-4 ${isActive ? "opacity-100" : "opacity-60"}`}>
{nametag}
<div className="border-l-4 border-blue-500 pl-2">{texts}</div>
</div>
)}
/>
);
}3. renderDialogItem Parameters
renderDialogItem receives NvlDialogItemRenderProps:
| Param | Type | Description |
|---|---|---|
entry | NvlDialogEntry | Dialogue entry (character, sentence, etc.) |
index | number | Index in the list |
isActive | boolean | Whether this is the currently active (typing) dialogue |
nametag | React.ReactNode | Pre-rendered character name (null when no character) |
texts | React.ReactNode | Pre-rendered text content |
4. Register with Game
import { Game, GameProviders, Player } from "narraleaf-react";
const game = new Game({ nvlDialog: CustomNvlContainer });
function App() {
return (
<GameProviders game={game}>
<Player story={story} onReady={({ liveGame }) => liveGame.newGame()} />
</GameProviders>
);
}Use CustomNvlWithRenderer instead when only the row layout needs to change.
See Also
- NvlContainer - NVL container API
- game.configure - Game configuration