Skip to content
Inputs

Rich Text Editor

A rich text editor that is a contenteditable and a toolbar, and nothing else.

Walkthrough

1. Basic

A contenteditable with a real toolbar on it. value is HTML, bindable, and sanitised on the way in and out — paste from a word processor and the fonts and colours are stripped on arrival.

<script lang="ts">	import { RichTextEditor } from 'omaris';​	let value = $state(		'<p>The kitchen closes at <strong>11pm</strong>, but delivery keeps going until midnight.</p>'	);</script>​<RichTextEditor bind:value placeholder="Describe the issue…" class="w-full" />

2. Tools and status

tools picks the buttons and their order — 'separator' draws a divider — so a comment box can have three and a description field twelve. status counts words and characters along the bottom.

8 words 48 characters
<h3>Release notes</h3><ul><li>Docs pages now show the components.</li></ul>
<script lang="ts">	import { RichTextEditor, Text, type RichTextTool } from 'omaris';​	const COMMENT_TOOLS: RichTextTool[] = ['bold', 'italic', 'separator', 'bulletList', 'link'];​	let comment = $state('');	let html = $state('<h3>Release notes</h3><ul><li>Docs pages now show the components.</li></ul>');</script>​<div class="flex w-full flex-col gap-4">	<RichTextEditor		bind:value={comment}		tools={COMMENT_TOOLS}		size="sm"		height="5rem"		placeholder="Leave a comment…"	/>​	<RichTextEditor bind:value={html} status height="10rem" />​	<Text variant="label-sm" tone="muted" font="mono" class="break-all">{html}</Text></div>

3. Overridden

The rendered HTML is styled through classes.content, not a stylesheet, so a consumer can replace any of it. readOnly keeps the same surface for displaying content that was written elsewhere.

read-only, same surface
<script lang="ts">	import { RichTextEditor, Text } from 'omaris';​	const DOC = `<h3>Refund policy</h3><p>A refund is offered when the order never arrived, or arrived cold.</p><blockquote>Anything past 24 hours goes to support first.</blockquote><ul><li>Card refunds settle in 3–5 days.</li><li>Cash refunds are handled by the courier.</li></ul>`;​	let value = $state(DOC);</script>​<div class="flex w-full flex-col gap-4">	<RichTextEditor		bind:value		height="auto"		classes={{			root: 'rounded-shape-lg border-none bg-surface-container-low',			toolbar: 'bg-transparent',			content:				'min-h-40 [&_h3]:text-title-lg [&_blockquote]:border-s-4 [&_blockquote]:border-primary'		}}	/>​	<div class="flex flex-col gap-1">		<Text variant="label-sm" tone="muted">read-only, same surface</Text>		<RichTextEditor value={DOC} readOnly height="auto" classes={{ content: 'min-h-0' }} />	</div></div>