Response editor

A multiline message editor that preserves failed drafts and ignores cancelled saves.

AssistantComplete
Two decisions need an owner.

This local example uses recorded response alternatives.

Edit and regenerate a reply

AssistantComplete
Two decisions need an owner.

This local example uses recorded response alternatives.

Use it for

  • Edit a supplied message with an application-owned async save. Failed saves preserve the draft.
  • Compose this editor with ResponseBranch when editing produces another response version. The application owns regenerate requests and history.
  • Escape or Cancel invalidates local pending feedback and calls onCancel.

Avoid

  • Treating local cancellation as cancellation of a backend operation; pass and manage that signal in the application.

React package

npm install @noorddev/vlak-react

Load the stylesheet once at your app root, then import the components you use.

import "@noorddev/vlak-react/css";
import { ResponseEditor } from "@noorddev/vlak-react";

Per-component imports are available at @noorddev/vlak-react/components/response-editor.

Copy the source

npx @noorddev/vlak-cli add response-editor

Adds the component and its dependencies to components/vlak/. Follow the StyleX setup to compile the source in your application.

shadcn registry

npx shadcn add https://vlak.dev/r/response-editor.json

Installs the same source through the shadcn CLI.

import { ResponseEditor } from "@noorddev/vlak-react";

export function EditMessage({ text, onSave, onCancel }: {
  text: string;
  onSave: (text: string) => void | Promise<void>;
  onCancel: () => void;
}) {
  return <ResponseEditor text={text} onSave={onSave} onCancel={onCancel} />;
}

See the integration example to compose these components with your application's model and data.

ResponseEditor

Multiline message editing with async save, cancellation, and failed-draft retention.

PropTypeDefaultDescription
textrequiredstring
onSaverequired(text: string) => void | Promise<void>
onCancelrequired() => void
labelstring"Edit message"
saveLabelstring"Save message"
disabledboolean
onError(error: unknown) => void

Also accepts Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit" | "onError">.

The ref reaches HTMLFormElement.

KeysDoes
TabMoves through the supplied native controls in reading order
Enter, SpaceActivates focused buttons and disclosure summaries
EscapeCancels the editor and invalidates pending feedback
  • Native attributes, className, style, and the forwarded ref reach the outer element.
  • Interactive content requires accessible names; progress text is not announced for every streamed token.

The same styles are available as CSS. Native HTML provides the static presentation; React or application code supplies state updates and actions.

npm install @noorddev/vlak
import "@noorddev/vlak/css";
<form class="rs-response-editor" aria-label="Edit message"><label>Message<textarea>Review the brief</textarea></label><div class="rs-response-editor-actions"><button class="rs-btn-subtle" type="submit">Save message</button></div></form>

Classes

.rs-response-editor.rs-response-editor-actions.rs-response-editor-error