Suncel home pageSuncel v1.0
  1. Richtext

Builder component > RichText


The RichText component allows the user to edit the rich text in real time in the page builder. The rich text is fully customizable: bold, italic, headings, etc...

The rich text is based on Titap, please have a look at the Tiptap documentation.

Property type

The RichText component interacts with a RichTextType property from your Block.

type HTMLContent = string;

type JSONContent = {
    type?: string;
    attrs?: Record<string, any>;
    content?: JSONContent[];
    marks?: {
        type: string;
        attrs?: Record<string, any>;
        [key: string]: any;
    text?: string;
    [key: string]: any;

type Content =
  | HTMLContent
  | { titapType: 'doc'; content: JSONContent | JSONContent[] }
  | null;

type RichTextType = Content;

Component properties

export enum RichTextKey {
  MARK_BOLD = 'bold',
  MARK_CODE = 'code',
  MARK_UNDERLINE = 'underline',
  MARK_HIGHLIGHT = 'highlight',
  MARK_ITALIC = 'italic',
  MARK_LINK = 'link',
  ELEMENT_HEADING = 'heading',
  ELEMENT_H1 = 'h1',
  ELEMENT_H2 = 'h2',
  ELEMENT_H3 = 'h3',
  ELEMENT_H4 = 'h4',
  ELEMENT_H5 = 'h5',
  ELEMENT_H6 = 'h6',
  ELEMENT_UL = 'bulletList',
  ELEMENT_OL = 'orderedList',
  ELEMENT_LI = 'li',
  ELEMENT_LIC = 'lic',
  ALIGN_LEFT = 'align-left',
  ALIGN_CENTER = 'align-center',
  ALIGN_RIGHT = 'align-right',
  ALIGN_JUSTIFY = 'align-justify',

type RichTextMenuElement = {
  element: (props: {
    editor: Editor;
    isMenuFocused: boolean;
    idoc: Document | undefined;
  }) => React.ReactNode;

type RichTextProps = {
  slug: string;
  value: RichTextType;
  allowedFeatures?: RichTextKey[];
  featuresHTMLAttributes?: Partial<Record<RichTextKey, Record<string, any>>>;
  className?: string;
  style?: React.CSSProperties;
  extensions?: Extensions;
  extendedMenu?: RichTextMenuElement[];
  • slug: The slug name of the block property to edit.

    If it's used inside an array ⇒ arraySlug.${index}.richtextSlug

  • value: The value of the property itself.

  • allowedFeatures: The features that the user will be able to use in the rich text. The features will appear on a hover menu when a text is selected. Available features : bold, italic, underline, highlight, code ,ul ,ol ,headings(h1 ,h2 ,h3 ,h4 ,h5 ,h6 ), link.

  • featuresHTMLAttributes: To override the attribute of the features. Specially made for the style.

  • extensions: Add extensions to the rich text. Look at the Tiptap documentation for more detail on creating your own extensions or using the existing ones.

  • extendedMenu: To add your own button in the hover menu.

  • className: The rich text container classname.

  • style: The rich text container style.

Good practices

As the RichText is a component meant to be used in many blocks, It is a good practice to define your own wrapper of the component.

This way, it will prevent you from redefining the style of each rich text feature or the allowedFeatures each time you used it.

Full example

Example of an implementation of the RichText that can be used as a wrapper.

import React from "react";
import { RichTextProps, RichTextKey, RichText } from "@suncel/nextjs/components";
import classes from "./styles.module.scss";

export const CustomRichText: React.FC<RichTextProps> = ({ featuresHTMLAttributes, }) => {
  return (
        [RichTextKey.ELEMENT_HEADING]: {
          class: classes.heading,
        [RichTextKey.ELEMENT_UL]: {
          class: classes.customList,
        [RichTextKey.ELEMENT_PARAGRAPH]: {
          class: classes.pStyle,
        [RichTextKey.MARK_HIGHLIGHT]: {
          class: classes.highlightStyle,

Now our wrapper is setup, we can use it in our blocks.

import React from "react";
import { RichTextType, SuncelBlock } from "@suncel/nextjs";
import { CustomRichText } from "@/suncel/wrappers/richtext";

type RichTextBlockProps = { richText: RichTextType };

export const RichTextBlock: SuncelBlock<RichTextBlockProps> = ({ richText}) => {
  return (
      <CustomRichText slug='richText' value={richText} />

RichTextBlock.suncel = {
  slug: "RichTextBlock",
  displayName: "Rich text",
  defaultProps: {
    richText: "Text to replace",