Composer

Chat composer card with optional context, attachments, editor content, and actions.

Installation

import {
  Composer,
  useComposerEditorSubmit,
} from "@o/pipeline/experimental/components/composer";

Usage

Editor

Composers pair with Editor: Editor.Root wraps the composer — outside Composer.Root, so drafts survive content swaps — and Editor.Content plus Editor.Bubble render inside Composer.EditorBody. The external Editor component and Composer.Editor are intentionally adjacent: Composer.Editor is the composer’s elevated card, while Editor.Root is the editor state owner.

useComposerEditorSubmit adds submission behavior to Composer editors without changing the generic Editor.Root: Enter and ⌘↵ submit when there is content, while Shift+Enter inserts a new paragraph. When the editor is empty or submission is disabled, the keymap yields so the editor handles the key normally. Set preventEmptySubmit when a parent composition has its own Enter behavior that should not run for an empty editor. Use the hook’s submit/canSubmit values to wire Composer.EditorSubmit; the keymap is removed when the calling component unmounts.

const { submit, canSubmit } = useComposerEditorSubmit({ onSubmit, disabled });

Context

Resume

Attachments

Dynamic content

Dynamic content swaps happen directly under Composer.Root, as keyed siblings of the persistent Composer.Header. Composer.Editor is the editor card and contains the EditorAttachments/EditorBody/EditorFooter arrangement. Non-editor views bring their own card surface and padding; there is no generic body slot by design. Use Questionnaire for question views. Composer.Action is generic and can be used in the header, editor footer, or a custom view. Keep dismissal in state too: Esc or a dismiss action simply switches back.

Click the button on the bottom right

Composition

Editor.Root
└── Composer.Root
    ├── Composer.Header
    │   ├── Glyph
    │   ├── Composer.HeaderTitle
    │   ├── Composer.HeaderDescription
    │   └── Composer.Action
    └── Composer.Editor
        ├── Composer.EditorAttachments
        │   └── Attachment.Root
        ├── Composer.EditorBody
        │   ├── Editor.Content
        │   └── Editor.Bubble
        └── Composer.EditorFooter
            ├── Composer.EditorActions
            │   └── Composer.Action
            └── Composer.EditorSubmit