ultisuite-client/components/gmail/compose/compose-formatting-toolbar.tsx
2026-05-20 18:22:36 +02:00

152 lines
4.1 KiB
TypeScript

"use client"
import { type Editor } from "@tiptap/react"
import {
Bold,
Italic,
Underline as UnderlineIcon,
List,
ListOrdered,
Undo,
Redo,
Indent,
Outdent,
RemoveFormatting,
} from "lucide-react"
import { cn } from "@/lib/utils"
import {
MAIL_COMPOSE_TOOLBAR_BTN,
MAIL_COMPOSE_TOOLBAR_BTN_ACTIVE,
MAIL_COMPOSE_TOOLBAR_SEP,
} from "@/lib/mail-chrome-classes"
import {
AlignmentDropdown,
FontDropdown,
FontSizeDropdown,
ColorDropdown,
} from "./compose-formatting-dropdowns"
export function FormattingToolbar({
editor,
}: {
editor: Editor | null
}) {
if (!editor) return null
const btnClass = MAIL_COMPOSE_TOOLBAR_BTN
const activeClass = MAIL_COMPOSE_TOOLBAR_BTN_ACTIVE
const sep = <span className={MAIL_COMPOSE_TOOLBAR_SEP} aria-hidden />
return (
<div className="compose-toolbar flex flex-wrap items-center border-t border-border bg-muted px-1 py-1">
{/* Undo / Redo */}
<button
type="button"
className={btnClass}
onClick={() => editor.chain().focus().undo().run()}
disabled={!editor.can().undo()}
title="Annuler"
>
<Undo className="h-4 w-4" />
</button>
<button
type="button"
className={btnClass}
onClick={() => editor.chain().focus().redo().run()}
disabled={!editor.can().redo()}
title="Rétablir"
>
<Redo className="h-4 w-4" />
</button>
{sep}
{/* Font */}
<FontDropdown editor={editor} btnClass={btnClass} />
{sep}
{/* Font size */}
<FontSizeDropdown editor={editor} btnClass={btnClass} />
{sep}
{/* Bold, Italic, Underline, Colors */}
<button
type="button"
className={cn(btnClass, editor.isActive("bold") && activeClass)}
onClick={() => editor.chain().focus().toggleMark("bold").run()}
title="Gras"
>
<Bold className="h-4 w-4" />
</button>
<button
type="button"
className={cn(btnClass, editor.isActive("italic") && activeClass)}
onClick={() => editor.chain().focus().toggleMark("italic").run()}
title="Italique"
>
<Italic className="h-4 w-4" />
</button>
<button
type="button"
className={cn(btnClass, editor.isActive("underline") && activeClass)}
onClick={() => editor.chain().focus().toggleUnderline().run()}
title="Souligné"
>
<UnderlineIcon className="h-4 w-4" />
</button>
<ColorDropdown editor={editor} btnClass={btnClass} />
{sep}
{/* Alignment dropdown, lists, indent/outdent, remove formatting */}
<AlignmentDropdown editor={editor} btnClass={btnClass} activeClass={activeClass} />
<button
type="button"
className={cn(btnClass, editor.isActive("orderedList") && activeClass)}
onClick={() => editor.chain().focus().toggleOrderedList().run()}
title="Liste numérotée"
>
<ListOrdered className="h-4 w-4" />
</button>
<button
type="button"
className={cn(btnClass, editor.isActive("bulletList") && activeClass)}
onClick={() => editor.chain().focus().toggleBulletList().run()}
title="Liste à puces"
>
<List className="h-4 w-4" />
</button>
<button
type="button"
className={btnClass}
onClick={() => {
try { editor.chain().focus().liftListItem("listItem").run() } catch { /* not in list */ }
}}
title="Désindenter"
>
<Outdent className="h-4 w-4" />
</button>
<button
type="button"
className={btnClass}
onClick={() => {
try { editor.chain().focus().sinkListItem("listItem").run() } catch { /* not in list */ }
}}
title="Indenter"
>
<Indent className="h-4 w-4" />
</button>
<button
type="button"
className={btnClass}
onClick={() => editor.chain().focus().clearNodes().unsetAllMarks().run()}
title="Supprimer la mise en forme"
>
<RemoveFormatting className="h-4 w-4" />
</button>
</div>
)
}