Rich text editor
One line of a CV, edited in place. Bold and links only: the CV template owns every other part of the look.
Playground
Change the controls to try each prop. The code under the preview updates as you go and lists only the props you changed; copy it into your page.
import { RichTextEditor } from '@/ui/rich-text-editor';<RichTextEditor label="Summary" />Default
The field reads as the CV text, with a hovered fill on a 4px radius. Click it, or press Enter on it, to edit: Bold and Link sit above the text, and the text takes the 2px focus ring. Enter or clicking away saves; Escape puts the text back.
import { useState } from 'react';
import { RichTextEditor } from '@/ui/rich-text-editor';
// Maya's summary on her CV. Click it, or Tab to it and press Enter, to edit.
export default function Summary() {
const [summary, setSummary] = useState('Data engineer with **8 years** on streaming platforms at [Northwind](https://northwind.io).');
return (
<div className="flex w-full max-w-120 flex-col gap-050">
<span className="text-body-small leading-body-small font-medium text-text-subtle">Summary</span>
<RichTextEditor label="Summary" value={summary} onSave={setSummary} />
</div>
);
}States
Empty names the field ("Add headline"). Disabled fades to 50% while the CV saves, or for a member without edit rights.
import { useState } from 'react';
import { RichTextEditor } from '@/ui/rich-text-editor';
// Empty names the field; disabled waits while the CV saves or for a member without edit rights.
export default function States() {
const [headline, setHeadline] = useState('');
return (
<div className="flex w-full max-w-120 flex-col gap-200">
<RichTextEditor label="Headline" value={headline} onSave={setHeadline} />
<RichTextEditor label="Current role" value="Lead data engineer, **Northwind**, 2022 to now" onSave={() => {}} disabled />
</div>
);
}Long and non-Latin text
A long line wraps in the read view and the editor. Names in any script keep their characters. A link address that doesn't start with http:// or https:// is refused with a message, and an empty address removes the link.
import { useState } from 'react';
import { RichTextEditor } from '@/ui/rich-text-editor';
// A long line wraps; names in any script keep their characters.
export default function LongText() {
const [line, setLine] = useState(
'Led **Nguyễn Thị Minh Khai** and **王小明** in rebuilding the payments ledger for 14 markets, moving 2.3 billion events a day off batch jobs onto [Apache Flink](https://flink.apache.org) with Zoë O’Brien-Smith.',
);
return (
<div className="w-full max-w-120">
<RichTextEditor label="Role line" value={line} onSave={setLine} />
</div>
);
}