Developer
Get Support
Sign in
Get Support
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
UI Kit components
Jira UI Kit components
UI Kit hooks
Forge bridge APIs
Jira bridge APIs
Confluence bridge APIs
Dashboard bridge APIs (EAP)
Upgrade UI Kit versions
Last updated Oct 14, 2025

Comment editor (EAP)

Editor components are now available as an Early Access Program (EAP). To start testing these components, sign up using this form.

Editor components are currently only available in Confluence and Jira modules.

Forge’s EAP offers experimental features to selected users for testing and feedback purposes. These features are unsupported and not recommended for use in production environments. They are also subject to change without notice.

For more details, see Forge EAP, Preview, and GA.

To add the CommentEditor component to your app:

1
2
import { CommentEditor } from "@forge/react";

Description

The comment editor provides a contained comment editor UI with a simple toolbar.

Props

NameTypeRequiredDescription
defaultValueJSONDocNodeNoSets the default editor content.
featuresFeaturesNoSets the enabled features in the editor. If not set, all editor features are enabled. See Features for a list of features.
isDisabledbooleanNoDisables the editor.
onChange(value?: JSONDocNode) => voidNoThe handler that is called when the content in the editor changes.
onSave(value?: JSONDocNode) => voidNoRenders a Save button at the bottom of the editor. Handler is called when this button is clicked.
onCancel() => voidNoRenders a Cancel button at the bottom of the editor. Handler is called when this button is clicked.

Features

You can use the features prop to enable or disable specific editor features. In the comment editor, disabling features removes them from the toolbar, as well as stops them from being able to be used in the editor itself. The following features are available:

PropertyTypeDescription
blockTypebooleanEnables different text types, including headings and quote blocks.
textFormattingbooleanEnables different formatting, such as bold and italic.
listbooleanEnables lists to be inserted.
textColorbooleanEnables different colors to be applied to the text.
hyperLinkbooleanEnables hyperlinks when pasting links.
codeBlockbooleanEnables code blocks to be inserted.
insertBlockbooleanDisplays the link, codeblock, and quoteblock options in the toolbar.
quickInsertbooleanAllows quick insertions of a block type via the / shortcut.

Examples

Default appearance

Example image of comment editor

1
2
export const CommentEditorExample = () => {
  return <CommentEditor />;
};

Enabling and disabling features

By default, all editor features are enabled. To enable certain features and disable the rest, you must pass in the features object with the specific features you want to enable.

Example image of comment editor with custom features

1
2
export const CommentEditorWithToggledFeaturesExample = () => {
  return (
    <CommentEditor
      features={{
        blockType: true,
        textFormatting: true,
        textColor: true,
        list: true,
      }}
    />
  );
};

Action buttons

The onSave prop will render a Save button for the user to interact with. Upon clicking, the value can be stored in state. onCancel will render a Cancel button that fires a callback.

Example image of comment editor with save and cancel buttons

1
2
const CommentEditorWithActionButtons = () => {
  const [savedContent, setSavedContent] = useState();

  return (
    <>
      <CommentEditor
        onSave={(value) => {
          setSavedContent(value);
        }}
        onCancel={() => {
          // handle cancel
        }}
      />
    </>
  );
};

onChange

To access the input value of the editor while it's being edited, onChange can be used.

Example image of comment editor using onchange

1
2
const CommentEditorWithActionButtons = () => {
  const [editorValue, setEditorValue] = useState();

  return (
    <>
      <CommentEditor onChange={(value) => setEditorValue(value)} />
      <Box paddingBlockStart="space.100">
        <Button
          onClick={() => {
            console.log(editorValue);
          }}
        >
          Submit
        </Button>
      </Box>
    </>
  );
};

Default value

To set a default value in the editor, pass in the defaultValue prop. This will be the initial content within the editor.

Example image of comment editor with default value

1
2
const editorValue = {
  version: 1,
  type: "doc",
  content: [
    {
      type: "heading",
      attrs: {
        level: 1,
      },
      content: [
        {
          type: "text",
          text: "Heading",
        },
      ],
    },
    {
      type: "blockquote",
      content: [
        {
          type: "paragraph",
          content: [
            {
              type: "text",
              text: "Quote block",
            },
          ],
        },
      ],
    },
    {
      type: "codeBlock",
      attrs: {
        language: "javascript",
      },
      content: [
        {
          type: "text",
          text: "const foo = 'bar'",
        },
      ],
    },
  ],
};

const CommentEditorWithDefaultValue = () => {
  return (
    <>
      <CommentEditor defaultValue={editorValue} />
    </>
  );
};

Disabled editor

To disable the editor, pass in the isDisabled prop. This will disable all interactions with the editor.

Example image of comment editor disabled

1
2
const CommentEditorDisabled = () => {
  return (
    <>
      <CommentEditor isDisabled />
    </>
  );
};

Example with ADF Renderer

The CommentEditor can be used together with the AdfRenderer component to display the content of a submitted value in a read-only format. This is useful for displaying the content of the editor after it has been saved.

Example image of comment editor with adf renderer Example image of comment editor with adf renderer

1
2
import { useState } from "react";
import { CommentEditor, AdfRenderer, Button, Box } from "@forge/react";

const pressableStyles = xcss({
  marginTop: "space.200",
  color: "color.text.subtle",
  fontWeight: "font.weight.bold",
  padding: "space.100",
  borderRadius: "border.radius",
  ":hover": {
    backgroundColor: "color.background.neutral.subtle.hovered",
    color: "color.text",
  },
});

export const PressableExample = () => {
  const [showEditor, setShowEditor] = useState(false);
  const [comment, setComment] = useState(undefined);
  return (
    <>
      {comment && !showEditor ? <AdfRenderer document={comment} /> : null}
      {showEditor ? (
        <CommentEditor
          defaultValue={comment}
          onSave={(content) => {
            setComment(content);
            setShowEditor(false);
          }}
          onCancel={() => setShowEditor(false)}
        />
      ) : (
        <Pressable xcss={pressableStyles} onClick={() => setShowEditor(true)}>
          {comment ? "Edit comment" : "Add comment"}
        </Pressable>
      )}
    </>
  );
};

Rate this page: