diff --git a/client/src/components/Artifacts/ArtifactButton.tsx b/client/src/components/Artifacts/ArtifactButton.tsx
index a1f32e8e73..de3e7b32c5 100644
--- a/client/src/components/Artifacts/ArtifactButton.tsx
+++ b/client/src/components/Artifacts/ArtifactButton.tsx
@@ -32,6 +32,7 @@ const ArtifactButton = ({ artifact }: { artifact: Artifact | null }) => {
+
);
};
diff --git a/client/src/components/Artifacts/Artifacts.tsx b/client/src/components/Artifacts/Artifacts.tsx
index 9eea91b45b..ffb60e4cc3 100644
--- a/client/src/components/Artifacts/Artifacts.tsx
+++ b/client/src/components/Artifacts/Artifacts.tsx
@@ -1,7 +1,7 @@
import * as Tabs from '@radix-ui/react-tabs';
-import { getFileExtension } from '~/utils/artifacts';
import useArtifacts from '~/hooks/Artifacts/useArtifacts';
import { CodeMarkdown, CopyCodeButton } from './Code';
+import { getFileExtension } from '~/utils/artifacts';
import { ArtifactPreview } from './ArtifactPreview';
import { cn } from '~/utils';
@@ -10,7 +10,6 @@ export default function Artifacts() {
isVisible,
activeTab,
setActiveTab,
- isSubmitting,
currentIndex,
cycleArtifact,
currentArtifact,
@@ -80,19 +79,13 @@ export default function Artifacts() {
{/* Content */}
0 ? 'result-streaming' : '',
- )}
+ className={cn('flex-grow overflow-x-auto overflow-y-scroll bg-gray-900 p-4')}
>
- {/* hidden div to scroll to could go here */}
diff --git a/client/src/components/Artifacts/Code.tsx b/client/src/components/Artifacts/Code.tsx
index c07fd5c616..5b94bf8580 100644
--- a/client/src/components/Artifacts/Code.tsx
+++ b/client/src/components/Artifacts/Code.tsx
@@ -1,36 +1,13 @@
-import React, { useRef, RefObject, memo, useState } from 'react';
+import React, { memo, useState } from 'react';
import rehypeKatex from 'rehype-katex';
import ReactMarkdown from 'react-markdown';
import rehypeHighlight from 'rehype-highlight';
import copy from 'copy-to-clipboard';
-import { handleDoubleClick, cn, langSubset } from '~/utils';
+import { handleDoubleClick, langSubset } from '~/utils';
import Clipboard from '~/components/svg/Clipboard';
import CheckMark from '~/components/svg/CheckMark';
import useLocalize from '~/hooks/useLocalize';
-type CodeBarProps = {
- lang: string;
- codeRef: RefObject;
-};
-
-type CodeBlockProps = Pick & {
- codeChildren: React.ReactNode;
- classProp?: string;
-};
-
-const CodeBlock: React.FC = ({ lang, codeChildren, classProp = '' }) => {
- const codeRef = useRef(null);
- return (
-
-
-
- {codeChildren}
-
-
-
- );
-};
-
type TCodeProps = {
inline: boolean;
className?: string;
@@ -49,41 +26,38 @@ export const code: React.ElementType = memo(({ inline, className, children }: TC
);
}
- return ;
+ return {children};
});
-const cursor = ' ';
-export const CodeMarkdown = memo(
- ({ content = '', showCursor }: { content: string; showCursor?: boolean }) => {
- const currentContent = content;
- const rehypePlugins = [
- [rehypeKatex, { output: 'mathml' }],
- [
- rehypeHighlight,
- {
- detect: true,
- ignoreMissing: true,
- subset: langSubset,
- },
- ],
- ];
+export const CodeMarkdown = memo(({ content = '' }: { content: string }) => {
+ const currentContent = content;
+ const rehypePlugins = [
+ [rehypeKatex, { output: 'mathml' }],
+ [
+ rehypeHighlight,
+ {
+ detect: true,
+ ignoreMissing: true,
+ subset: langSubset,
+ },
+ ],
+ ];
- return (
-
- {showCursor === true ? currentContent + cursor : currentContent}
-
- );
- },
-);
+ }
+ >
+ {currentContent}
+
+ );
+});
export const CopyCodeButton: React.FC<{ content: string }> = ({ content }) => {
const localize = useLocalize();
diff --git a/client/src/hooks/Artifacts/useAutoScroll.ts b/client/src/hooks/Artifacts/useAutoScroll.ts
new file mode 100644
index 0000000000..3a03fc20fd
--- /dev/null
+++ b/client/src/hooks/Artifacts/useAutoScroll.ts
@@ -0,0 +1,30 @@
+import { useState, useRef, useCallback, useEffect } from 'react';
+import { useChatContext } from '~/Providers';
+
+export default function useAutoScroll() {
+ const { isSubmitting } = useChatContext();
+ const [showScrollButton, setShowScrollButton] = useState(false);
+ const scrollableRef = useRef(null);
+ const contentEndRef = useRef(null);
+
+ const scrollToBottom = useCallback(() => {
+ if (scrollableRef.current) {
+ scrollableRef.current.scrollTop = scrollableRef.current.scrollHeight;
+ }
+ }, []);
+
+ const handleScroll = useCallback(() => {
+ if (scrollableRef.current) {
+ const { scrollTop, scrollHeight, clientHeight } = scrollableRef.current;
+ setShowScrollButton(scrollHeight - scrollTop - clientHeight > 100);
+ }
+ }, []);
+
+ useEffect(() => {
+ if (isSubmitting) {
+ scrollToBottom();
+ }
+ }, [isSubmitting, scrollToBottom]);
+
+ return { scrollableRef, contentEndRef, handleScroll, scrollToBottom, showScrollButton };
+}