Dialogue box
Dialogue box is a neobrutalist React component from Cruise UI. A game-style speech box for tours and tips: portrait, name tab, typewriter text, Next / Skip and a step count. Install it with npx shadcn@latest add @cruiseui/dialogue-box.
Install
Terminal
npx shadcn@latest add @cruiseui/dialogue-boxFirst time? Installation shows the one-off components.json setup (the @cruiseui registry) and how to turn the theme on.
Example
Corners
AO
Welcome to Cruise UI! I'll show you around in three quick steps.
Step 1 / 3
"use client";
import { useState } from "react";
import { CruiseAvatar } from "@/components/cruise/avatar";
import { CruiseButton } from "@/components/cruise/button";
import { CruiseDialogueBox } from "@/components/cruise/dialogue-box";
const steps = [
{ text: "Welcome to Cruise UI! I'll show you around in three quick steps." },
{ text: "Pick a city theme in the Studio, then tweak the colours, borders and corners." },
{ text: "Copy the prompt into your AI, or install the components into your React app." },
];
export default function DialogueBoxExample() {
const [key, setKey] = useState(0);
const [done, setDone] = useState(false);
if (done) {
return (
<CruiseButton variant="secondary" onClick={() => (setDone(false), setKey((k) => k + 1))}>
Show the tour again
</CruiseButton>
);
}
return (
<CruiseDialogueBox
key={key}
speaker="Ada"
portrait={<CruiseAvatar name="Ada Okafor" size="lg" />}
steps={steps}
onSkip={() => setDone(true)}
onFinish={() => setDone(true)}
/>
);
}
<section class="dialogue" aria-label="Ada says">
<span class="dialogue-name">Ada</span>
<div class="dialogue-main">
<p class="dialogue-text"><span class="visually-hidden" aria-live="polite">Pick a city theme in the Studio, then tweak the colours.</span><span aria-hidden="true">Pick a city theme in the Studio, then tweak the colours.</span></p>
<div class="dialogue-foot">
<span class="dialogue-step"><span class="visually-hidden">Step </span>2 / 3</span>
<div class="dialogue-buttons">
<button type="button" class="brutal btn btn-secondary">Skip</button>
<button type="button" class="brutal btn on-primary">Next</button>
</div>
</div>
</div>
</section>Needs theme.css. Interactive parts (menus, tabs, drawers) also need the script in the spec for that component.
When to use it
When to use
Onboarding tours, tips from a character, story moments in games.
When not to
Important instructions people need to find again (put them on the page).
Props
CruiseDialogueBox
| Prop | Type | Default | Description |
|---|---|---|---|
steps | CruiseDialogueStep[] | — | — |
speaker? | string | — | Default speaker for every step. |
portrait? | ReactNode | — | Default portrait (an avatar or character), left of the text. |
typewriter? | boolean | true | Type each line out. |
speed? | number | 28 | Milliseconds per character when typing. |
position? | "inline" | "fixed" | "inline" | — |
onFinish? | (() => void) | — | After the last step's "Done". |
onSkip? | (() => void) | — | "Skip" (all steps). Without it, there's no Skip button. |
className? | string | — | — |
Accessibility
- Screen readers get the whole line at once; the typing is visual only.
- Click, Enter or "Show all" reveals the full line; reduced motion shows it straight away.
- Next, Skip and Done are real buttons; the step count reads "Step 2 / 5".