'use client'; import React, { useEffect, useRef, useState } from 'react'; import useMeasure from 'react-use-measure'; import { AnimatePresence, motion, MotionConfig } from 'motion/react'; import { cn } from '@/lib/utils'; import useClickOutside from '@/hooks/useClickOutside'; import { Folder, MessageCircle, User, WalletCards } from 'lucide-react'; const transition = { type: 'spring', bounce: 0.1, duration: 0.25, }; const ITEMS = [ { id: 1, label: 'User', title: <User className='h-5 w-5' />, content: ( <div className='flex flex-col space-y-4'> <div className='flex flex-col space-y-1 text-zinc-700'> <div className='h-8 w-8 rounded-full bg-linear-to-br from-blue-500 to-blue-400' /> <span>Ibelick</span> </div> <button className='relative h-8 w-full scale-100 select-none appearance-none items-center justify-center rounded-lg border border-zinc-950/10 px-2 text-sm text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-800 focus-visible:ring-2 active:scale-[0.98]' type='button' > Edit Profile </button> </div> ), }, { id: 2, label: 'Messages', title: <MessageCircle className='h-5 w-5' />, content: ( <div className='flex flex-col space-y-4'> <div className='text-zinc-700'>You have 3 new messages.</div> <button className='relative h-8 w-full scale-100 select-none appearance-none items-center justify-center rounded-lg border border-zinc-950/10 px-2 text-sm text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-800 focus-visible:ring-2 active:scale-[0.98]' type='button' > View more </button> </div> ), }, { id: 3, label: 'Documents', title: <Folder className='h-5 w-5' />, content: ( <div className='flex flex-col space-y-4'> <div className='flex flex-col text-zinc-700'> <div className='space-y-1'> <div>Project_Proposal.pdf</div> <div>Meeting_Notes.docx</div> <div>Financial_Report.xls</div> </div> </div> <button className='relative h-8 w-full scale-100 select-none appearance-none items-center justify-center rounded-lg border border-zinc-950/10 px-2 text-sm text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-800 focus-visible:ring-2 active:scale-[0.98]' type='button' > Manage documents </button> </div> ), }, { id: 4, label: 'Wallet', title: <WalletCards className='h-5 w-5' />, content: ( <div className='flex flex-col space-y-4'> <div className='flex flex-col text-zinc-700'> <span>Current Balance</span> <span>$1,250.32</span> </div> <button className='relative h-8 w-full scale-100 select-none appearance-none items-center justify-center rounded-lg border border-zinc-950/10 px-2 text-sm text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-800 focus-visible:ring-2 active:scale-[0.98]' type='button' > View Transactions </button> </div> ), }, ]; export default function ToolbarExpandable() { const [active, setActive] = useState<number | null>(null); const [contentRef, { height: heightContent }] = useMeasure(); const [menuRef, { width: widthContainer }] = useMeasure(); const ref = useRef<HTMLDivElement>(null); const [isOpen, setIsOpen] = useState(false); const [maxWidth, setMaxWidth] = useState(0); useClickOutside(ref, () => { setIsOpen(false); setActive(null); }); useEffect(() => { if (!widthContainer || maxWidth > 0) return; setMaxWidth(widthContainer); }, [widthContainer, maxWidth]); return ( <MotionConfig transition={transition}> <div className='absolute bottom-8' ref={ref}> <div className='h-full w-full rounded-xl border border-zinc-950/10 bg-white'> <div className='overflow-hidden'> <AnimatePresence initial={false} mode='sync'> {isOpen ? ( <motion.div key='content' initial={{ height: 0 }} animate={{ height: heightContent || 0 }} exit={{ height: 0 }} style={{ width: maxWidth, }} > <div ref={contentRef} className='p-2'> {ITEMS.map((item) => { const isSelected = active === item.id; return ( <motion.div key={item.id} initial={{ opacity: 0 }} animate={{ opacity: isSelected ? 1 : 0 }} exit={{ opacity: 0 }} > <div className={cn( 'px-2 pt-2 text-sm', isSelected ? 'block' : 'hidden' )} > {item.content} </div> </motion.div> ); })} </div> </motion.div> ) : null} </AnimatePresence> </div> <div className='flex space-x-2 p-2' ref={menuRef}> {ITEMS.map((item) => ( <button key={item.id} aria-label={item.label} className={cn( 'relative flex h-9 w-9 shrink-0 scale-100 select-none appearance-none items-center justify-center rounded-lg text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-800 focus-visible:ring-2 active:scale-[0.98]', active === item.id ? 'bg-zinc-100 text-zinc-800' : '' )} type='button' onClick={() => { if (!isOpen) setIsOpen(true); if (active === item.id) { setIsOpen(false); setActive(null); return; } setActive(item.id); }} > {item.title} </button> ))} </div> </div> </div> </MotionConfig> ); }