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:
Aditya Nandan 2023-06-15 02:28:37 +05:30 committed by GitHub
parent 9af6a250e3
commit e6e5099d6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 79 additions and 27 deletions

View File

@ -6,8 +6,8 @@ import { MdSettings } from "react-icons/md";
export function ConfigButton() {
return (
<Link href={"/config"}>
<Button className="px-3" variant={"tertiary"}>
<MdSettings className="text-2xl" />
<Button className="p-2 sm:px-3" variant={"tertiary"}>
<MdSettings className="text-lg sm:text-xl lg:text-2xl" />
</Button>
</Link>
);

View File

@ -8,16 +8,16 @@ export function MicButton() {
return (
<Button
className="px-3"
className="p-2 sm:px-3"
variant={"tertiary"}
type="button"
onClick={startListening}
disabled={!speechSupported}
>
{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>
);

View File

@ -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"
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"}
</Button>
<MicButton />
<ConfigButton />
<div className="flex items-center">
<MicButton />
<ConfigButton />
</div>
</form>
);
}

View File

@ -1,23 +1,72 @@
"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 ChatsListItem from "./ChatsListItem";
import { NewChatButton } from "./NewChatButton";
export function ChatsList() {
const { allChats, deleteChat } = useChatsContext();
const [open, setOpen] = useState(false);
return (
<div className="sticky top-0 max-h-screen overflow-auto scrollbar">
<aside className="relative bg-white dark:bg-black max-w-xs w-full border-r border-black/10 dark:border-white/25 h-screen">
<NewChatButton />
<div className="flex flex-col gap-0">
{allChats.map((chat) => (
<ChatsListItem
key={chat.chatId}
chat={chat}
deleteChat={deleteChat}
/>
))}
</div>
</aside>
</div>
<MotionConfig transition={{ mass: 1, damping: 10 }}>
<motion.div
drag="x"
dragConstraints={{ right: 0, left: 0 }}
// dragSnapToOrigin
dragElastic={0.15}
onDragEnd={(event, info) => {
if (info.offset.x > 100 && !open) {
setOpen(true);
} else if (info.offset.x < -100 && open) {
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"
>
<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>
);
}

View File

@ -32,17 +32,14 @@ export const anthropicModels = [
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 = [
...openAiModels,
...anthropicModels,
...googleModels,
] as const;
export const paidModels= [
...openAiPaidModels,
...googleModels,
] as const;
export const paidModels = [...openAiPaidModels, ...googleModels] as const;
export type PaidModels = (typeof paidModels)[number];