mirror of
https://github.com/StanGirard/quivr.git
synced 2024-09-11 21:17:36 +03:00
Feat/responsive chat bar (#314)
* feat(chat): close and open chatbar on button toggle * feat(chat): drag to open chat bar * fix(chat): fix warning of not being able to animate shadows * fix(chat): make chat input a little responsive --------- Co-authored-by: Stan Girard <girard.stanislas@gmail.com>
This commit is contained in:
parent
9af6a250e3
commit
e6e5099d6b
@ -6,8 +6,8 @@ import { MdSettings } from "react-icons/md";
|
|||||||
export function ConfigButton() {
|
export function ConfigButton() {
|
||||||
return (
|
return (
|
||||||
<Link href={"/config"}>
|
<Link href={"/config"}>
|
||||||
<Button className="px-3" variant={"tertiary"}>
|
<Button className="p-2 sm:px-3" variant={"tertiary"}>
|
||||||
<MdSettings className="text-2xl" />
|
<MdSettings className="text-lg sm:text-xl lg:text-2xl" />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
@ -8,16 +8,16 @@ export function MicButton() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
className="px-3"
|
className="p-2 sm:px-3"
|
||||||
variant={"tertiary"}
|
variant={"tertiary"}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={startListening}
|
onClick={startListening}
|
||||||
disabled={!speechSupported}
|
disabled={!speechSupported}
|
||||||
>
|
>
|
||||||
{isListening ? (
|
{isListening ? (
|
||||||
<MdMicOff className="text-2xl" />
|
<MdMicOff className="text-lg sm:text-xl lg:text-2xl" />
|
||||||
) : (
|
) : (
|
||||||
<MdMic className="text-2xl" />
|
<MdMic className="text-lg sm:text-xl lg:text-2xl" />
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
@ -28,11 +28,17 @@ export function ChatInput() {
|
|||||||
className="w-full p-2 border border-gray-300 dark:border-gray-500 outline-none rounded dark:bg-gray-800"
|
className="w-full p-2 border border-gray-300 dark:border-gray-500 outline-none rounded dark:bg-gray-800"
|
||||||
placeholder="Begin conversation here..."
|
placeholder="Begin conversation here..."
|
||||||
/>
|
/>
|
||||||
<Button type="submit" isLoading={isSendingMessage}>
|
<Button
|
||||||
|
className="px-3 py-2 sm:px-4 sm:py-2"
|
||||||
|
type="submit"
|
||||||
|
isLoading={isSendingMessage}
|
||||||
|
>
|
||||||
{isSendingMessage ? "Thinking..." : "Chat"}
|
{isSendingMessage ? "Thinking..." : "Chat"}
|
||||||
</Button>
|
</Button>
|
||||||
<MicButton />
|
<div className="flex items-center">
|
||||||
<ConfigButton />
|
<MicButton />
|
||||||
|
<ConfigButton />
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,72 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { MotionConfig, motion } from "framer-motion";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { MdChevronRight } from "react-icons/md";
|
||||||
import useChatsContext from "@/lib/context/ChatsProvider/hooks/useChatsContext";
|
import useChatsContext from "@/lib/context/ChatsProvider/hooks/useChatsContext";
|
||||||
import ChatsListItem from "./ChatsListItem";
|
import ChatsListItem from "./ChatsListItem";
|
||||||
import { NewChatButton } from "./NewChatButton";
|
import { NewChatButton } from "./NewChatButton";
|
||||||
export function ChatsList() {
|
export function ChatsList() {
|
||||||
const { allChats, deleteChat } = useChatsContext();
|
const { allChats, deleteChat } = useChatsContext();
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sticky top-0 max-h-screen overflow-auto scrollbar">
|
<MotionConfig transition={{ mass: 1, damping: 10 }}>
|
||||||
<aside className="relative bg-white dark:bg-black max-w-xs w-full border-r border-black/10 dark:border-white/25 h-screen">
|
<motion.div
|
||||||
<NewChatButton />
|
drag="x"
|
||||||
<div className="flex flex-col gap-0">
|
dragConstraints={{ right: 0, left: 0 }}
|
||||||
{allChats.map((chat) => (
|
// dragSnapToOrigin
|
||||||
<ChatsListItem
|
dragElastic={0.15}
|
||||||
key={chat.chatId}
|
onDragEnd={(event, info) => {
|
||||||
chat={chat}
|
if (info.offset.x > 100 && !open) {
|
||||||
deleteChat={deleteChat}
|
setOpen(true);
|
||||||
/>
|
} else if (info.offset.x < -100 && open) {
|
||||||
))}
|
setOpen(false);
|
||||||
</div>
|
}
|
||||||
</aside>
|
}}
|
||||||
</div>
|
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"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
animate={{
|
||||||
|
width: open ? "fit-content" : "0px",
|
||||||
|
opacity: open ? 1 : 0.5,
|
||||||
|
boxShadow: open
|
||||||
|
? "10px 10px 16px rgba(0, 0, 0, 0)"
|
||||||
|
: "10px 10px 16px rgba(0, 0, 0, 0.5)",
|
||||||
|
// shadow: open ? "none" : "10px 10px 16px black",
|
||||||
|
}}
|
||||||
|
className={cn("overflow-hidden")}
|
||||||
|
>
|
||||||
|
<div className="min-w-fit max-h-screen overflow-auto scrollbar">
|
||||||
|
<aside className="relative max-w-xs w-full h-screen">
|
||||||
|
<NewChatButton />
|
||||||
|
<div className="flex flex-col gap-0">
|
||||||
|
{allChats.map((chat) => (
|
||||||
|
<ChatsListItem
|
||||||
|
key={chat.chatId}
|
||||||
|
chat={chat}
|
||||||
|
deleteChat={deleteChat}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(!open);
|
||||||
|
}}
|
||||||
|
className="absolute left-full top-16 lg:top-0 text-3xl bg-black dark:bg-white text-white dark:text-black rounded-r-full p-3 pl-1"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
whileTap={{ scale: 0.9 }}
|
||||||
|
animate={{ scaleX: open ? -1 : 1 }}
|
||||||
|
>
|
||||||
|
<MdChevronRight />
|
||||||
|
</motion.div>
|
||||||
|
</button>
|
||||||
|
</motion.div>
|
||||||
|
</MotionConfig>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -32,17 +32,14 @@ export const anthropicModels = [
|
|||||||
|
|
||||||
export const googleModels = ["vertexai"] as const; // TODO activate when not in demo mode
|
export const googleModels = ["vertexai"] as const; // TODO activate when not in demo mode
|
||||||
|
|
||||||
// export const googleModels = [] as const;
|
// export const googleModels = [] as const;
|
||||||
export const models = [
|
export const models = [
|
||||||
...openAiModels,
|
...openAiModels,
|
||||||
...anthropicModels,
|
...anthropicModels,
|
||||||
...googleModels,
|
...googleModels,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const paidModels= [
|
export const paidModels = [...openAiPaidModels, ...googleModels] as const;
|
||||||
...openAiPaidModels,
|
|
||||||
...googleModels,
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export type PaidModels = (typeof paidModels)[number];
|
export type PaidModels = (typeof paidModels)[number];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user