---
title: "rich-text"
image: "https://adonia.pages.dev/og.png"
version: "next"
---

> Documentation Index
> Fetch the complete documentation index at: https://adonia.pages.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# rich-text

<!-- Generated by `pnpm docs:fields` from packages/core/src/schema/fields/rich_text.ts. Edit the TSDoc, not this file. -->

WYSIWYG editor storing sanitized HTML.

The toolbar preset and the sanitizer allowlist are INDEPENDENT, and
deliberately so. The preset decides which buttons the editor renders; the
allowlist decides which markup survives the server. A narrow toolbar is a
usability choice a client can always be talked out of — by a paste, by a
bug, by a crafted request — so it is never load-bearing for safety.
Narrowing what may be STORED is `RichTextField.sanitize`'s job.

| | |
| --- | --- |
| Builder | `F.richText(attribute: string): RichTextField` |
| Wire type key | `rich-text` |
| Class chain | `RichTextField` → `Field` |
| Detail projection | `html` |
| Column counterpart | — *(not tabulatable)* |

## Example

```ts
import { DEFAULT_SANITIZE_CONFIG, F } from '@adonia/core'

F.richText('body')
  .label('Body')
  .toolbar('full')
  .sanitize({ allowedTags: [...DEFAULT_SANITIZE_CONFIG.allowedTags, 'figure'] })
```

## Props

Beyond the shared [field DSL](/reference/fields#the-shared-field-dsl):

| Prop | Declared on | Behaviour |
| --- | --- | --- |
| `toolbar(preset: RichTextToolbar): this` | `RichTextField` | Selects the editor's toolbar preset (§7.3); `standard` by default. |
| `sanitize(overrides: Partial<AdoniaSanitizeConfig>): this` | `RichTextField` | Overrides the sanitizer allowlist for THIS field (§7.3 "allowlist configurable"), on top of `DEFAULT_SANITIZE_CONFIG`. |
| `rows(count: number): this` | `RichTextField` | Initial editor height in rows; the client's default applies when unset. |

### Introspection

Read-only members this type adds — used by the compiler, the table derivation and
tests rather than by a schema author.

| Member | Declared on | Behaviour |
| --- | --- | --- |
| `get sanitizePolicy(): CompiledSanitizePolicy` | `RichTextField` | The compiled allowlist this field sanitizes against (§19). |

## Validation

Vine base: `vine.string()`.

§11.1 mapping: `vine.string()` with the declared length bounds.

`maxLength` counts MARKUP characters, not rendered text — the value is
HTML, and there is nothing else to count before the sanitizer has run.
No `trim()`: whitespace between block elements is insignificant anyway,
and trimming would make the sanitizer's output differ from its input
for reasons unrelated to safety.

Contributed by `RichTextField.vineSchema()` in `packages/core/src/schema/fields/rich_text.ts`. The shared modifiers (`required`, `nullable`, `requiredWhen`, `unique`, optionality) are applied on top by `Field.buildValidation`, and a `rules()` override replaces the base entirely — the validator compiler never branches on the field class.

## Declared in

- `packages/core/src/schema/fields/rich_text.ts` — `RichTextField`

Source: https://adonia.pages.dev/reference/fields/rich-text/index.mdx
