RichTextField

Shows stored HTML sanitized with DOMPurify, or its plain text.

Installation

pnpm dlx shadcn@latest add @chelone/rich-text-input
Loading preview…

<RichTextField> displays stored HTML after sanitizing it with DOMPurify. Use it for formatted content in a show view. To edit that content, use RichTextInput.

In a show view

import { RecordField, Show } from "@chelone/react";
import { RichTextField } from "@/components/rich-text-input/rich-text-field";
 
export const PostShow = () => (
  <Show>
    <RecordField source="body">
      <RichTextField source="body" empty="No content" />
    </RecordField>
  </Show>
);

The rendered HTML sits in a div carrying the rich-text class, which the add-on's stylesheet styles. Import the stylesheet even when you only show values. See Installing the add-on.

Plain text

stripTags displays the text of the sanitized HTML without rendering its elements. For example, <p>Hello <strong>world</strong></p> displays as Hello world:

<RichTextField source="body" stripTags />

Empty values

A missing value or "" shows empty. A string is translated, and in React a node renders as-is. HTML such as <p></p> is still a nonempty string and does not trigger the fallback.

In Vue, empty takes a string. Use the #empty slot for custom content:

<RichTextField source="body">
  <template #empty><span>No content yet</span></template>
</RichTextField>

Vue uses class for React's className and also accepts record, default-value and strip-tags. It has no label, resource or table column props.

What survives sanitizing

DOMPurify runs with core's richTextStyledSanitizeOptions: scripts, event handlers, frames, form controls and a <style> element are removed before the HTML reaches the DOM. Images and colors written by <RichTextInput> come through as they are: an img keeps its src, alt, title and width, and colored text keeps its style.

A style attribute survives only when it is one color declaration with a palette, hex, rgb() or hsl() value. An img whose src is unsafe is removed, and an SVG data URL never counts as safe. Code blocks show plain, with no highlight markup.

See the input page's Images, Text color and Stored HTML sections for what the editor stores, the editor schema, and why the server should sanitize what it stores too.

Props

PropTypeDefaultDescription
cellClassNamestring—A class name to apply to the cell element when used inside `<DataTable>`.
classNamestring—A class name to apply to the root element.
emptyReactNode—The node to display when the field value is empty. Defaults to nothing. A string is translated; a ReactNode renders as-is.
headerClassNamestring—A class name to apply to the header cell element when used inside `<DataTable>`.
labelReactNode—Label to use as column header when using `<DataTable>` or `<SimpleShowLayout>`. Defaults to the capitalized field name. Set to `false` to disable the label.
recordRecordType—The record to render. Defaults to the ambient `RecordContext` value.
resourcestring—The resource name. Defaults to the ambient `ResourceContext` value.
sortableboolean—Disable the header click handler when used inside `<DataTable>`.
sortBystring—The field to sort by when this column head is clicked, if sortable.
sortByOrderSortOrder—The order used for sorting when this column head is clicked, if sortable.
sourceSourceProp<RecordType>—Name of the property to display (dot/bracket path).
stripTagsboolean—Shows the text of the HTML, with no elements.
textAlignTextAlign—The text alignment for the cell content, when used inside `<DataTable>`.

Installing the add-on

This field is part of the rich text add-on:

npx shadcn add @chelone/rich-text-input

For Vue, use npx shadcn-vue add @chelone/rich-text-input. For npm, use @chelone/react/rich-text-input or @chelone/vue/rich-text-input and install the optional peers, of which the field needs dompurify. The input page lists the full set for each adapter and the stylesheet import the rendered HTML needs.