Rich Text Editor

Editor producing formatted text.

Great work this sprint, the launch went smoothly.

html

<div class="rte" style="--accent:#A8E6C1;">
  <div class="rte__toolbar rte__toolbar--full" data-density="full" role="toolbar" aria-label="Formatting">
    <button type="button" class="rte__btn" aria-pressed="true" aria-label="Bold"><strong>B</strong></button>
    <button type="button" class="rte__btn" aria-pressed="false" aria-label="Italic"><em>I</em></button>
    <button type="button" class="rte__btn rte__btn--extra" aria-label="Underline"><span class="rte__u">U</span></button>
    <button type="button" class="rte__btn rte__btn--extra" aria-label="Bulleted list">&#8801;</button>
  </div>
  <div class="rte__body" contenteditable="true" role="textbox" aria-multiline="true" aria-label="Document content" style="font-weight:700;font-style:normal;">Great work this sprint, the launch went smoothly.</div>
</div>
<style>
.rte { font-family: system-ui, sans-serif; color: #241430; background: #FAF7F2; border: 1.5px solid #24143020; border-radius: 10px; overflow: hidden; max-width: 380px; }
.rte__toolbar { display: flex; gap: 2px; padding: 6px; border-bottom: 1.5px solid #24143020; }
.rte__btn { width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; border: none; background: transparent; border-radius: 6px; cursor: pointer; }
.rte__btn[aria-pressed="true"] { background: var(--accent); }
.rte__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.rte__u { text-decoration: underline; }
.rte__toolbar--compact .rte__btn--extra { display: none; }
.rte__body { padding: 14px 16px; font-size: 15px; line-height: 1.6; min-height: 3em; }
.rte__body:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
</style>

tailwind

<div class="rte-tw max-w-[380px] bg-[#FAF7F2] text-[#241430] font-sans border-[1.5px] border-[#24143020] rounded-[10px] overflow-hidden" style="--accent:#A8E6C1;">
  <div class="rte-tw__toolbar flex gap-0.5 p-1.5 border-b-[1.5px] border-[#24143020]" data-density="full" role="toolbar" aria-label="Formatting">
    <button type="button" class="w-7 h-7 inline-flex items-center justify-center rounded-md border-0 bg-transparent cursor-pointer" aria-pressed="true" aria-label="Bold" style="background:#A8E6C1"><strong>B</strong></button>
    <button type="button" class="w-7 h-7 inline-flex items-center justify-center rounded-md border-0 bg-transparent cursor-pointer" aria-pressed="false" aria-label="Italic" style="background:"><em>I</em></button>
    <button type="button" class="rte-tw__extra w-7 h-7 inline-flex items-center justify-center rounded-md border-0 bg-transparent cursor-pointer" aria-label="Underline"><span class="underline">U</span></button>
    <button type="button" class="rte-tw__extra w-7 h-7 inline-flex items-center justify-center rounded-md border-0 bg-transparent cursor-pointer" aria-label="Bulleted list">&#8801;</button>
  </div>
  <div class="px-4 py-3.5 text-[15px] leading-relaxed min-h-[3em]" contenteditable="true" role="textbox" aria-multiline="true" aria-label="Document content" style="font-weight:700;font-style:normal;">Great work this sprint, the launch went smoothly.</div>
</div>
<style>
[data-density="compact"] .rte-tw__extra { display: none; }
</style>

react

export function RichTextEditor({
  content = "Great work this sprint, the launch went smoothly.",
  toolbarDensity = "full",
  accent = "#A8E6C1",
  boldActive = true,
  italicActive = false,
}) {
  const compact = toolbarDensity === "compact";
  const btn = (pressed) => ({ width: 28, height: 28, display: "inline-flex", alignItems: "center", justifyContent: "center", border: "none", borderRadius: 6, cursor: "pointer", background: pressed ? accent : "transparent" });
  return (
    <div style={{ fontFamily: "system-ui, sans-serif", color: "#241430", background: "#FAF7F2", border: "1.5px solid #24143020", borderRadius: 10, overflow: "hidden", maxWidth: 380 }}>
      <div role="toolbar" aria-label="Formatting" style={{ display: "flex", gap: 2, padding: 6, borderBottom: "1.5px solid #24143020" }}>
        <button type="button" aria-pressed={boldActive} aria-label="Bold" style={btn(boldActive)}><strong>B</strong></button>
        <button type="button" aria-pressed={italicActive} aria-label="Italic" style={btn(italicActive)}><em>I</em></button>
        {!compact && <button type="button" aria-label="Underline" style={btn(false)}><span style={{ textDecoration: "underline" }}>U</span></button>}
        {!compact && <button type="button" aria-label="Bulleted list" style={btn(false)}>{"\u2261"}</button>}
      </div>
      <div contentEditable suppressContentEditableWarning role="textbox" aria-multiline="true" aria-label="Document content"
        style={{ padding: "14px 16px", fontSize: 15, lineHeight: 1.6, minHeight: "3em", fontWeight: boldActive ? 700 : 400, fontStyle: italicActive ? "italic" : "normal" }}>
        {content}
      </div>
    </div>
  );
}