Data Displayduskmoonimplemented9 demos

Chat

Chat composes conversational turns with message bubbles, reasoning traces, tool calls, and live response states.

Import@duskmoon-dev/components/chat
17API sections
6documented props
6behavior scenarios
Key API
placementcolorsizefilledstreamingstatus

Usage

When to use

  • Use it to clarify state, metadata, content hierarchy, or loading without creating a new workflow.
  • Pair it with semantic content so visual treatment never becomes the only source of meaning.

Implementation notes

StylesheetImport @duskmoon-dev/components/styles.css once in the app or docs shell.
StateStart with default props for static examples, then switch to controlled props when state must be shared.
ThemeThe preview inherits the active DuskMoon data-theme value from the docs layout.

Features

Visual hierarchy

Focuses on status, metadata, empty/loading states, or content grouping without owning application state.

Theme integration

Uses DuskMoon tokens so the component follows the active docs theme.

Primary API surface

Chat is most often configured through `placement`, `color`, `size`, `filled`.

Covered behavior

Renders a start-aligned turn with structural slots

Feature Demos

Feature demos are authored for the component page, then supplemented with behavior scenarios from the component test coverage.

Preview
primary
primary response
secondary
secondary response
tertiary
tertiary response
accent
accent response
neutral
neutral response
base
base response
info
info response
success
success response
warning
warning response
error
error response

Colors

authored

Chat supports the full semantic color palette: primary, secondary, tertiary, accent, neutral, base, info, success, warning, error.

Source
import "@duskmoon-dev/components/styles.css";
import { Chat } from "@duskmoon-dev/components/chat";

const colors = [
  "primary",
  "secondary",
  "tertiary",
  "accent",
  "neutral",
  "base",
  "info",
  "success",
  "warning",
  "error"
] as const;

export function ChatColorsDemo() {
  return (<div style={{ display: "grid", gap: 10 }}>
  {colors.map((color) => (
    <Chat key={color}>
      <Chat.Bubble color={color}>{color} response</Chat.Bubble>
    </Chat>
  ))}
</div>);
}
Preview
AI
Assistant · just now
Thinking (2s)
Checking the component catalog before replying.
search_componentsDone
{"query":"chat"}
Found the DuskMoon Chat primitives.
The React chat primitives are ready to compose.
You
You · just now
Show me the live response state.
AI

Basic usage

authored

Import the component stylesheet and Chat from its package subpath, then render it with the core props.

Source
import "@duskmoon-dev/components/styles.css";
import { Chat } from "@duskmoon-dev/components/chat";

export function Example() {
  return (<Chat aria-live="polite">
  <Chat.Avatar>
    <span className="avatar avatar-sm avatar-info">AI</span>
  </Chat.Avatar>
  <Chat.Header>Assistant · just now</Chat.Header>
  <Chat.Reasoning open>
    <summary>Thinking (2s)</summary>
    <div>Reviewing the component API before answering.</div>
  </Chat.Reasoning>
  <Chat.Tool status="success" open>
    <Chat.ToolHeader>
      <span>search_components</span>
      <Chat.ToolStatus>Done</Chat.ToolStatus>
    </Chat.ToolHeader>
    <Chat.ToolCall>{'{"query":"chat"}'}</Chat.ToolCall>
    <Chat.ToolResult>Found the DuskMoon Chat primitives.</Chat.ToolResult>
  </Chat.Tool>
  <Chat.Bubble color="primary" streaming>
    Chat is ready for React.
  </Chat.Bubble>
  <Chat.Footer>Delivered</Chat.Footer>
</Chat>);
}
Preview
AI
Assistant · just now
Thinking (2s)
Checking the component catalog before replying.
search_componentsDone
{"query":"chat"}
Found the DuskMoon Chat primitives.
The React chat primitives are ready to compose.
You
You · just now
Show me the live response state.
AI

Renders a start-aligned turn with structural slots

test-backed

Chat scenario from the component test coverage: renders a start-aligned turn with structural slots.

Source
import "@duskmoon-dev/components/styles.css";
import { Chat } from "@duskmoon-dev/components/chat";

export function ChatRendersAStartAlignedDemo() {
  return (<Chat aria-live="polite">
  <Chat.Avatar>
    <span className="avatar avatar-sm avatar-info">AI</span>
  </Chat.Avatar>
  <Chat.Header>Assistant · just now</Chat.Header>
  <Chat.Reasoning open>
    <summary>Thinking (2s)</summary>
    <div>Reviewing the component API before answering.</div>
  </Chat.Reasoning>
  <Chat.Tool status="success" open>
    <Chat.ToolHeader>
      <span>search_components</span>
      <Chat.ToolStatus>Done</Chat.ToolStatus>
    </Chat.ToolHeader>
    <Chat.ToolCall>{'{"query":"chat"}'}</Chat.ToolCall>
    <Chat.ToolResult>Found the DuskMoon Chat primitives.</Chat.ToolResult>
  </Chat.Tool>
  <Chat.Bubble color="primary" streaming>
    Chat is ready for React.
  </Chat.Bubble>
  <Chat.Footer>Delivered</Chat.Footer>
</Chat>);
}
Preview
AI
Assistant · just now
Thinking (2s)
Checking the component catalog before replying.
search_componentsDone
{"query":"chat"}
Found the DuskMoon Chat primitives.
The React chat primitives are ready to compose.
You
You · just now
Show me the live response state.
AI

Supports end placement and bubble variants

test-backed

Chat scenario from the component test coverage: supports end placement and bubble variants.

Source
import "@duskmoon-dev/components/styles.css";
import { Chat } from "@duskmoon-dev/components/chat";

export function ChatSupportsEndPlacementAndDemo() {
  return (<Chat aria-live="polite">
  <Chat.Avatar>
    <span className="avatar avatar-sm avatar-info">AI</span>
  </Chat.Avatar>
  <Chat.Header>Assistant · just now</Chat.Header>
  <Chat.Reasoning open>
    <summary>Thinking (2s)</summary>
    <div>Reviewing the component API before answering.</div>
  </Chat.Reasoning>
  <Chat.Tool status="success" open>
    <Chat.ToolHeader>
      <span>search_components</span>
      <Chat.ToolStatus>Done</Chat.ToolStatus>
    </Chat.ToolHeader>
    <Chat.ToolCall>{'{"query":"chat"}'}</Chat.ToolCall>
    <Chat.ToolResult>Found the DuskMoon Chat primitives.</Chat.ToolResult>
  </Chat.Tool>
  <Chat.Bubble color="primary" streaming>
    Chat is ready for React.
  </Chat.Bubble>
  <Chat.Footer>Delivered</Chat.Footer>
</Chat>);
}
Preview
AI
Assistant · just now
Thinking (2s)
Checking the component catalog before replying.
search_componentsDone
{"query":"chat"}
Found the DuskMoon Chat primitives.
The React chat primitives are ready to compose.
You
You · just now
Show me the live response state.
AI

Maps every bubble size and tool state

test-backed

Chat scenario from the component test coverage: maps every bubble size and tool state.

Source
import "@duskmoon-dev/components/styles.css";
import { Chat } from "@duskmoon-dev/components/chat";

export function ChatMapsEveryBubbleSizeDemo() {
  return (<Chat aria-live="polite">
  <Chat.Avatar>
    <span className="avatar avatar-sm avatar-info">AI</span>
  </Chat.Avatar>
  <Chat.Header>Assistant · just now</Chat.Header>
  <Chat.Reasoning open>
    <summary>Thinking (2s)</summary>
    <div>Reviewing the component API before answering.</div>
  </Chat.Reasoning>
  <Chat.Tool status="success" open>
    <Chat.ToolHeader>
      <span>search_components</span>
      <Chat.ToolStatus>Done</Chat.ToolStatus>
    </Chat.ToolHeader>
    <Chat.ToolCall>{'{"query":"chat"}'}</Chat.ToolCall>
    <Chat.ToolResult>Found the DuskMoon Chat primitives.</Chat.ToolResult>
  </Chat.Tool>
  <Chat.Bubble color="primary" streaming>
    Chat is ready for React.
  </Chat.Bubble>
  <Chat.Footer>Delivered</Chat.Footer>
</Chat>);
}
Preview
AI
Assistant · just now
Thinking (2s)
Checking the component catalog before replying.
search_componentsDone
{"query":"chat"}
Found the DuskMoon Chat primitives.
The React chat primitives are ready to compose.
You
You · just now
Show me the live response state.
AI

Uses native details and summary elements for LLM blocks

test-backed

Chat scenario from the component test coverage: uses native details and summary elements for llm blocks.

Source
import "@duskmoon-dev/components/styles.css";
import { Chat } from "@duskmoon-dev/components/chat";

export function ChatUsesNativeDetailsAndDemo() {
  return (<Chat aria-live="polite">
  <Chat.Avatar>
    <span className="avatar avatar-sm avatar-info">AI</span>
  </Chat.Avatar>
  <Chat.Header>Assistant · just now</Chat.Header>
  <Chat.Reasoning open>
    <summary>Thinking (2s)</summary>
    <div>Reviewing the component API before answering.</div>
  </Chat.Reasoning>
  <Chat.Tool status="success" open>
    <Chat.ToolHeader>
      <span>search_components</span>
      <Chat.ToolStatus>Done</Chat.ToolStatus>
    </Chat.ToolHeader>
    <Chat.ToolCall>{'{"query":"chat"}'}</Chat.ToolCall>
    <Chat.ToolResult>Found the DuskMoon Chat primitives.</Chat.ToolResult>
  </Chat.Tool>
  <Chat.Bubble color="primary" streaming>
    Chat is ready for React.
  </Chat.Bubble>
  <Chat.Footer>Delivered</Chat.Footer>
</Chat>);
}
Preview
AI
Assistant · just now
Thinking (2s)
Checking the component catalog before replying.
search_componentsDone
{"query":"chat"}
Found the DuskMoon Chat primitives.
The React chat primitives are ready to compose.
You
You · just now
Show me the live response state.
AI

Renders an accessible typing indicator with the required inner dot

test-backed

Chat scenario from the component test coverage: renders an accessible typing indicator with the required inner dot.

Source
import "@duskmoon-dev/components/styles.css";
import { Chat } from "@duskmoon-dev/components/chat";

export function ChatRendersAnAccessibleTypingDemo() {
  return (<Chat aria-live="polite">
  <Chat.Avatar>
    <span className="avatar avatar-sm avatar-info">AI</span>
  </Chat.Avatar>
  <Chat.Header>Assistant · just now</Chat.Header>
  <Chat.Reasoning open>
    <summary>Thinking (2s)</summary>
    <div>Reviewing the component API before answering.</div>
  </Chat.Reasoning>
  <Chat.Tool status="success" open>
    <Chat.ToolHeader>
      <span>search_components</span>
      <Chat.ToolStatus>Done</Chat.ToolStatus>
    </Chat.ToolHeader>
    <Chat.ToolCall>{'{"query":"chat"}'}</Chat.ToolCall>
    <Chat.ToolResult>Found the DuskMoon Chat primitives.</Chat.ToolResult>
  </Chat.Tool>
  <Chat.Bubble color="primary" streaming>
    Chat is ready for React.
  </Chat.Bubble>
  <Chat.Footer>Delivered</Chat.Footer>
</Chat>);
}
Preview
AI
Assistant · just now
Thinking (2s)
Checking the component catalog before replying.
search_componentsDone
{"query":"chat"}
Found the DuskMoon Chat primitives.
The React chat primitives are ready to compose.
You
You · just now
Show me the live response state.
AI

Exposes named primitives through the compound API

test-backed

Chat scenario from the component test coverage: exposes named primitives through the compound api.

Source
import "@duskmoon-dev/components/styles.css";
import { Chat } from "@duskmoon-dev/components/chat";

export function ChatExposesNamedPrimitivesThroughDemo() {
  return (<Chat aria-live="polite">
  <Chat.Avatar>
    <span className="avatar avatar-sm avatar-info">AI</span>
  </Chat.Avatar>
  <Chat.Header>Assistant · just now</Chat.Header>
  <Chat.Reasoning open>
    <summary>Thinking (2s)</summary>
    <div>Reviewing the component API before answering.</div>
  </Chat.Reasoning>
  <Chat.Tool status="success" open>
    <Chat.ToolHeader>
      <span>search_components</span>
      <Chat.ToolStatus>Done</Chat.ToolStatus>
    </Chat.ToolHeader>
    <Chat.ToolCall>{'{"query":"chat"}'}</Chat.ToolCall>
    <Chat.ToolResult>Found the DuskMoon Chat primitives.</Chat.ToolResult>
  </Chat.Tool>
  <Chat.Bubble color="primary" streaming>
    Chat is ready for React.
  </Chat.Bubble>
  <Chat.Footer>Delivered</Chat.Footer>
</Chat>);
}
Preview
AI
Assistant · just now
Thinking (2s)
Checking the component catalog before replying.
search_componentsDone
{"query":"chat"}
Found the DuskMoon Chat primitives.
The React chat primitives are ready to compose.
You
You · just now
Show me the live response state.
AI

Theme aware

authored

Docs previews inherit the DuskMoon data-theme value. Use the header switch to compare light and dark rendering.

Source
<div data-theme="sunshine">
  <Chat aria-live="polite">
  <Chat.Avatar>
    <span className="avatar avatar-sm avatar-info">AI</span>
  </Chat.Avatar>
  <Chat.Header>Assistant · just now</Chat.Header>
  <Chat.Reasoning open>
    <summary>Thinking (2s)</summary>
    <div>Reviewing the component API before answering.</div>
  </Chat.Reasoning>
  <Chat.Tool status="success" open>
    <Chat.ToolHeader>
      <span>search_components</span>
      <Chat.ToolStatus>Done</Chat.ToolStatus>
    </Chat.ToolHeader>
    <Chat.ToolCall>{'{"query":"chat"}'}</Chat.ToolCall>
    <Chat.ToolResult>Found the DuskMoon Chat primitives.</Chat.ToolResult>
  </Chat.Tool>
  <Chat.Bubble color="primary" streaming>
    Chat is ready for React.
  </Chat.Bubble>
  <Chat.Footer>Delivered</Chat.Footer>
</Chat>
</div>

<div data-theme="moonlight">
  <Chat aria-live="polite">
  <Chat.Avatar>
    <span className="avatar avatar-sm avatar-info">AI</span>
  </Chat.Avatar>
  <Chat.Header>Assistant · just now</Chat.Header>
  <Chat.Reasoning open>
    <summary>Thinking (2s)</summary>
    <div>Reviewing the component API before answering.</div>
  </Chat.Reasoning>
  <Chat.Tool status="success" open>
    <Chat.ToolHeader>
      <span>search_components</span>
      <Chat.ToolStatus>Done</Chat.ToolStatus>
    </Chat.ToolHeader>
    <Chat.ToolCall>{'{"query":"chat"}'}</Chat.ToolCall>
    <Chat.ToolResult>Found the DuskMoon Chat primitives.</Chat.ToolResult>
  </Chat.Tool>
  <Chat.Bubble color="primary" streaming>
    Chat is ready for React.
  </Chat.Bubble>
  <Chat.Footer>Delivered</Chat.Footer>
</Chat>
</div>

API

The API reference below lists every parsed exported type or interface for Chat. Start with `placement`, `color`, `size`, `filled` for common usage.

Types: packages/components/src/components/chat/Chat.types.tsScenarios: packages/components/src/components/chat/Chat.test.tsx
ChatPropsinterface extends ComponentProps<"div">
PropTypeRequiredDescription
placementChatPlacementNoPosition the turn at the start or end of the conversation row.
ChatBubblePropsinterface extends ComponentProps<"div">
PropTypeRequiredDescription
colorChatBubbleColorNoApply a semantic DuskMoon color to the bubble.
sizeChatBubbleSizeNoControl the bubble padding and font size. @default "md"
filledbooleanNoUse the saturated form of the selected color.
streamingbooleanNoShow the live streaming caret after the bubble content.
ChatToolPropsinterface extends ComponentProps<"details">
PropTypeRequiredDescription
statusChatToolStateNoReflect the current tool-call state.
ChatPlacementtype
"start" | "end"
ChatBubbleColortype
| "primary" | "secondary" | "tertiary" | "accent" | "neutral" | "base" | "info" | "success" | "warning" | "error"
ChatBubbleSizetype
"xs" | "sm" | "md" | "lg"
ChatToolStatetype
"pending" | "running" | "success" | "error"
ChatAvatarPropstype
ComponentProps<"div">
ChatHeaderPropstype
ComponentProps<"div">
ChatFooterPropstype
ComponentProps<"div">
ChatReasoningPropstype
ComponentProps<"details">
ChatToolHeaderPropstype
ComponentProps<"summary">
ChatToolStatusPropstype
ComponentProps<"span">
ChatToolCallPropstype
ComponentProps<"div">
ChatToolResultPropstype
ComponentProps<"div">
ChatTypingPropstype
Omit<ComponentProps<"span">, "children">
ChatComponenttype
ChatPartComponent<HTMLDivElement, ChatProps> & { Avatar: ChatPartComponent<HTMLDivElement, ChatAvatarProps>