Skip to main content
Gremorie

Chat surface

Conversation plus Message plus Reasoning plus PromptInput, fully composed. The flagship Gremorie AI surface.

Overview

A complete AI chat surface: a streaming conversation log with stick-to-bottom scrolling, user and assistant messages, an expandable reasoning collapsible, and a PromptInput composer at the bottom.

This is the flagship Gremorie block. Wire it to the AI SDK or any streaming endpoint and you get a production-ready chat surface in a single import.

Preview

What did the team ship this week?

The user wants a quick weekly status summary. I'll group the work into 3 buckets: shipped, in-flight, and blockers. Each row stays short for skimmability.

Here is a quick weekly recap: **Shipped** - Auth flow with GitHub provider - Dashboard analytics widget **In flight** - Settings form (3 sections) - Empty state pattern **Blockers** - Waiting on API key for analytics provider

Anatomy

The block composes:

  1. Conversation / ConversationContent - stick-to-bottom scroll log
  2. Message (from "user") - user turn with MessageContent
  3. Reasoning + ReasoningTrigger + ReasoningContent - collapsible thinking step
  4. Message (from "assistant") - assistant turn with markdown-ready MessageContent
  5. PromptInput + PromptInputBody + PromptInputTextarea - composer
  6. PromptInputFooter + PromptInputTools + PromptInputSubmit - actions row

Installation

npx gremorie@latest add block-chat-surface
pnpm dlx gremorie@latest add block-chat-surface
yarn dlx gremorie@latest add block-chat-surface
bunx --bun gremorie@latest add block-chat-surface

Code

'use client';

import {
  Conversation,
  ConversationContent,
  Message,
  MessageContent,
  PromptInput,
  PromptInputBody,
  PromptInputFooter,
  PromptInputSubmit,
  PromptInputTextarea,
  PromptInputTools,
  Reasoning,
  ReasoningContent,
  ReasoningTrigger,
} from '@gremorie/rx-ai';

export function ChatSurface() {
  return (
    <div className="flex h-[560px] w-full flex-col overflow-hidden rounded-lg border bg-card">
      <Conversation>
        <ConversationContent className="px-4 py-6">
          <Message from="user">
            <MessageContent>What did the team ship this week?</MessageContent>
          </Message>
          <Message from="assistant">
            <Reasoning isStreaming={false} duration={2}>
              <ReasoningTrigger />
              <ReasoningContent>
                The user wants a quick weekly status summary. I'll group the
                work into 3 buckets: shipped, in-flight, and blockers.
              </ReasoningContent>
            </Reasoning>
            <MessageContent>{`Here is a quick weekly recap:

**Shipped**
- Auth flow with GitHub provider
- Dashboard analytics widget

**In flight**
- Settings form (3 sections)
- Empty state pattern`}</MessageContent>
          </Message>
        </ConversationContent>
      </Conversation>
      <div className="border-t bg-background p-3">
        <PromptInput onSubmit={() => {}}>
          <PromptInputBody>
            <PromptInputTextarea placeholder="Ask anything..." />
            <PromptInputFooter>
              <PromptInputTools />
              <PromptInputSubmit disabled />
            </PromptInputFooter>
          </PromptInputBody>
        </PromptInput>
      </div>
    </div>
  );
}

Angular edition planned for Phase 5h. Star the repo to track progress.

Customization

  • Wire onSubmit to the AI SDK's sendMessage or your streaming endpoint
  • Stream Reasoning content while isStreaming is true to get auto-collapse on completion
  • Add PromptInputActionMenu for slash commands or attachment buttons
  • Swap MessageContent for MessageResponse (Streamdown) when rendering server-streamed markdown

On this page