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.
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;
export enum RichTextKey {
MARK_BOLD = 'bold',
MARK_CODE = 'code',
MARK_UNDERLINE = 'underline',
MARK_HIGHLIGHT = 'highlight',
MARK_ITALIC = 'italic',
MARK_LINK = 'link',
ELEMENT_PARAGRAPH = 'p',
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.
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.
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, ...rest }) => {
return (
<RichText
allowedFeatures={[
RichTextKey.ELEMENT_H1,
RichTextKey.ELEMENT_H2,
RichTextKey.ELEMENT_H3,
RichTextKey.MARK_BOLD,
RichTextKey.MARK_ITALIC,
RichTextKey.MARK_CODE,
RichTextKey.MARK_HIGHLIGHT,
RichTextKey.ELEMENT_UL,
RichTextKey.ELEMENT_OL,
RichTextKey.MARK_LINK,
RichTextKey.ALIGN_LEFT,
RichTextKey.ALIGN_CENTER,
RichTextKey.ALIGN_RIGHT,
RichTextKey.ALIGN_JUSTIFY,
]}
featuresHTMLAttributes={{
[RichTextKey.ELEMENT_HEADING]: {
class: classes.heading,
},
[RichTextKey.ELEMENT_UL]: {
class: classes.customList,
},
[RichTextKey.ELEMENT_PARAGRAPH]: {
class: classes.pStyle,
},
[RichTextKey.MARK_HIGHLIGHT]: {
class: classes.highlightStyle,
},
...featuresHTMLAttributes,
}}
{...rest}
/>
);
};
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",
},
};