zzzUI

Dialogue

React 游戏对话框组件:说话人名字置于斜切块上,台词逐字打出,闪烁的标记提示继续,回复选项带编号。

安装

terminal
# 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

dialogue-talk.tsx
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

属性类型默认值说明
childrenstring—台词。
speednumber45每秒显示的字符数。
onDone() => void—整句台词显示完毕时触发。

DialogueNext

属性类型默认值说明
onClick(event) => void—台词完整显示后点击时调用;在此之前,点击会显示剩余部分。
childrenReactNode"Continue"按钮文字。

DialogueChoice

属性类型默认值说明
indexnumber—序号,也是选择该项的按键。

Dialogue, DialogueSpeaker, DialogueChoices