ToonUI
Packages

@toon-ui/react

Complete API reference for the ToonUI React runtime, renderers, adapters, hooks, helpers, and component props.

@toon-ui/react is the client rendering package.

Use it in React client code to:

  • register the standard ToonUI components your app can render
  • render mixed markdown plus toon-ui blocks
  • capture button replies and form submits
  • convert those interactions into messages for your chat loop

Do not import it from server-only files. Use @toon-ui/core on the server.

Install

pnpm add @toon-ui/react

Main API map

AreaAPIs
RuntimecreateToonReactRuntime, ToonReactRuntime
AdaptercreateToonReactAdapter, createToonAdapter, assertToonReactAdapter, getToonAdapterCoverage, mergeToonComponentRegistry
RenderingToonMessage, ToonRenderer, ToonProvider, ToonError
HooksuseToonUI, useToonAction, useToonReply, useToonSubmit
HelpersextractToonMarkdown, getToonButtonProps, getToonInputProps, getToonTextareaProps, getToonCheckboxProps, getToonFieldId
Props/typescomponent props, payload props, adapter metadata, error state, resolved DOM prop types

Runtime APIs

createToonReactRuntime(options)

Creates the React runtime from registered components or an adapter.

import { createToonReactRuntime } from '@toon-ui/react';

const toon = createToonReactRuntime({
  components: {
    text: TextComponent,
    card: CardComponent,
    form: FormComponent,
    field: FieldComponent,
    button: ButtonComponent,
  },
});

Parameters

OptionTypeRequiredDescription
componentsToonReactComponentRegistryNoReact components keyed by standard ToonUI node type.
adapterToonReactAdapterNoPrebuilt adapter. If provided, it is used instead of creating one from components.
adapterLevel'minimal' | 'default' | 'strict'NoLevel used when creating an internal adapter. Defaults to minimal.
layoutToonReactLayoutOptionsNoSpacing configuration for message, block, and node gaps.

Returns

type ToonReactRuntime = ToonRuntime<ToonReactComponentRegistry> & {
  adapter: ToonReactAdapter;
  layout: {
    messageGap: React.CSSProperties['gap'];
    blockGap: React.CSSProperties['gap'];
    nodeGap: React.CSSProperties['gap'];
  };
};

The runtime includes core APIs too:

  • prompt
  • rules
  • catalog
  • events
  • messages
  • parse
  • validate
  • extractBlocks

Important behavior

createToonReactRuntime requires a configured component catalog. If no components or adapter are provided, it throws.

That is intentional. ToonUI should not let the model generate UI your app did not configure.


ToonReactLayoutOptions

Controls spacing in the default wrapper layout.

const toon = createToonReactRuntime({
  components,
  layout: {
    messageGap: 20,
    blockGap: 16,
    nodeGap: 12,
  },
});
OptionMeaningDefault
messageGapgap between ordered markdown/UI segments in ToonMessage16
blockGapgap between rendered ToonUI blocks16
nodeGapgap between nodes inside block containers12

Adapter APIs

createToonReactAdapter(options)

Creates an adapter object around a component registry.

const adapter = createToonReactAdapter({
  level: 'strict',
  components: {
    text: TextComponent,
    card: CardComponent,
    form: FormComponent,
    field: FieldComponent,
    button: ButtonComponent,
  },
});

Parameters

OptionTypeRequiredDescription
componentsToonReactComponentRegistryNoComponent registry.
level'minimal' | 'default' | 'strict'NoCoverage behavior. Defaults to minimal.

Returns

type ToonReactAdapter = {
  components: ToonReactComponentRegistry;
  meta: ToonReactAdapterMeta;
};

Adapter levels

LevelBehavior
minimalonly components you pass are registered
strictthrows if any adapter key is missing

Use minimal for explicit production integration. Use strict when design-system coverage must be complete.


createToonAdapter

Alias for createToonReactAdapter.

const adapter = createToonAdapter({ components });

getToonAdapterCoverage(components, level?)

Computes adapter coverage metadata.

const meta = getToonAdapterCoverage(components, 'minimal');

Returns

type ToonReactAdapterMeta = {
  level: 'minimal' | 'default' | 'strict';
  isComplete: boolean;
  providedKeys: ToonReactAdapterComponentKey[];
  missingKeys: ToonReactAdapterComponentKey[];
};

Use it for diagnostics, tests, or integration health checks.


assertToonReactAdapter(adapter)

Returns the adapter when valid. Throws when adapter.meta.level === 'strict' and coverage is incomplete.

assertToonReactAdapter(adapter);

mergeToonComponentRegistry(...registries)

Merges registries from left to right.

const components = mergeToonComponentRegistry(baseComponents, overrides);

Later registries override earlier ones.



Rendering APIs

ToonMessage

Renders mixed assistant output: markdown plus fenced toon-ui blocks.

<ToonMessage
  content={content}
  runtime={toon}
  renderMarkdown={(markdown) => <MessageResponse>{markdown}</MessageResponse>}
  renderError={(error) => <MyError details={error.details} />}
  onReply={(payload) => append(toon.messages.toUIMessage(payload))}
  onSubmit={(payload) => append(toon.messages.toUIMessage(payload))}
/>

Props

PropTypeRequiredDescription
contentstringYesAssistant output containing markdown and optional toon-ui fenced blocks.
runtimeToonReactRuntimeYesRuntime created with createToonReactRuntime.
onReply(payload: ToonReplyPayload) => voidNoCalled when a reply button is clicked.
onSubmit(payload: ToonSubmitPayload) => voidNoCalled when a form is submitted.
renderMarkdown(markdown: string) => React.ReactNodeNoCustom markdown renderer. Defaults to react-markdown.
interactivebooleanNoEnables/disables interactions. Defaults to true.
renderErrorToonErrorRendererNoCustom parse/validation error renderer.
showErrorDetailsbooleanNoShows validation/parse details in default error UI. Defaults to false.

Markdown responsibility

ToonMessage can render markdown with a default renderer, but real apps usually pass their own renderMarkdown so prose matches the rest of the chat UI.


ToonRenderer

Renders only toon-ui blocks from content. It ignores markdown.

<ToonRenderer
  content={content}
  runtime={toon}
  onReply={handleReply}
  onSubmit={handleSubmit}
/>

Props

PropTypeRequiredDescription
contentstringYesContent containing one or more toon-ui blocks.
runtimeToonReactRuntimeYesRuntime created with createToonReactRuntime.
onReply(payload: ToonReplyPayload) => voidNoCalled for reply interactions.
onSubmit(payload: ToonSubmitPayload) => voidNoCalled for form submissions.
interactivebooleanNoEnables/disables interactions.
renderErrorToonErrorRendererNoCustom parse/validation error renderer.
showErrorDetailsbooleanNoShows details in default error UI.

Use ToonRenderer when your app renders markdown separately.


ToonProvider

Provides runtime and interaction context for lower-level custom rendering.

<ToonProvider runtime={toon} onReply={handleReply} onSubmit={handleSubmit}>
  {children}
</ToonProvider>

Props

PropTypeRequiredDescription
runtimeToonReactRuntimeYesRuntime instance.
childrenReact.ReactNodeYesDescendant render tree.
onReply(payload: ToonReplyPayload) => voidNoReply callback.
onSubmit(payload: ToonSubmitPayload) => voidNoSubmit callback.
interactivebooleanNoWhen false, interactions are disabled/resolved. Defaults to true.

ToonMessage and ToonRenderer already use ToonProvider internally.


ToonError

Default error display component.

<ToonError message="This interface could not be displayed." details={details} />
PropTypeRequiredDescription
messagestringYesMain error message.
detailsstring[]NoOptional error details.

Hook APIs

useToonUI()

Returns the current ToonReactRuntime from context.

const runtime = useToonUI();

Throws if used outside ToonProvider.


useToonReply()

Returns the reply dispatcher from render context.

const sendReply = useToonReply();

Throws if used outside ToonProvider.


useToonSubmit()

Returns the form submit dispatcher from render context.

const submitForm = useToonSubmit();

Throws if used outside ToonProvider.


useToonAction()

Returns protocol helpers from the current runtime.

const { events, messages } = useToonAction();

Use this inside custom components when you need event/message helpers without importing a separate runtime.


Helper APIs

extractToonMarkdown(content)

Returns only markdown prose from mixed content, stripping toon-ui blocks.

const markdown = extractToonMarkdown(content);

Use it when rendering markdown and ToonUI separately.


getToonFieldId(node)

Creates a stable field id from a field node.

const id = getToonFieldId(props.node);

Returns string in the form <field-name>-<line>.


getToonButtonProps(props)

Returns normalized DOM props for a button component.

function ButtonComponent(props: ToonButtonComponentProps) {
  return <button {...getToonButtonProps(props)}>{props.node.label}</button>;
}

Returns

type ToonResolvedButtonProps = Pick<
  React.ButtonHTMLAttributes<HTMLButtonElement>,
  'type' | 'disabled' | 'onClick'
>;

It handles:

  • disabled state
  • reply actions
  • submit actions

getToonInputProps(props)

Returns normalized props for text-like inputs.

<input {...getToonInputProps(props)} />

It handles:

  • id/name
  • input type
  • required/disabled
  • placeholder
  • value
  • numeric conversion for number fields
  • change dispatch

When the parsed ToonUI field includes value="...", @toon-ui/react uses that parsed value as the initial controlled input value.


getToonTextareaProps(props)

Returns normalized props for textarea fields.

<textarea {...getToonTextareaProps(props)} />

getToonCheckboxProps(props)

Returns normalized props for checkbox fields.

<input {...getToonCheckboxProps(props)} />

It maps checked to the current field value and dispatches boolean changes.


Component registry

The registry maps standard ToonUI node types to React components.

type ToonReactComponentRegistry = Partial<{
  [K in keyof ToonReactComponentPropsByType]: React.ComponentType<ToonReactComponentPropsByType[K]>;
}>;

Specialized props exist for the common components that need interaction wiring.

Shared base props

Most component props include:

PropMeaning
nodeParsed AST node for that component.
childrenRendered child nodes, when the component supports children.
contextLow-level render context.
disabledWhether the block has already resolved or interactivity is disabled.

Specialized component props

ToonTextComponentProps

type ToonTextComponentProps = {
  node: TextNode;
  context: ToonRenderContextValue;
  disabled?: boolean;
};

Use node.value for visible text.


ToonCardComponentProps

type ToonCardComponentProps = {
  node: CardNode;
  children?: React.ReactNode;
  context: ToonRenderContextValue;
  disabled?: boolean;
};

Use node.title, optional node.description, and children.


ToonFormComponentProps

type ToonFormComponentProps = {
  node: FormNode;
  children?: React.ReactNode;
  context: ToonRenderContextValue;
  submitForm: () => void;
  values: Record<string, ToonFieldValue>;
  disabled: boolean;
};

Use submitForm if your form shell owns the submit button. In most generated forms, submit is usually triggered by a button submit child.


ToonFieldComponentProps

type ToonFieldComponentProps = {
  node: FieldNode;
  context: ToonRenderContextValue;
  value: ToonFieldValue | undefined;
  onChange: (value: ToonFieldValue) => void;
  disabled: boolean;
};

Use getToonInputProps, getToonTextareaProps, or getToonCheckboxProps to wire inputs.


ToonButtonComponentProps

type ToonButtonComponentProps = {
  node: ButtonNode;
  context: ToonRenderContextValue;
  sendReply: (reply?: string) => void;
  submitForm: () => void;
  disabled: boolean;
};

Use getToonButtonProps unless you need custom interaction behavior.


Other specialized props

TypeNode
ToonConfirmComponentPropsConfirmNode
ToonListComponentPropsListNode
ToonItemComponentPropsItemNode
ToonBadgeComponentPropsBadgeNode
ToonAlertComponentPropsAlertNode
ToonTableComponentPropsTableNode
ToonEmptyComponentPropsEmptyNode

For less-common nodes, use:

type ToonGenericComponentProps<'heading'>

or:

type ToonTypedNode<'heading'>

Payload types

ToonReplyPayload

Extends core ReplyPayload with the originating ButtonNode.

type ToonReplyPayload = ReplyPayload & {
  node: ButtonNode;
};

ToonSubmitPayload

Extends core SubmitPayload with the originating FormNode.

type ToonSubmitPayload = SubmitPayload & {
  node: FormNode;
};

Error types

ToonRenderErrorState

Passed to renderError.

type ToonRenderErrorState = {
  kind: 'parse' | 'validation';
  block: ToonBlock;
  message: string;
  details: string[];
  cause?: unknown;
};

ToonErrorRenderer

type ToonErrorRenderer = (error: ToonRenderErrorState) => React.ReactNode;

On this page