Dialogue
React 游戏对话框组件:说话人名字置于斜切块上,台词逐字打出,闪烁的标记提示继续,回复选项带编号。
安装
# once per project: where @zzzui items come frompnpm dlx shadcn@latest registry add @zzzui=https://zzzui.catforest.dev/r/{name}.jsonpnpm dlx shadcn@latest add @zzzui/dialogue示例
带回复选项的对话
Mara
import { useState } from "react";import { Dialogue, DialogueChoice, DialogueChoices, DialogueNext, DialogueSpeaker, DialogueText,} from "@/components/zero/dialogue";const script = [ { who: "Mara", line: "You're late. The gate shuts at two, and the crates are still at the yards.", }, { who: "Mara", line: "Rook says the river road is watched tonight. Your call, courier.", },];const replies = [ { say: "We take the river road. It's faster.", answer: "Fast and loud. Keep your shield charged.", }, { say: "We go round by the old market.", answer: "Slower, but nobody looks twice at the market.", }, { say: "Who's watching it?", answer: "Nobody you want to meet. Pick a road.", },];export default function DialogueTalk() { const [step, setStep] = useState(0); const [answer, setAnswer] = useState<string | null>(null); const [typed, setTyped] = useState(""); const line = answer ?? script[step].line; const asking = answer === null && step === script.length - 1; return ( <Dialogue aria-label="Conversation with Mara" className="w-full max-w-2xl"> <DialogueSpeaker>{answer ? "Mara" : script[step].who}</DialogueSpeaker> <DialogueText key={line} onDone={() => setTyped(line)}> {line} </DialogueText> {/* the replies wait for the line; until then, Continue shows the rest */} {asking && typed === line ? ( <DialogueChoices> {replies.map((reply, index) => ( <DialogueChoice key={reply.say} index={index + 1} onClick={() => setAnswer(reply.answer)} > {reply.say} </DialogueChoice> ))} </DialogueChoices> ) : ( <DialogueNext onClick={() => { if (answer) { setAnswer(null); setStep(0); } else setStep((s) => s + 1); }} > {answer ? "Start over" : "Continue"} </DialogueNext> )} </Dialogue> );}行为
对话框是一道黑色横条,说话人的名字写在一块斜切块上,压在横条的上边缘。台词以每秒 speed 个字符的速度逐字打出;点击台词或 Continue,或在对话框内任意位置按 Enter 或空格键,会立即显示全文;回复选项等台词完整显示后才出现。焦点位于对话框内时,按数字键可选择回复。
读屏软件通过对话框上 polite 级别的实时区域,将每句完整台词读出一次,不读逐字打出的过程。开启「减少动态效果」时,台词直接完整显示。每句新台词需为 DialogueText 指定新的 key,逐字效果才会从头开始。
属性
DialogueText
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| children | string | — | 台词。 |
| speed | number | 45 | 每秒显示的字符数。 |
| onDone | () => void | — | 整句台词显示完毕时触发。 |
DialogueNext
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| onClick | (event) => void | — | 台词完整显示后点击时调用;在此之前,点击会显示剩余部分。 |
| children | ReactNode | "Continue" | 按钮文字。 |
DialogueChoice
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| index | number | — | 序号,也是选择该项的按键。 |