This example demonstrates the use of Shadcn-ui for ui, but alternative libraries and components can also be employed.

Shadcn-ui

You can find more info about installing shadcn-ui here. You will need to add the following components: Button, Separator, Popover, Command, Dialog

This example will use the same stucture from here: Anatomy
You can find the full example here: Tailwind Example

Configure Wrapper

"use client";

import { EditorContent, EditorRoot } from "novel";
import { useState } from "react";

const TailwindEditor = () => {
  const [content, setContent] = useState(null);
  return (
    <EditorRoot>
      <EditorContent
        initialContent={content}
        onUpdate={({ editor }) => {
          const json = editor.getJSON();
          setContent(json);
        }}
      />
    </EditorRoot>
  );
};
export default TailwindEditor;

onUpdate runs on every change. In most cases, you will want to debounce the updates to prevent too many state changes.

import { EditorInstance } from "novel"

...
const debouncedUpdates = useDebouncedCallback(async (editor: EditorInstance) => {
  const json = editor.getJSON();
  setContent(json);
  setSaveStatus("Saved");
}, 500);

onUpdate={debouncedUpdates};

Configure Extensions

Extensions

You can find here example of extensions

import { defaultExtensions } from "./extensions";

const extensions = [...defaultExtensions];

<EditorContent
  extensions={extensions}
  ...
/>;

Create Menus

Add Editor Props

handleCommandNavigation is required for fixing the arrow navigation in the / command;

import { handleCommandNavigation } from "novel/extensions";
import { defaultEditorProps, EditorContent } from "novel";

<EditorContent
  ...
  editorProps={{
      handleDOMEvents: {
        keydown: (_view, event) => handleCommandNavigation(event),
      },
      attributes: {
        class: `prose prose-lg dark:prose-invert prose-headings:font-title font-default focus:outline-none max-w-full`,
      }
  }}
/>

Add Styles

You need require("@tailwindcss/typography") for the prose styling

Usage within Dialogs

Novel has been designed to work automatically within Radix Dialogs, namely by looking for the closest parent attribute [role="dialog"]. If you’re using a different implementation for popups and dialogs, ensure you add this attribute above the editor so the drag handle calculates the correct position.