RichTextEditor
Tiptap-powered rich text editor for formatted content.
Quick Preview
Usage
<RichTextEditor defaultValue="<p>Describe the property.</p>" onChange={setHtml} />Examples
Default RichTextEditor
Use this as the starting point for RichTextEditor. The toolbar covers block styles, marks, colour, lists, alignment, links, quotes, code blocks, images (via URL popover), and undo/redo. Keep product data, routing, fetching, and authorization logic in the consuming app.
In a form field
Pass an id and point a <FieldLabel htmlFor={id}> at it. The editable surface is a contenteditable region rather than a native input, so a plain label can't focus it natively — the editor wires the association itself, so clicking the label still moves focus into the content.
Error state
Set aria-invalid to surface a validation error, matching the other form controls. It applies the danger border/ring and reflects aria-invalid on the textbox for assistive tech. Pair it with FieldError for the message.
With React Hook Form
onChange emits an HTML string (not a DOM event), so wire it up with a Controller rather than register. Forward the field ref to get RHF's focus-on-error behaviour, and spread fieldState into aria-invalid.
import { Controller, useForm } from "react-hook-form";
import { Field, FieldError, FieldLabel } from "@giddaa-housing/ui/field";
import { RichTextEditor } from "@giddaa-housing/ui/rich-text-editor";
function DescriptionField() {
const { control } = useForm({ defaultValues: { description: "" } });
return (
<Controller
name="description"
control={control}
rules={{ required: "A description is required." }}
render={({ field, fieldState }) => (
<Field>
<FieldLabel htmlFor="description">Description</FieldLabel>
<RichTextEditor
id="description"
ref={field.ref}
value={field.value}
onChange={field.onChange}
aria-invalid={fieldState.invalid}
/>
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>
);
}Props
| Prop/API | Type | Default | Description |
|---|---|---|---|
value / defaultValue | string | - | Controlled or uncontrolled HTML content. |
onChange | (html) => void | - | Called with next HTML value on every edit. |
size | `"sm" | "md" | "lg"` |
placeholder | string | writing hint | Empty-state placeholder text. |
disabled | boolean | false | Makes the content read-only and disables the toolbar. |
id | string | - | Associates a <label htmlFor={id}>; clicking it focuses the editor. |
aria-invalid | boolean | false | Marks the field invalid; applies the danger border/ring styling. |
aria-label | string | "Rich text editor" | Accessible name for the editable region. |
ref | RichTextEditorHandle | - | Exposes focus() / blur() for imperative and form-library focus control. |
className | string | - | Local layout or spacing overrides. |
| native/root props | React component props | - | Passed through to the underlying root or primitive. |
Accessibility
- The editable area is a labelled multiline
textbox; the toolbar is a labelledtoolbarwith pressed-state buttons. - Provide visible labels or accessible names for interactive controls.
- Preserve the component-provided focus, keyboard, disabled, and invalid-state behavior.
- Do not communicate state with color alone; include text, icons, or helper copy.