tiptap-extension-twemoji
1

Custom Emojis

Welcome to the Custom Emojis!
This page will walk you through the basic usage of custom emoji.


okabe Using Predefined Custom Emojis

// components/Editor.tsx
import * as React from "react";
import { useEditor } from "@tiptap/react";
import { StarterKit } from "@tiptap/starter-kit";
import {
  TwemojiExtension,
  CustomEmoji,
} from "@raihancodes/tiptap-extension-twemoji-react";

export default function Editor() {
  const editor = useEditor({ extensions: [StarterKit, TwemojiExtension] });

  const customEmojis: CustomEmoji[] = [
    {
      id: "8177849e-c2c9-424a-a914-ff128ce439c5",
      created_at: "2025-08-09T00:26:09.143473+00:00",
      label: "github-icon",
      url: "...",
    },
    {
      id: "cecf7043-80da-4e3f-b167-6a85de0e464a",
      created_at: "2025-08-09T01:23:15.144872+00:00",
      label: "npm-icon",
      url: "...",
    },
  ];

  React.useEffect(() => {
    if (editor) {
      editor.commands.updateCustomEmojis(customEmojis);
    }
  }, [editor]);

  return <EditorContent editor={editor} />;
}

🗄️ Using Custom Emojis from Database

Example: Fetching custom emojis from your database

// page.tsx
import { CustomEmoji } from "@raihancodes/tiptap-extension-twemoji-react";

export default async function Page() {
  const { data, error } = await supabase.from("emojis").select("*");

  if (error) {
    console.error("Error fetching emojis:", error);
  }

  const customEmojis = (data ?? []) as CustomEmoji[];

  return <Editor customEmojis={customEmojis} />;
}

Handling Emoji Uploads and Applying Fetched Emojis

"use client";

// components/Editor.tsx

import * as React from "react";
import { useEditor } from "@tiptap/react";
import { StarterKit } from "@tiptap/starter-kit";
import {
  EmojiUploadProps,
  TwemojiExtension,
  CustomEmoji,
} from "@raihancodes/tiptap-extension-twemoji-react";

export default function Editor({
  customEmojis,
}: {
  customEmojis: CustomEmoji[];
}) {
  const handleEmojiUpload: EmojiUploadProps["upload"] = async ({
    emojiName,
    files,
    handleSuccess,
    handleError,
    dismiss,
  }) => {
    // your code
  };

  const handleEmojiOnError: EmojiUploadProps["onError"] = (errorMessage) => {
    // your code
  };

  const handleEmojiOnSuccess: EmojiUploadProps["onSuccess"] = (
    successMessage,
    callback
  ) => {
    // your code
  };

  const editor = useEditor({
    extensions: [
      StarterKit,
      TwemojiExtension.configure({
        customEmojiOptions: {
          upload: handleEmojiUpload,
          onSuccess: handleEmojiOnSuccess,
          onError: handleEmojiOnError,
        },
      }),
    ],
  });

  // Applying Fetched Emojis
  React.useEffect(() => {
    if (editor) {
      editor.commands.updateCustomEmojis(customEmojis);
    }
  }, [editor, customEmojis]);

  return <EditorContent editor={editor} />;
}

Choose the approach that best fits your needs


github Quick Demo

For more details, check the example repo on GitHub


🚀 What’s Next?

  • 👉 Check out the Deep Dive section to learn how to customize the extension—header, navigation, cell size, custom emojis, etc.