Improve sidebar, new chat, and share dialog (#190)
This commit is contained in:
parent
35e83dc87e
commit
be90a40427
23 changed files with 598 additions and 217 deletions
|
|
@ -1,10 +1,12 @@
|
|||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
|
||||
import { type Chat } from '@/lib/types'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { motion } from 'framer-motion'
|
||||
|
||||
import { buttonVariants } from '@/components/ui/button'
|
||||
import { IconMessage, IconUsers } from '@/components/ui/icons'
|
||||
import {
|
||||
|
|
@ -12,20 +14,45 @@ import {
|
|||
TooltipContent,
|
||||
TooltipTrigger
|
||||
} from '@/components/ui/tooltip'
|
||||
import { useLocalStorage } from '@/lib/hooks/use-local-storage'
|
||||
import { type Chat } from '@/lib/types'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface SidebarItemProps {
|
||||
index: number
|
||||
chat: Chat
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function SidebarItem({ chat, children }: SidebarItemProps) {
|
||||
export function SidebarItem({ index, chat, children }: SidebarItemProps) {
|
||||
const pathname = usePathname()
|
||||
|
||||
const isActive = pathname === chat.path
|
||||
const [newChatId, setNewChatId] = useLocalStorage('newChatId', null)
|
||||
const shouldAnimate = index === 0 && isActive && newChatId
|
||||
|
||||
if (!chat?.id) return null
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<motion.div
|
||||
className="relative h-8"
|
||||
variants={{
|
||||
initial: {
|
||||
height: 0,
|
||||
opacity: 0
|
||||
},
|
||||
animate: {
|
||||
height: 'auto',
|
||||
opacity: 1
|
||||
}
|
||||
}}
|
||||
initial={shouldAnimate ? 'initial' : undefined}
|
||||
animate={shouldAnimate ? 'animate' : undefined}
|
||||
transition={{
|
||||
duration: 0.25,
|
||||
ease: 'easeIn'
|
||||
}}
|
||||
>
|
||||
<div className="absolute left-2 top-1 flex h-6 w-6 items-center justify-center">
|
||||
{chat.sharePath ? (
|
||||
<Tooltip delayDuration={1000}>
|
||||
|
|
@ -45,18 +72,53 @@ export function SidebarItem({ chat, children }: SidebarItemProps) {
|
|||
href={chat.path}
|
||||
className={cn(
|
||||
buttonVariants({ variant: 'ghost' }),
|
||||
'group w-full pl-8 pr-16',
|
||||
isActive && 'bg-accent'
|
||||
'group w-full px-8 transition-colors hover:bg-zinc-200/40 dark:hover:bg-zinc-300/10',
|
||||
isActive && 'bg-zinc-200 pr-16 font-semibold dark:bg-zinc-800'
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="relative max-h-5 flex-1 select-none overflow-hidden text-ellipsis break-all"
|
||||
title={chat.title}
|
||||
>
|
||||
<span className="whitespace-nowrap">{chat.title}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{shouldAnimate ? (
|
||||
chat.title.split('').map((character, index) => (
|
||||
<motion.span
|
||||
key={index}
|
||||
variants={{
|
||||
initial: {
|
||||
opacity: 0,
|
||||
x: -100
|
||||
},
|
||||
animate: {
|
||||
opacity: 1,
|
||||
x: 0
|
||||
}
|
||||
}}
|
||||
initial={shouldAnimate ? 'initial' : undefined}
|
||||
animate={shouldAnimate ? 'animate' : undefined}
|
||||
transition={{
|
||||
duration: 0.25,
|
||||
ease: 'easeIn',
|
||||
delay: index * 0.05,
|
||||
staggerChildren: 0.05
|
||||
}}
|
||||
onAnimationComplete={() => {
|
||||
if (index === chat.title.length - 1) {
|
||||
setNewChatId(null)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{character}
|
||||
</motion.span>
|
||||
))
|
||||
) : (
|
||||
<span>{chat.title}</span>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
{isActive && <div className="absolute right-2 top-1">{children}</div>}
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue