carbon-tokenization / frontend /src /editor /BubbleToolbar.tsx
tfrere's picture
tfrere HF Staff
feat(editor): code block button in the bubble toolbar
add3959
Raw
History Blame Contribute Delete
3.45 kB
import { BubbleMenu } from "@tiptap/react/menus";
import type { Editor } from "@tiptap/core";
import { Tooltip } from "../components/Tooltip";
import {
Bold,
Italic,
Strikethrough,
Code,
Code2,
Quote,
Link,
Heading2,
MessageCircle,
Sigma,
} from "lucide-react";
interface BubbleToolbarProps {
editor: Editor;
onAddComment?: () => void;
}
function Btn({
onClick,
active,
tooltip,
children,
}: {
onClick: () => void;
active?: boolean;
tooltip: string;
children: React.ReactNode;
}) {
return (
<Tooltip title={tooltip} placement="top">
<button
className={`icon-btn ${active ? "icon-btn--active" : ""}`}
onMouseDown={(e) => {
e.preventDefault();
onClick();
}}
aria-label={tooltip}
>
{children}
</button>
</Tooltip>
);
}
export function BubbleToolbar({ editor, onAddComment }: BubbleToolbarProps) {
const setLink = () => {
const url = window.prompt("URL:");
if (url) {
editor.chain().focus().setLink({ href: url }).run();
}
};
return (
<BubbleMenu
editor={editor}
options={{ placement: "top", offset: 6 }}
>
<div className="bubble-toolbar">
<Btn
onClick={() => editor.chain().focus().toggleBold().run()}
active={editor.isActive("bold")}
tooltip="Bold"
>
<Bold size={18} />
</Btn>
<Btn
onClick={() => editor.chain().focus().toggleItalic().run()}
active={editor.isActive("italic")}
tooltip="Italic"
>
<Italic size={18} />
</Btn>
<Btn
onClick={() => editor.chain().focus().toggleStrike().run()}
active={editor.isActive("strike")}
tooltip="Strikethrough"
>
<Strikethrough size={18} />
</Btn>
<Btn
onClick={() => editor.chain().focus().toggleCode().run()}
active={editor.isActive("code")}
tooltip="Code"
>
<Code size={18} />
</Btn>
<Btn
onClick={() => editor.chain().focus().insertInlineMath({ latex: "x^2" }).run()}
active={editor.isActive("inlineMath")}
tooltip="Inline math"
>
<Sigma size={18} />
</Btn>
<span className="divider-v" />
<Btn
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
active={editor.isActive("heading", { level: 2 })}
tooltip="Heading"
>
<Heading2 size={18} />
</Btn>
<Btn
onClick={() => editor.chain().focus().toggleBlockquote().run()}
active={editor.isActive("blockquote")}
tooltip="Quote"
>
<Quote size={18} />
</Btn>
<Btn
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
active={editor.isActive("codeBlock")}
tooltip="Code block"
>
<Code2 size={18} />
</Btn>
<Btn
onClick={setLink}
active={editor.isActive("link")}
tooltip="Link"
>
<Link size={18} />
</Btn>
{onAddComment && (
<>
<span className="divider-v" />
<Btn onClick={onAddComment} tooltip="Comment">
<MessageCircle size={18} />
</Btn>
</>
)}
</div>
</BubbleMenu>
);
}