From 92efa1e9e9d424930c2617f1076ca9f757951c59 Mon Sep 17 00:00:00 2001 From: jakubduda-dsai Date: Wed, 14 May 2025 10:40:28 +0200 Subject: [PATCH 1/6] Clear HeroUI components, prompt in minimalistic version, removed unnecessary components based on HeroUI Pro --- ui/src/core/components/ChatMessage.tsx | 4 +- .../components/PromptInput/PromptInput.tsx | 4 +- .../PromptInput/PromptInputAssets.tsx | 52 -------- .../PromptInput/PromptInputText.tsx | 3 - ui/src/core/components/SidebarDrawer.tsx | 112 ------------------ 5 files changed, 4 insertions(+), 171 deletions(-) delete mode 100644 ui/src/core/components/PromptInput/PromptInputAssets.tsx delete mode 100644 ui/src/core/components/SidebarDrawer.tsx diff --git a/ui/src/core/components/ChatMessage.tsx b/ui/src/core/components/ChatMessage.tsx index 67fae44a6..f4268afba 100644 --- a/ui/src/core/components/ChatMessage.tsx +++ b/ui/src/core/components/ChatMessage.tsx @@ -29,9 +29,11 @@ const ChatMessage = forwardRef( ref, ) => { const rightAlign = role === MessageRole.USER; + const [didAnimate, setDidAnimate] = useState(false); - const copyIconTimerRef = useRef | null>(null); const [copyIcon, setCopyIcon] = useState("heroicons:clipboard"); + + const copyIconTimerRef = useRef | null>(null); const { theme } = useThemeContext(); const onCopyClick = () => { diff --git a/ui/src/core/components/PromptInput/PromptInput.tsx b/ui/src/core/components/PromptInput/PromptInput.tsx index 38a820e56..94db421a3 100644 --- a/ui/src/core/components/PromptInput/PromptInput.tsx +++ b/ui/src/core/components/PromptInput/PromptInput.tsx @@ -64,10 +64,9 @@ const PromptInput = ({ "!bg-transparent shadow-none group-data-[focus-visible=true]:ring-0 group-data-[focus-visible=true]:ring-offset-0 pr-3 pl-[20px] pt-3 pb-4", }} maxRows={16} - minRows={2} + minRows={1} name="content" radius="lg" - spellCheck={"false"} value={message} variant="flat" onKeyDown={handleKeyDown} @@ -98,4 +97,3 @@ const PromptInput = ({ }; export default PromptInput; -PromptInput.displayName = "PromptInput"; diff --git a/ui/src/core/components/PromptInput/PromptInputAssets.tsx b/ui/src/core/components/PromptInput/PromptInputAssets.tsx deleted file mode 100644 index 0ac4a6766..000000000 --- a/ui/src/core/components/PromptInput/PromptInputAssets.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { Badge, Button } from "@heroui/react"; -import { Image } from "@heroui/image"; -import { Icon } from "@iconify/react"; - -interface PromptInputAssetsProps { - assets: string[]; - onRemoveAsset: (index: number) => void; -} - -const PromptInputAssets = ({ - assets, - onRemoveAsset, -}: PromptInputAssetsProps) => { - if (assets.length === 0) return null; - - return ( - <> - {assets.map((asset, index) => ( - onRemoveAsset(index)} - > - - - } - > - uploaded image - - ))} - - ); -}; - -export default PromptInputAssets; - -PromptInputAssets.displayName = "PromptInputAssets"; diff --git a/ui/src/core/components/PromptInput/PromptInputText.tsx b/ui/src/core/components/PromptInput/PromptInputText.tsx index 9b05e923b..7d1cd90ba 100644 --- a/ui/src/core/components/PromptInput/PromptInputText.tsx +++ b/ui/src/core/components/PromptInput/PromptInputText.tsx @@ -16,7 +16,6 @@ const PromptInputText = React.forwardRef( label: cn("hidden", classNames?.label), input: cn("py-0", classNames?.input), }} - minRows={1} placeholder="Enter a prompt here" radius="lg" variant="bordered" @@ -27,5 +26,3 @@ const PromptInputText = React.forwardRef( ); export default PromptInputText; - -PromptInputText.displayName = "PromptInputText"; diff --git a/ui/src/core/components/SidebarDrawer.tsx b/ui/src/core/components/SidebarDrawer.tsx deleted file mode 100644 index 096e7d060..000000000 --- a/ui/src/core/components/SidebarDrawer.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import type { ModalProps } from "@heroui/react"; - -import React from "react"; -import { TRANSITION_EASINGS } from "@heroui/framer-utils"; -import { Drawer, DrawerBody, DrawerContent } from "@heroui/react"; -import { cn } from "@heroui/react"; - -const SidebarDrawer = React.forwardRef< - HTMLDivElement, - ModalProps & { - sidebarWidth?: number; - sidebarPlacement?: "left" | "right"; - } ->( - ( - { - children, - className, - onOpenChange, - isOpen, - sidebarWidth = 288, - classNames = {}, - sidebarPlacement = "left", - motionProps: drawerMotionProps, - ...props - }, - ref, - ) => { - const motionProps = React.useMemo(() => { - if (!!drawerMotionProps && typeof drawerMotionProps === "object") { - return drawerMotionProps; - } - - return { - variants: { - enter: { - x: 0, - transition: { - x: { - duration: 0.3, - ease: TRANSITION_EASINGS.easeOut, - }, - }, - }, - exit: { - x: sidebarPlacement == "left" ? -sidebarWidth : sidebarWidth, - transition: { - x: { - duration: 0.2, - ease: TRANSITION_EASINGS.easeOut, - }, - }, - }, - }, - }; - }, [sidebarWidth, sidebarPlacement, drawerMotionProps]); - - return ( - <> - - - {children} - - -
- {children} -
- - ); - }, -); - -SidebarDrawer.displayName = "SidebarDrawer"; - -export default SidebarDrawer; From 2901b69ab5d24bc3284371716014df6eb87ea9a4 Mon Sep 17 00:00:00 2001 From: jakubduda-dsai Date: Thu, 22 May 2025 10:29:48 +0200 Subject: [PATCH 2/6] Components organization --- ui/src/App.tsx | 8 +++ .../components/PromptInput/PromptInput.tsx | 62 +++++++++---------- .../PromptInput/PromptInputText.tsx | 20 ++---- 3 files changed, 43 insertions(+), 47 deletions(-) diff --git a/ui/src/App.tsx b/ui/src/App.tsx index da96ecbc6..ac9d66e20 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -41,13 +41,16 @@ export default function Component() { const handleScroll = useCallback(() => { const AUTO_SCROLL_THRESHOLD = 25; const SCROLL_DOWN_THRESHOLD = 100; + if (!scrollContainerRef.current) return; + const container = scrollContainerRef.current; const offsetFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight; setShowScrollDownButton(offsetFromBottom > SCROLL_DOWN_THRESHOLD); setShouldAutoScroll(false); + if (offsetFromBottom > AUTO_SCROLL_THRESHOLD) { setShouldAutoScroll(false); } else { @@ -58,6 +61,7 @@ export default function Component() { useEffect(() => { if (configRequest.data) { const config = configRequest.data.data; + setConfig(config); } }, [configRequest.data]); @@ -77,6 +81,7 @@ export default function Component() { useEffect(() => { setShouldAutoScroll(true); + if (history.length === 0) { setShowScrollDownButton(false); } @@ -102,10 +107,12 @@ export default function Component() { const scrollToBottom = useCallback(() => { if (!scrollContainerRef.current) return; + scrollContainerRef.current.scrollTo({ top: scrollContainerRef.current.scrollHeight, behavior: "smooth", }); + setShouldAutoScroll(true); }, []); @@ -126,6 +133,7 @@ export default function Component() { const handleSubmit = () => { sendMessage(message); + setMessage(""); }; const heroMessage = `Hello! I'm your AI assistant.\n\n How can I help you today? diff --git a/ui/src/core/components/PromptInput/PromptInput.tsx b/ui/src/core/components/PromptInput/PromptInput.tsx index 94db421a3..9990e0821 100644 --- a/ui/src/core/components/PromptInput/PromptInput.tsx +++ b/ui/src/core/components/PromptInput/PromptInput.tsx @@ -19,19 +19,19 @@ const PromptInput = ({ submit, isLoading, }: PromptInputProps) => { - const inputRef = React.useRef(null); + const textAreaRef = React.useRef(null); const handleSubmit = useCallback(() => { - if (!prompt && !isLoading) return; + if (!message && !isLoading) return; submit(); - setMessage(""); - inputRef?.current?.focus(); + textAreaRef?.current?.focus(); }, [setMessage, isLoading, submit]); const onSubmit = useCallback( (e: React.FormEvent) => { e.preventDefault(); + handleSubmit(); }, [handleSubmit], @@ -50,48 +50,44 @@ const PromptInput = ({ return (
-
- -
+ ); }; diff --git a/ui/src/core/components/PromptInput/PromptInputText.tsx b/ui/src/core/components/PromptInput/PromptInputText.tsx index 7d1cd90ba..b7786d355 100644 --- a/ui/src/core/components/PromptInput/PromptInputText.tsx +++ b/ui/src/core/components/PromptInput/PromptInputText.tsx @@ -1,24 +1,16 @@ import type { TextAreaProps } from "@heroui/react"; - -import React from "react"; +import { forwardRef } from "react"; import { Textarea } from "@heroui/react"; -import { cn } from "@heroui/react"; -const PromptInputText = React.forwardRef( +interface PromptInputTextProps extends TextAreaProps {} + +const PromptInputText = forwardRef( ({ classNames = {}, ...props }, ref) => { return (