Skip to content

Commit

Permalink
feat: Replace Markdown-related libraries with TipTap (#229)
Browse files Browse the repository at this point in the history
  • Loading branch information
evadecker authored Nov 27, 2024
1 parent d3d5732 commit 422078e
Show file tree
Hide file tree
Showing 11 changed files with 818 additions and 3,213 deletions.
5 changes: 5 additions & 0 deletions .changeset/cyan-spoons-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"namesake": minor
---

Improve rich text editing experience
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@
"@auth/core": "0.36.0",
"@convex-dev/auth": "^0.0.74",
"@faker-js/faker": "^9.2.0",
"@mdxeditor/editor": "^3.19.3",
"@pdfme/common": "^5.2.6",
"@pdfme/generator": "^5.2.6",
"@pdfme/schemas": "^5.2.6",
"@pdfme/ui": "^5.2.6",
"@tanstack/react-router": "^1.82.8",
"@tiptap/pm": "^2.10.3",
"@tiptap/react": "^2.10.3",
"@tiptap/starter-kit": "^2.10.3",
"convex": "^1.17.2",
"convex-helpers": "^0.1.65",
"framer-motion": "^11.11.17",
Expand All @@ -53,7 +55,6 @@
"react-aria-components": "^1.5.0",
"react-dom": "^18.3.1",
"react-helmet-async": "^2.0.5",
"react-markdown": "^9.0.1",
"resend": "4.0.1",
"sonner": "^1.7.0",
"storybook": "^8.4.5",
Expand Down
3,835 changes: 705 additions & 3,130 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import type { Meta, StoryObj } from "@storybook/react";

import { RichTextEditor } from "./RichTextEditor";
import { RichText } from "./RichText";

const meta = {
component: RichTextEditor,
component: RichText,
parameters: {
layout: "padded",
},
} satisfies Meta<typeof RichTextEditor>;
} satisfies Meta<typeof RichText>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
markdown: "hello",
initialContent: "hello",
},
};
95 changes: 95 additions & 0 deletions src/components/RichText/RichText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { BubbleMenu, EditorContent, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import { Bold, Italic } from "lucide-react";
import { useEffect } from "react";
import { twMerge } from "tailwind-merge";
import { tv } from "tailwind-variants";
import { ReadingScore } from "../ReadingScore";
import { ToggleButton } from "../ToggleButton";

export interface RichTextProps {
className?: string;
showReadingScore?: boolean;
initialContent?: string;
onChange?: (content: string) => void;
editable?: boolean;
}

export function RichText({
className,
showReadingScore = false,
initialContent,
onChange,
editable = true,
}: RichTextProps) {
const extensions = [StarterKit];

const editor = useEditor({
extensions,
content: initialContent,
editable,
onUpdate: ({ editor }) => {
if (onChange) {
onChange(editor.getHTML());
}
},
});

useEffect(() => {
if (editor && initialContent !== editor.getHTML()) {
editor.commands.setContent(initialContent ?? "");
}
}, [editor, initialContent]);

if (!editor) {
return null;
}

const styles = tv({
base: "w-full",
variants: {
editable: {
true: "border border-gray-dim flex flex-col rounded-xl [&_.tiptap]:p-4 [&_.tiptap]:outline-none",
},
},
});

return (
<div className={styles({ editable })}>
<EditorContent
editor={editor}
className={twMerge("w-full prose dark:prose-invert", className)}
/>
{editable && (
<>
<BubbleMenu
editor={editor}
className="bg-gray-1 dark:bg-graydark-2 p-1.5 rounded-xl shadow-md flex gap-1 items-center"
>
<ToggleButton
onPress={() => editor.chain().focus().toggleBold().run()}
isDisabled={!editor.can().chain().focus().toggleBold().run()}
isSelected={editor.isActive("bold")}
icon={Bold}
aria-label="Toggle bold text"
size="small"
/>
<ToggleButton
onPress={() => editor.chain().focus().toggleItalic().run()}
isDisabled={!editor.can().chain().focus().toggleItalic().run()}
isSelected={editor.isActive("italic")}
icon={Italic}
aria-label="Toggle italic text"
size="small"
/>
</BubbleMenu>
{showReadingScore && (
<div className="border-t border-gray-dim">
<ReadingScore text={editor.state.doc.textContent} />
</div>
)}
</>
)}
</div>
);
}
1 change: 1 addition & 0 deletions src/components/RichText/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./RichText";
65 changes: 0 additions & 65 deletions src/components/RichTextEditor/RichTextEditor.tsx

This file was deleted.

1 change: 0 additions & 1 deletion src/components/RichTextEditor/index.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export * from "./ProgressBar";
export * from "./RadioGroup";
export * from "./RangeCalendar";
export * from "./ReadingScore";
export * from "./RichTextEditor";
export * from "./RichText";
export * from "./SearchField";
export * from "./Select";
export * from "./Separator";
Expand Down
6 changes: 2 additions & 4 deletions src/routes/_authenticated/_home/quests.$questId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
MenuTrigger,
PageHeader,
Popover,
RichText,
StatusSelect,
Tooltip,
TooltipTrigger,
Expand All @@ -26,7 +27,6 @@ import {
Link as LinkIcon,
Milestone,
} from "lucide-react";
import Markdown from "react-markdown";
import { Fragment } from "react/jsx-runtime";
import { toast } from "sonner";

Expand Down Expand Up @@ -239,9 +239,7 @@ function QuestDetailRoute() {
<QuestUrls urls={quest.urls} />
<QuestForms questId={quest._id} />
{quest.content ? (
<Markdown className="prose lg:prose-lg dark:prose-invert max-w-full">
{quest.content}
</Markdown>
<RichText initialContent={quest.content} editable={false} />
) : (
"No content"
)}
Expand Down
8 changes: 2 additions & 6 deletions src/routes/_authenticated/admin/quests/$questId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
Form,
NumberField,
PageHeader,
RichTextEditor,
RichText,
Select,
SelectItem,
TextField,
Expand Down Expand Up @@ -335,11 +335,7 @@ function AdminQuestDetailRoute() {
Add URL
</Button>
</div>
<RichTextEditor
markdown={content}
onChange={setContent}
showReadingScore
/>
<RichText initialContent={content} onChange={setContent} />
<div className="flex gap-2 justify-end">
<Button type="submit" variant="primary">
Save
Expand Down

0 comments on commit 422078e

Please sign in to comment.