mirror of
https://github.com/StanGirard/quivr.git
synced 2024-12-25 12:22:58 +03:00
remove blank scrollbars and use predefined components (#452)
* style(chat and brains dropdown): remove blank scrollbars and use predefined components * style(chat): use custom scrollbar style by using scrollbar class
This commit is contained in:
parent
b444761622
commit
315411facd
@ -9,7 +9,7 @@ import { ChatProvider } from "./context/ChatContext";
|
|||||||
export default function ChatPage() {
|
export default function ChatPage() {
|
||||||
return (
|
return (
|
||||||
<main className="flex flex-col w-full pt-10">
|
<main className="flex flex-col w-full pt-10">
|
||||||
<section className="flex flex-col flex-1 items-center w-full h-full min-h-screen">
|
<section className="flex flex-col flex-1 items-center w-full h-full min-h-[70vh]">
|
||||||
<PageHeading
|
<PageHeading
|
||||||
title="Chat with your brain"
|
title="Chat with your brain"
|
||||||
subtitle="Talk to a language model about your uploaded data"
|
subtitle="Talk to a language model about your uploaded data"
|
||||||
|
@ -12,7 +12,7 @@ export const ChatMessages = (): JSX.Element => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
className="p-5 max-w-3xl w-full flex flex-col mb-8 overflow-y-auto"
|
className="p-5 max-w-3xl w-full flex flex-col mb-8 overflow-y-auto scrollbar"
|
||||||
ref={chatListRef}
|
ref={chatListRef}
|
||||||
>
|
>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
|
@ -26,7 +26,7 @@ export const ChatsList = (): JSX.Element => {
|
|||||||
setOpen(false);
|
setOpen(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className="lg:sticky fixed top-0 left-0 bottom-0 overflow-visible z-30 border-r border-black/10 dark:border-white/25 bg-white dark:bg-black"
|
className="flex flex-col lg:sticky fixed top-16 left-0 bottom-0 lg:h-[90vh] overflow-visible z-30 border-r border-black/10 dark:border-white/25 bg-white dark:bg-black"
|
||||||
>
|
>
|
||||||
<motion.div
|
<motion.div
|
||||||
animate={{
|
animate={{
|
||||||
@ -36,18 +36,11 @@ export const ChatsList = (): JSX.Element => {
|
|||||||
? "10px 10px 16px rgba(0, 0, 0, 0)"
|
? "10px 10px 16px rgba(0, 0, 0, 0)"
|
||||||
: "10px 10px 16px rgba(0, 0, 0, 0.5)",
|
: "10px 10px 16px rgba(0, 0, 0, 0.5)",
|
||||||
}}
|
}}
|
||||||
className={cn("overflow-hidden")}
|
className={cn("overflow-hidden flex flex-col flex-1")}
|
||||||
>
|
>
|
||||||
<div
|
<div className="flex flex-col flex-1">
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
flex: 1,
|
|
||||||
height: "90vh",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<NewChatButton />
|
<NewChatButton />
|
||||||
<div style={{ flex: 1, overflow: "scroll", height: "100%" }}>
|
<div className="flex-1 overflow-auto scrollbar h-full">
|
||||||
{allChats.map((chat) => (
|
{allChats.map((chat) => (
|
||||||
<ChatsListItem
|
<ChatsListItem
|
||||||
key={chat.chat_id}
|
key={chat.chat_id}
|
||||||
|
@ -19,7 +19,7 @@ const Layout = ({ children }: LayoutProps): JSX.Element => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatsProvider>
|
<ChatsProvider>
|
||||||
<div className="relative h-full w-full flex items-start">
|
<div className="relative h-full w-full flex justify-stretch items-stretch">
|
||||||
<ChatsList />
|
<ChatsList />
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,9 +3,12 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
import { FaBrain } from "react-icons/fa";
|
import { FaBrain } from "react-icons/fa";
|
||||||
import { IoMdAdd } from "react-icons/io";
|
import { IoMdAdd } from "react-icons/io";
|
||||||
|
|
||||||
|
import Button from "@/lib/components/ui/Button";
|
||||||
|
import Field from "@/lib/components/ui/Field";
|
||||||
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
||||||
import { useEventTracking } from "@/services/analytics/useEventTracking";
|
import { useEventTracking } from "@/services/analytics/useEventTracking";
|
||||||
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
|
import { MdCheck } from "react-icons/md";
|
||||||
|
|
||||||
export const BrainsDropDown = (): JSX.Element => {
|
export const BrainsDropDown = (): JSX.Element => {
|
||||||
const [showDropdown, setShowDropdown] = useState(false);
|
const [showDropdown, setShowDropdown] = useState(false);
|
||||||
@ -17,7 +20,7 @@ export const BrainsDropDown = (): JSX.Element => {
|
|||||||
|
|
||||||
const toggleDropdown = () => {
|
const toggleDropdown = () => {
|
||||||
setShowDropdown((prevState) => !prevState);
|
setShowDropdown((prevState) => !prevState);
|
||||||
void track("SHOW_BRAINS_DROPDOWN")
|
void track("SHOW_BRAINS_DROPDOWN");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateBrain = () => {
|
const handleCreateBrain = () => {
|
||||||
@ -27,7 +30,7 @@ export const BrainsDropDown = (): JSX.Element => {
|
|||||||
|
|
||||||
void createBrain(newBrainName);
|
void createBrain(newBrainName);
|
||||||
setNewBrainName(""); // Reset the new brain name input
|
setNewBrainName(""); // Reset the new brain name input
|
||||||
void track("BRAIN_CREATED")
|
void track("BRAIN_CREATED");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
@ -40,9 +43,9 @@ export const BrainsDropDown = (): JSX.Element => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const changeBrains = (value: string) => {
|
const changeBrains = (value: string) => {
|
||||||
void track("CHANGE_BRAIN")
|
void track("CHANGE_BRAIN");
|
||||||
setNewBrainName(value)
|
setNewBrainName(value);
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.addEventListener("mousedown", handleClickOutside);
|
document.addEventListener("mousedown", handleClickOutside);
|
||||||
@ -63,42 +66,58 @@ export const BrainsDropDown = (): JSX.Element => {
|
|||||||
>
|
>
|
||||||
<FaBrain className="w-6 h-6" />
|
<FaBrain className="w-6 h-6" />
|
||||||
</button>
|
</button>
|
||||||
{showDropdown && (
|
<AnimatePresence>
|
||||||
<div className="absolute overflow-scroll right-0 mt-2 w-96 h-52 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-lg">
|
{showDropdown && (
|
||||||
{/* Option to create a new brain */}
|
<motion.div
|
||||||
<div className="px-4 py-2">
|
initial={{ opacity: 0, y: -32, height: "0" }}
|
||||||
<div className="flex items-center">
|
animate={{
|
||||||
<input
|
opacity: 1,
|
||||||
type="text"
|
y: 0,
|
||||||
placeholder="Add a new brain"
|
height: "13rem",
|
||||||
value={newBrainName}
|
}}
|
||||||
onChange={(e) => changeBrains(e.target.value)}
|
exit={{ opacity: 0, y: -32, height: "0" }}
|
||||||
className="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:outline-none"
|
transition={{ duration: 0.2, ease: "easeInOut" }}
|
||||||
/>
|
className="absolute right-0 mt-2 w-96 flex flex-col bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-lg"
|
||||||
<button
|
>
|
||||||
type="button"
|
{/* Option to create a new brain */}
|
||||||
className="flex-shrink-0 ml-2 px-3 py-2 text-sm font-medium leading-5 text-white transition-colors duration-200 transform bg-blue-600 border border-transparent rounded-lg hover:bg-blue-500 focus:outline-none focus:bg-blue-500"
|
<form
|
||||||
onClick={handleCreateBrain}
|
onSubmit={(e) => {
|
||||||
>
|
e.preventDefault();
|
||||||
<IoMdAdd className="w-5 h-5" />
|
handleCreateBrain();
|
||||||
</button>
|
}}
|
||||||
</div>
|
className="flex items-center gap-2 p-2"
|
||||||
</div>
|
|
||||||
{/* List of brains */}
|
|
||||||
{allBrains.map((brain) => (
|
|
||||||
<button
|
|
||||||
key={brain.id}
|
|
||||||
type="button"
|
|
||||||
className={`block w-full text-left px-4 py-2 text-sm leading-5 ${
|
|
||||||
currentBrain?.id === brain.id ? "bg-blue-100" : ""
|
|
||||||
} text-gray-900 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:bg-gray-100 dark:focus:bg-gray-700 focus:outline-none`}
|
|
||||||
onClick={() => setActiveBrain({ ...brain })}
|
|
||||||
>
|
>
|
||||||
{brain.name}
|
<Field
|
||||||
</button>
|
name="brainname"
|
||||||
))}
|
placeholder="Add a new brain"
|
||||||
</div>
|
autoFocus
|
||||||
)}
|
onChange={(e) => changeBrains(e.target.value)}
|
||||||
|
/>
|
||||||
|
<Button type="submit" className="px-2 py-2">
|
||||||
|
<IoMdAdd className="w-5 h-5" />
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
<div className="overflow-auto scrollbar flex flex-col h-full">
|
||||||
|
{/* List of brains */}
|
||||||
|
{allBrains.map((brain) => (
|
||||||
|
<button
|
||||||
|
key={brain.id}
|
||||||
|
type="button"
|
||||||
|
className={`flex items-center gap-2 w-full text-left px-4 py-2 text-sm leading-5 text-gray-900 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:bg-gray-100 dark:focus:bg-gray-700 focus:outline-none`}
|
||||||
|
onClick={() => setActiveBrain({ ...brain })}
|
||||||
|
>
|
||||||
|
<span className="flex-1">{brain.name}</span>
|
||||||
|
<span>
|
||||||
|
{currentBrain?.id === brain.id && (
|
||||||
|
<MdCheck className="text-xl" width={32} height={32} />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user