mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-12-23 20:18:15 +00:00
feat(app): enhance attach transition
This commit is contained in:
@@ -16,6 +16,8 @@ import {
|
|||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { Fragment, useRef, useState } from 'react';
|
import { Fragment, useRef, useState } from 'react';
|
||||||
import { useChat } from '@/lib/hooks/useChat';
|
import { useChat } from '@/lib/hooks/useChat';
|
||||||
|
import { AnimatePresence } from 'motion/react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
const Attach = () => {
|
const Attach = () => {
|
||||||
const { files, setFiles, setFileIds, fileIds } = useChat();
|
const { files, setFiles, setFileIds, fileIds } = useChat();
|
||||||
@@ -53,29 +55,33 @@ const Attach = () => {
|
|||||||
|
|
||||||
return loading ? (
|
return loading ? (
|
||||||
<div className="active:border-none hover:bg-light-200 hover:dark:bg-dark-200 p-2 rounded-lg focus:outline-none text-black/50 dark:text-white/50 transition duration-200">
|
<div className="active:border-none hover:bg-light-200 hover:dark:bg-dark-200 p-2 rounded-lg focus:outline-none text-black/50 dark:text-white/50 transition duration-200">
|
||||||
<LoaderCircle size={16} className="text-sky-400 animate-spin" />
|
<LoaderCircle size={16} className="text-sky-500 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
) : files.length > 0 ? (
|
) : files.length > 0 ? (
|
||||||
<Popover className="relative w-full max-w-[15rem] md:max-w-md lg:max-w-lg">
|
<Popover className="relative w-full max-w-[15rem] md:max-w-md lg:max-w-lg">
|
||||||
|
{({ open }) => (
|
||||||
|
<>
|
||||||
<PopoverButton
|
<PopoverButton
|
||||||
type="button"
|
type="button"
|
||||||
className="active:border-none hover:bg-light-200 hover:dark:bg-dark-200 p-2 rounded-lg focus:outline-none headless-open:text-black dark:headless-open:text-white text-black/50 dark:text-white/50 active:scale-95 transition duration-200 hover:text-black dark:hover:text-white"
|
className="active:border-none hover:bg-light-200 hover:dark:bg-dark-200 p-2 rounded-lg focus:outline-none headless-open:text-black dark:headless-open:text-white text-black/50 dark:text-white/50 active:scale-95 transition duration-200 hover:text-black dark:hover:text-white"
|
||||||
>
|
>
|
||||||
<File size={16} className="text-sky-400" />
|
<File size={16} className="text-sky-500" />
|
||||||
</PopoverButton>
|
</PopoverButton>
|
||||||
<Transition
|
<AnimatePresence>
|
||||||
as={Fragment}
|
{open && (
|
||||||
enter="transition ease-out duration-150"
|
<PopoverPanel
|
||||||
enterFrom="opacity-0 translate-y-1"
|
className="absolute z-10 w-64 md:w-[350px] right-0"
|
||||||
enterTo="opacity-100 translate-y-0"
|
static
|
||||||
leave="transition ease-in duration-150"
|
>
|
||||||
leaveFrom="opacity-100 translate-y-0"
|
<motion.div
|
||||||
leaveTo="opacity-0 translate-y-1"
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
exit={{ opacity: 0, scale: 0.9 }}
|
||||||
|
transition={{ duration: 0.1, ease: 'easeOut' }}
|
||||||
|
className="origin-top-right bg-light-primary dark:bg-dark-primary border rounded-md border-light-200 dark:border-dark-200 w-full max-h-[200px] md:max-h-none overflow-y-auto flex flex-col"
|
||||||
>
|
>
|
||||||
<PopoverPanel className="absolute z-10 w-64 md:w-[350px] right-0">
|
|
||||||
<div className="bg-light-primary dark:bg-dark-primary border rounded-md border-light-200 dark:border-dark-200 w-full max-h-[200px] md:max-h-none overflow-y-auto flex flex-col">
|
|
||||||
<div className="flex flex-row items-center justify-between px-3 py-2">
|
<div className="flex flex-row items-center justify-between px-3 py-2">
|
||||||
<h4 className="text-black dark:text-white font-medium text-sm">
|
<h4 className="text-black/70 dark:text-white/70 text-sm">
|
||||||
Attached files
|
Attached files
|
||||||
</h4>
|
</h4>
|
||||||
<div className="flex flex-row items-center space-x-4">
|
<div className="flex flex-row items-center space-x-4">
|
||||||
@@ -102,7 +108,7 @@ const Attach = () => {
|
|||||||
}}
|
}}
|
||||||
className="flex flex-row items-center space-x-1 text-black/70 dark:text-white/70 hover:text-black hover:dark:text-white transition duration-200 focus:outline-none"
|
className="flex flex-row items-center space-x-1 text-black/70 dark:text-white/70 hover:text-black hover:dark:text-white transition duration-200 focus:outline-none"
|
||||||
>
|
>
|
||||||
<Trash size={14} />
|
<Trash size={13} />
|
||||||
<p className="text-xs">Clear</p>
|
<p className="text-xs">Clear</p>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -114,15 +120,17 @@ const Attach = () => {
|
|||||||
key={i}
|
key={i}
|
||||||
className="flex flex-row items-center justify-start w-full space-x-3 p-3"
|
className="flex flex-row items-center justify-start w-full space-x-3 p-3"
|
||||||
>
|
>
|
||||||
<div className="bg-light-100 dark:bg-dark-100 flex items-center justify-center w-10 h-10 rounded-md">
|
<div className="bg-light-100 dark:bg-dark-100 flex items-center justify-center w-9 h-9 rounded-md">
|
||||||
<File
|
<File
|
||||||
size={16}
|
size={16}
|
||||||
className="text-black/70 dark:text-white/70"
|
className="text-black/70 dark:text-white/70"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-black/70 dark:text-white/70 text-sm">
|
<p className="text-black/70 dark:text-white/70 text-xs">
|
||||||
{file.fileName.length > 25
|
{file.fileName.length > 25
|
||||||
? file.fileName.replace(/\.\w+$/, '').substring(0, 25) +
|
? file.fileName
|
||||||
|
.replace(/\.\w+$/, '')
|
||||||
|
.substring(0, 25) +
|
||||||
'...' +
|
'...' +
|
||||||
file.fileExtension
|
file.fileExtension
|
||||||
: file.fileName}
|
: file.fileName}
|
||||||
@@ -130,9 +138,12 @@ const Attach = () => {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
</PopoverPanel>
|
</PopoverPanel>
|
||||||
</Transition>
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Popover>
|
</Popover>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -1,21 +1,14 @@
|
|||||||
import { cn } from '@/lib/utils';
|
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
PopoverButton,
|
PopoverButton,
|
||||||
PopoverPanel,
|
PopoverPanel,
|
||||||
Transition,
|
Transition,
|
||||||
} from '@headlessui/react';
|
} from '@headlessui/react';
|
||||||
import {
|
import { File, LoaderCircle, Paperclip, Plus, Trash } from 'lucide-react';
|
||||||
CopyPlus,
|
|
||||||
File,
|
|
||||||
LoaderCircle,
|
|
||||||
Paperclip,
|
|
||||||
Plus,
|
|
||||||
Trash,
|
|
||||||
} from 'lucide-react';
|
|
||||||
import { Fragment, useRef, useState } from 'react';
|
import { Fragment, useRef, useState } from 'react';
|
||||||
import { File as FileType } from '../ChatWindow';
|
|
||||||
import { useChat } from '@/lib/hooks/useChat';
|
import { useChat } from '@/lib/hooks/useChat';
|
||||||
|
import { AnimatePresence } from 'motion/react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
const AttachSmall = () => {
|
const AttachSmall = () => {
|
||||||
const { files, setFiles, setFileIds, fileIds } = useChat();
|
const { files, setFiles, setFileIds, fileIds } = useChat();
|
||||||
@@ -53,29 +46,33 @@ const AttachSmall = () => {
|
|||||||
|
|
||||||
return loading ? (
|
return loading ? (
|
||||||
<div className="flex flex-row items-center justify-between space-x-1 p-1 ">
|
<div className="flex flex-row items-center justify-between space-x-1 p-1 ">
|
||||||
<LoaderCircle size={20} className="text-sky-400 animate-spin" />
|
<LoaderCircle size={20} className="text-sky-500 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
) : files.length > 0 ? (
|
) : files.length > 0 ? (
|
||||||
<Popover className="max-w-[15rem] md:max-w-md lg:max-w-lg">
|
<Popover className="max-w-[15rem] md:max-w-md lg:max-w-lg">
|
||||||
|
{({ open }) => (
|
||||||
|
<>
|
||||||
<PopoverButton
|
<PopoverButton
|
||||||
type="button"
|
type="button"
|
||||||
className="flex flex-row items-center justify-between space-x-1 p-1 text-black/50 dark:text-white/50 rounded-xl hover:bg-light-secondary dark:hover:bg-dark-secondary active:scale-95 transition duration-200 hover:text-black dark:hover:text-white"
|
className="flex flex-row items-center justify-between space-x-1 p-1 text-black/50 dark:text-white/50 rounded-xl hover:bg-light-secondary dark:hover:bg-dark-secondary active:scale-95 transition duration-200 hover:text-black dark:hover:text-white"
|
||||||
>
|
>
|
||||||
<File size={20} className="text-sky-400" />
|
<File size={20} className="text-sky-500" />
|
||||||
</PopoverButton>
|
</PopoverButton>
|
||||||
<Transition
|
<AnimatePresence>
|
||||||
as={Fragment}
|
{open && (
|
||||||
enter="transition ease-out duration-150"
|
<PopoverPanel
|
||||||
enterFrom="opacity-0 translate-y-1"
|
className="absolute z-10 w-64 md:w-[350px] bottom-14"
|
||||||
enterTo="opacity-100 translate-y-0"
|
static
|
||||||
leave="transition ease-in duration-150"
|
>
|
||||||
leaveFrom="opacity-100 translate-y-0"
|
<motion.div
|
||||||
leaveTo="opacity-0 translate-y-1"
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
exit={{ opacity: 0, scale: 0.9 }}
|
||||||
|
transition={{ duration: 0.1, ease: 'easeOut' }}
|
||||||
|
className="origin-bottom-left bg-light-primary dark:bg-dark-primary border rounded-md border-light-200 dark:border-dark-200 w-full max-h-[200px] md:max-h-none overflow-y-auto flex flex-col"
|
||||||
>
|
>
|
||||||
<PopoverPanel className="absolute z-10 w-64 md:w-[350px] bottom-14 -ml-3">
|
|
||||||
<div className="bg-light-primary dark:bg-dark-primary border rounded-md border-light-200 dark:border-dark-200 w-full max-h-[200px] md:max-h-none overflow-y-auto flex flex-col">
|
|
||||||
<div className="flex flex-row items-center justify-between px-3 py-2">
|
<div className="flex flex-row items-center justify-between px-3 py-2">
|
||||||
<h4 className="text-black dark:text-white font-medium text-sm">
|
<h4 className="text-black/70 dark:text-white/70 font-medium text-sm">
|
||||||
Attached files
|
Attached files
|
||||||
</h4>
|
</h4>
|
||||||
<div className="flex flex-row items-center space-x-4">
|
<div className="flex flex-row items-center space-x-4">
|
||||||
@@ -92,7 +89,7 @@ const AttachSmall = () => {
|
|||||||
multiple
|
multiple
|
||||||
hidden
|
hidden
|
||||||
/>
|
/>
|
||||||
<Plus size={18} />
|
<Plus size={16} />
|
||||||
<p className="text-xs">Add</p>
|
<p className="text-xs">Add</p>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@@ -102,7 +99,7 @@ const AttachSmall = () => {
|
|||||||
}}
|
}}
|
||||||
className="flex flex-row items-center space-x-1 text-black/70 dark:text-white/70 hover:text-black hover:dark:text-white transition duration-200"
|
className="flex flex-row items-center space-x-1 text-black/70 dark:text-white/70 hover:text-black hover:dark:text-white transition duration-200"
|
||||||
>
|
>
|
||||||
<Trash size={14} />
|
<Trash size={13} />
|
||||||
<p className="text-xs">Clear</p>
|
<p className="text-xs">Clear</p>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -114,15 +111,17 @@ const AttachSmall = () => {
|
|||||||
key={i}
|
key={i}
|
||||||
className="flex flex-row items-center justify-start w-full space-x-3 p-3"
|
className="flex flex-row items-center justify-start w-full space-x-3 p-3"
|
||||||
>
|
>
|
||||||
<div className="bg-light-100 dark:bg-dark-100 flex items-center justify-center w-10 h-10 rounded-md">
|
<div className="bg-light-100 dark:bg-dark-100 flex items-center justify-center w-9 h-9 rounded-md">
|
||||||
<File
|
<File
|
||||||
size={16}
|
size={16}
|
||||||
className="text-black/70 dark:text-white/70"
|
className="text-black/70 dark:text-white/70"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-black/70 dark:text-white/70 text-sm">
|
<p className="text-black/70 dark:text-white/70 text-xs">
|
||||||
{file.fileName.length > 25
|
{file.fileName.length > 25
|
||||||
? file.fileName.replace(/\.\w+$/, '').substring(0, 25) +
|
? file.fileName
|
||||||
|
.replace(/\.\w+$/, '')
|
||||||
|
.substring(0, 25) +
|
||||||
'...' +
|
'...' +
|
||||||
file.fileExtension
|
file.fileExtension
|
||||||
: file.fileName}
|
: file.fileName}
|
||||||
@@ -130,9 +129,12 @@ const AttachSmall = () => {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
</PopoverPanel>
|
</PopoverPanel>
|
||||||
</Transition>
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Popover>
|
</Popover>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
|||||||
Reference in New Issue
Block a user