Rich Text Parameter Utilities

Rich text parameters store structured content with formatting (headings, lists, links, bold, italic, etc.) managed through the Uniform rich text editor. The SDK provides the UniformRichText component and the @uniformdev/richtext package for working with rich text data.

Uniform provides a Vanilla JS rich text-to-HTML renderer as well as components for React and Vue, plus framework-specific packages for Next.js and Nuxt. Each option lets you override how individual rich text nodes are rendered. The examples on this page use React; for Vue and Nuxt, see UniformRichText in the Nuxt SDK.

The UniformRichText component renders rich text parameters with full formatting support and inline editing capabilities in the Uniform visual editor:

import { ComponentParameter, ComponentProps, UniformRichText, } from "@uniformdev/next-app-router/component"; import { ParameterRichTextValue } from "@uniformdev/richtext"; type ArticleProps = { body?: ComponentParameter<ParameterRichTextValue>; }; export const ArticleComponent = ({ parameters: { body }, component, }: ComponentProps<ArticleProps>) => { return ( <article> <UniformRichText component={component} parameter={body} className="prose" placeholder="Write your article content here" /> </article> ); };
PropTypeDefaultDescription
componentPick<ComponentContext, '_id'>requiredComponent context (from ComponentProps)
parameterComponentParameter<ParameterRichTextValue>requiredThe rich text parameter value
asReact.ElementType"div"Wrapper HTML element. Set to null for no wrapper.
classNamestringCSS class applied to the wrapper
placeholderstring | ((parameter) => string)Placeholder text shown in the editor when empty
resolveRichTextRendererRenderRichTextComponentResolverCustom renderer for rich text nodes

The RenderRichTextComponentResolver type is not exported from the public API, so you cannot import it directly. It has the shape (node: RichTextNode) => RichTextRendererComponent | null | undefined, where returning null or undefined falls back to the default renderer for that node type.

Because the rich text value is a structured JSON object rather than a string, checking whether it's empty is more involved than comparing against an empty string or undefined. Use isRichTextValueConsideredEmpty from @uniformdev/richtext to guard rendering:

import { UniformRichText } from "@uniformdev/next-app-router/component"; import { isRichTextValueConsideredEmpty } from "@uniformdev/richtext"; isRichTextValueConsideredEmpty(body?.value) ? null : ( <UniformRichText component={component} parameter={body} /> );

By default, UniformRichText maps rich text nodes to standard HTML elements. You can override the rendering of specific node types using resolveRichTextRenderer:

import { linkParamValueToAnchorProps } from "@uniformdev/canvas-react"; import { RichTextNode, isRichTextNodeType } from "@uniformdev/richtext"; const customResolver = (node: RichTextNode) => { // Custom heading rendering if (node.type === "heading") { return ({ node, children }) => { const tag = node.tag || "h2"; const Tag = tag as keyof JSX.IntrinsicElements; return <Tag className="font-display text-brand">{children}</Tag>; }; } // Custom link rendering if (node.type === "link") { return ({ node, children }) => { // Narrow to a link node so `node.link` is available under strict TS if (!isRichTextNodeType(node, "link")) return null; return ( <a {...linkParamValueToAnchorProps(node.link)} className="text-blue-600 underline hover:text-blue-800" > {children} </a> ); }; } // Return undefined to use default renderer return undefined; }; // Usage: <UniformRichText component={component} parameter={body} resolveRichTextRenderer={customResolver} />

Link nodes carry the link value on node.link ({ type, path, nodeId?, projectMapId?, attributes? }). The linkParamValueToAnchorProps helper from @uniformdev/canvas-react converts it to React anchor props: it derives the href and includes any custom link attributes set by the editor (such as target, rel, or data-*), applying the built-in safeguards (security filtering, automatic rel="noopener noreferrer", and class to className translation) described in Link Parameter Utilities. The default link renderer applies the same behavior. Outside React (Vue, Nuxt, or HTML string output), use linkParamValueToHtmlAttributes from @uniformdev/richtext, which returns a plain attribute record.

Note that a custom className prop as in the example above overrides any class attribute set on the link by the editor; merge the two values if you need both.

The UniformRichText component looks up its value from the current component, so it does not resolve rich text that is nested inside a block parameter. When you already have a rich text node — such as one nested in a block — render it directly with UniformRichTextNode.

A rich text value looks like this, with the top-level node available on richTextValue.root:

const richTextValue = { root: { type: "root", version: 1, children: [ { type: "paragraph", version: 1, children: [ { type: "text", version: 1, text: "text", }, ], }, ], }, };

Pass the root node (or any child node) to UniformRichTextNode:

import { UniformRichTextNode } from "@uniformdev/canvas-react"; <UniformRichTextNode node={richTextValue.root} />;

The SDK provides default renderers for these rich text node types:

Node TypeDefault Rendering
heading<h1> through <h6> based on tag level
paragraph<p>
textInline text with formatting (bold, italic, underline, etc.)
link<a>
list<ul> or <ol>
listitem<li>
quote<blockquote>
code<pre><code>
linebreak<br>
table<table><tbody>
tablerow<tr>
tablecell<td> or <th>
asset<img> or media element
tabTab content wrapper

The table, tablerow, and tablecell nodes require Uniform SDKs >= 19.181.1, and the asset node requires >= 19.187.0.

Some nodes carry additional properties that are useful when writing custom renderers. Each listed helper is exported from @uniformdev/richtext.

Node typeAdditional propertiesNotes
headingtag: 'h1''h6'Use tag to pick the heading level.
paragraphformat (optional): 'center' | 'end' | 'justify' | 'left' | 'match-parent' | 'right' | 'start'; direction (optional): 'ltr' | 'rtl' | nullUse isPureTextAlign and isPureDirection to decide whether format and direction should be applied to the style and dir attributes.
listtag: 'ul' | 'ol'; start: numberIf start is > 1, set it as the list's start attribute.
listitemvalue: numberIf value is > 0, set it as the list item's value attribute.
linklink: { type: 'projectMapNode' | 'url' | 'tel' | 'email'; path: string; nodeId?: string; projectMapId?: string; attributes?: Record<string, string>; }path may include a #fragment anchor, and attributes holds any custom link attributes set by the editor. See Custom rich text node renderers for how to keep the default link behavior.
tablecellheaderState: number0: no header, 1: row header, 2: column header, 3: row and column header. Use getRichTextTagFromTableCellHeaderState to derive the tag.
textformat: number; text: stringUse getRichTextTagsFromTextFormat to get the list of tags for a text node from its format.
asset__assetProperties of the embedded asset.

For non-visual use cases (SEO meta descriptions, search indexing, summaries), use renderToText from @uniformdev/richtext:

import { renderToText } from "@uniformdev/richtext"; // richTextValue is the raw ParameterRichTextValue const plainText = renderToText(richTextValue);

For server-side HTML generation (e.g., RSS feeds, emails), use renderToHtml:

import { renderToHtml } from "@uniformdev/richtext"; const htmlString = renderToHtml(richTextValue);

You can override node renderers when generating an HTML string by passing a resolveRenderer:

import { renderToHtml } from "@uniformdev/richtext"; function myParagraphRenderer({ context, renderChildren }) { return `<p class="my-paragraph">${renderChildren(context.currentNode.children)}</p>`; } const html = renderToHtml(richTextValue.root, { resolveRenderer({ currentNode }) { if (currentNode.type === "paragraph") { return myParagraphRenderer; } }, });
ExportPackageDescription
UniformRichText@uniformdev/next-app-router/componentReact component for rendering rich text
UniformRichTextNode@uniformdev/canvas-reactRender a rich text node directly (e.g. rich text nested in a block parameter)
ParameterRichTextValue@uniformdev/richtextType for rich text parameter values
renderToText@uniformdev/richtextConvert rich text to plain text
renderToHtml@uniformdev/richtextConvert rich text to HTML string
walkRichTextTree@uniformdev/richtextWalk and transform the rich text node tree
isRichTextValue@uniformdev/richtextType guard for rich text values
isRichTextNode@uniformdev/richtextType guard for a rich text node starting from the root node
isRichTextNodeType@uniformdev/richtextCheck whether a node is of a given type
isRichTextValueConsideredEmpty@uniformdev/richtextCheck if rich text is empty
isPureTextAlign@uniformdev/richtextCheck whether a paragraph format value maps to a text alignment
isPureDirection@uniformdev/richtextCheck whether a paragraph direction value should be applied
getRichTextTagFromTableCellHeaderState@uniformdev/richtextGet the tag name (td/th) for a table cell from its headerState
getRichTextTagsFromTextFormat@uniformdev/richtextGet the list of tags for a text node from its format
linkParamValueToHref@uniformdev/richtextConvert a link value to a href string (adds the mailto:/tel: prefix for email and telephone links)
linkParamValueToHtmlAttributes@uniformdev/richtextConvert a link value to a sanitized HTML attribute record (href plus custom link attributes)
linkParamValueToAnchorProps@uniformdev/canvas-reactConvert a link value to React anchor props (class becomes className)