diff --git a/src/components/GenerateCourse/AICourseFollowUp.css b/src/components/GenerateCourse/AICourseFollowUp.css new file mode 100644 index 000000000..a6b8a9bac --- /dev/null +++ b/src/components/GenerateCourse/AICourseFollowUp.css @@ -0,0 +1,131 @@ +.prose ul li > code, +.prose ol li > code, +p code, +a > code, +strong > code, +em > code, +h1 > code, +h2 > code, +h3 > code { + background: #ebebeb !important; + color: currentColor !important; + font-size: 14px; + font-weight: normal !important; +} + +.course-ai-content.course-content.prose ul li > code, +.course-ai-content.course-content.prose ol li > code, +.course-ai-content.course-content.prose p code, +.course-ai-content.course-content.prose a > code, +.course-ai-content.course-content.prose strong > code, +.course-ai-content.course-content.prose em > code, +.course-ai-content.course-content.prose h1 > code, +.course-ai-content.course-content.prose h2 > code, +.course-ai-content.course-content.prose h3 > code, +.course-notes-content.prose ul li > code, +.course-notes-content.prose ol li > code, +.course-notes-content.prose p code, +.course-notes-content.prose a > code, +.course-notes-content.prose strong > code, +.course-notes-content.prose em > code, +.course-notes-content.prose h1 > code, +.course-notes-content.prose h2 > code, +.course-notes-content.prose h3 > code { + font-size: 12px !important; +} + +.course-ai-content pre { + -ms-overflow-style: none; + scrollbar-width: none; +} + +.course-ai-content pre::-webkit-scrollbar { + display: none; +} + +.course-ai-content pre, +.course-notes-content pre { + overflow: scroll; + font-size: 15px; + margin: 10px 0; +} + +.prose ul li > code:before, +p > code:before, +.prose ul li > code:after, +.prose ol li > code:before, +p > code:before, +.prose ol li > code:after, +.course-content h1 > code:after, +.course-content h1 > code:before, +.course-content h2 > code:after, +.course-content h2 > code:before, +.course-content h3 > code:after, +.course-content h3 > code:before, +.course-content h4 > code:after, +.course-content h4 > code:before, +p > code:after, +a > code:after, +a > code:before { + content: '' !important; +} + +.course-content.prose ul li > code, +.course-content.prose ol li > code, +.course-content p code, +.course-content a > code, +.course-content strong > code, +.course-content em > code, +.course-content h1 > code, +.course-content h2 > code, +.course-content h3 > code, +.course-content table code { + background: #f4f4f5 !important; + border: 1px solid #282a36 !important; + color: #282a36 !important; + padding: 2px 4px; + border-radius: 5px; + font-size: 16px !important; + white-space: pre; + font-weight: normal; +} + +.course-content blockquote { + font-style: normal; +} + +.course-content.prose blockquote h1, +.course-content.prose blockquote h2, +.course-content.prose blockquote h3, +.course-content.prose blockquote h4 { + font-style: normal; + margin-bottom: 8px; +} + +.course-content.prose ul li > code:before, +.course-content p > code:before, +.course-content.prose ul li > code:after, +.course-content p > code:after, +.course-content h2 > code:after, +.course-content h2 > code:before, +.course-content table code:before, +.course-content table code:after, +.course-content a > code:after, +.course-content a > code:before, +.course-content h2 code:after, +.course-content h2 code:before, +.course-content h2 code:after, +.course-content h2 code:before { + content: '' !important; +} + +.course-content table { + border-collapse: collapse; + border: 1px solid black; + border-radius: 5px; +} + +.course-content table td, +.course-content table th { + padding: 5px 10px; +} diff --git a/src/components/GenerateCourse/AICourseFollowUp.tsx b/src/components/GenerateCourse/AICourseFollowUp.tsx index 78b602b03..7c25ae536 100644 --- a/src/components/GenerateCourse/AICourseFollowUp.tsx +++ b/src/components/GenerateCourse/AICourseFollowUp.tsx @@ -17,7 +17,14 @@ export function AICourseFollowUp(props: AICourseFollowUpProps) { const [isOpen, setIsOpen] = useState(false); const [courseAIChatHistory, setCourseAIChatHistory] = useState< AIChatHistoryType[] - >([]); + >([ + { + role: 'assistant', + content: + 'Hey, I am your AI instructor. Here are some examples of what you can ask me about 🤖', + isDefault: true, + }, + ]); return ( <div className="relative"> @@ -47,6 +54,10 @@ export function AICourseFollowUp(props: AICourseFollowUpProps) { }} /> )} + + {isOpen && ( + <div className="pointer-events-none fixed inset-0 z-50 bg-black/50" /> + )} </div> ); } diff --git a/src/components/GenerateCourse/AICourseFollowUpPopover.tsx b/src/components/GenerateCourse/AICourseFollowUpPopover.tsx index d5f138e39..a39097574 100644 --- a/src/components/GenerateCourse/AICourseFollowUpPopover.tsx +++ b/src/components/GenerateCourse/AICourseFollowUpPopover.tsx @@ -182,7 +182,7 @@ export function AICourseFollowUpPopover(props: AICourseFollowUpPopoverProps) { return ( <div - className="absolute bottom-0 left-0 z-10 flex h-[400px] w-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white shadow" + className="absolute bottom-0 left-0 z-[99] flex h-[500px] w-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white shadow" ref={containerRef} > <div className="flex items-center justify-between gap-2 border-b border-gray-200 px-4 py-2 text-sm"> @@ -256,7 +256,7 @@ function AIChatCard(props: AIChatCardProps) { const { role, content } = props; const html = useMemo(() => { - return markdownToHtml(content); + return markdownToHtml(content, false); }, [content]); return ( @@ -278,7 +278,7 @@ function AIChatCard(props: AIChatCardProps) { <Bot className="size-4 stroke-[2.5]" /> </div> <div - className="course-content course-ai-content prose prose-sm mt-0.5 max-w-full grow overflow-hidden text-sm" + className="course-content course-ai-content prose prose-sm mt-0.5 max-w-full overflow-hidden text-sm" dangerouslySetInnerHTML={{ __html: html }} /> </div> diff --git a/src/components/GenerateCourse/AICourseModuleView.tsx b/src/components/GenerateCourse/AICourseModuleView.tsx index 79a1e23de..841788d2f 100644 --- a/src/components/GenerateCourse/AICourseModuleView.tsx +++ b/src/components/GenerateCourse/AICourseModuleView.tsx @@ -1,10 +1,5 @@ -import { - CheckIcon, - ChevronLeft, - ChevronRight, - Loader2Icon, - LockIcon, -} from 'lucide-react'; +import './AICourseFollowUp.css'; +import { CheckIcon, ChevronLeft, ChevronRight, Loader2Icon, LockIcon } from 'lucide-react'; import { cn } from '../../lib/classname'; import { useEffect, useMemo, useState } from 'react'; import { isLoggedIn, removeAuthToken } from '../../lib/jwt'; @@ -213,7 +208,7 @@ export function AICourseModuleView(props: AICourseModuleViewProps) { {!error && isLoggedIn() && ( <div - className="prose max-w-none" + className="course-content prose prose-lg mt-8 text-black prose-headings:mb-3 prose-headings:mt-8 prose-blockquote:font-normal prose-pre:rounded-2xl prose-pre:text-lg prose-li:my-1 prose-thead:border-zinc-800 prose-tr:border-zinc-800" dangerouslySetInnerHTML={{ __html: lessonHtml }} /> )} @@ -268,7 +263,7 @@ export function AICourseModuleView(props: AICourseModuleViewProps) { </div> </div> - {!isGenerating && ( + {!isGenerating && !isLoading && ( <AICourseFollowUp courseSlug={courseSlug} moduleTitle={currentModuleTitle} diff --git a/src/lib/markdown.ts b/src/lib/markdown.ts index 721cb6492..dc12f8f67 100644 --- a/src/lib/markdown.ts +++ b/src/lib/markdown.ts @@ -17,13 +17,13 @@ export function replaceVariables( }); } +const md = new MarkdownIt({ + html: true, + linkify: true, +}); + export function markdownToHtml(markdown: string, isInline = true): string { try { - const md = new MarkdownIt({ - html: true, - linkify: true, - }); - // Solution to open links in new tab in markdown // otherwise default behaviour is to open in same tab //