editorcn pro

Chat Composer

A chat interface with streaming replies, message actions, attachments and a model picker, built on the editor.

A chat interface built on the editor: a centered thread, a rounded input with a bubble menu for formatting that cleans up pasted web content, copy, edit and regenerate actions on each message, streaming replies with a stop button, image attachments and an optional model picker.

Installation

$ pnpm dlx shadcn@latest add @editorcn-pro/chat-composer

Usage

onSend receives the user's message as Tiptap JSON. Return the reply as plain text, as Tiptap JSON, or as an async iterable of text chunks to stream it. The signal aborts when the user presses stop. Throw to mark the message as failed so it can be retried.

import { ChatComposer } from "@/components/templates/chat-composer";
 
export const Chat = () => (
  <ChatComposer
    onSend={async function* (content, { signal }) {
      const res = await fetch("/api/chat", {
        body: JSON.stringify(content),
        method: "POST",
        signal,
      });
      const reader = res.body!.pipeThrough(new TextDecoderStream()).getReader();
      for (;;) {
        const { done, value } = await reader.read();
        if (done) return;
        yield value;
      }
    }}
  />
);

Attachments and models

Set attachments to let people add files with the + button, by pasting, or by dropping them on the input. Files arrive in onSend as files; uploading them is up to your backend. Pass models to show a model picker; the selected value arrives as model.

<ChatComposer
  attachments
  models={[
    { icon: <ClaudeIcon />, label: "Claude Opus", value: "claude-opus" },
    { icon: <ClaudeIcon />, label: "Claude Sonnet", value: "claude-sonnet" },
  ]}
  onSend={(content, { files, model, signal }) =>
    sendToYourApi({ content, files, model, signal })
  }
/>

Props

PropTypeDescription
onSendfunctionGets the message, returns the reply
initialMessagesChatMessage[]Messages shown on open
attachmentsbooleanAccept picked, pasted and dropped files
acceptstringAllowed file types, default image/*
maxFilesnumberFiles per message, default 4
modelsChatModel[]Items for the model picker
defaultModelstringModel value selected at first
onModelChangefunctionGets the new model value
suggestionsstring[]Prompts before the first message
placeholderstringInput placeholder
disclaimerstringText under the input, "" hides it
classNamestringOuter container classes