Rich Text Editor

Form

WYSIWYG text editor with formatting toolbar.

Preview

Usage

example.jsx
import { RichTextEditor } from "@/components/ui/rich-text-editor";

export default function Example() {
  return <RichTextEditor />;
}

Source Code

Copy this file into components/ui/rich-text-editor.jsx in your project.

rich-text-editor.jsx
"use client";

import { forwardRef } from "react";
import { cn } from "@/lib/utils";

const RichTextEditor = forwardRef(({ className, value, onValueChange, placeholder = "Start writing...", ...props }, ref) => {
  return (
    <div ref={ref} className={cn("rounded-md border border-input shadow-sm", className)} {...props}>
      {/* Toolbar */}
      <div className="flex flex-wrap items-center gap-1 border-b px-2 py-1.5">
        {["B", "I", "U", "S", "H1", "H2", "•", "1.", "\"", "<>", "🔗"].map((btn) => (
          <button
            key={btn}
            type="button"
            className="inline-flex h-7 w-7 items-center justify-center rounded text-xs font-medium hover:bg-accent cursor-pointer"
          >
            {btn}
          </button>
        ))}
      </div>
      {/* Editor area */}
      <div
        contentEditable
        suppressContentEditableWarning
        className="min-h-[120px] px-3 py-2 text-sm outline-none focus-visible:ring-1 focus-visible:ring-ring rounded-b-md"
        onInput={(e) => onValueChange?.(e.currentTarget.innerHTML)}
        dangerouslySetInnerHTML={{ __html: value || "" }}
        data-placeholder={placeholder}
      />
    </div>
  );
});
RichTextEditor.displayName = "RichTextEditor";

export { RichTextEditor };

Quick Install

Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.

npm install clsx tailwind-merge