{ "name": "toolbar-expandable", "type": "registry:ui", "registryDependencies": [], "dependencies": [ "motion", "react-use-measure" ], "devDependencies": [], "tailwind": {}, "cssVars": { "light": {}, "dark": {} }, "files": [ { "path": "toolbar-expandable.tsx", "content": "'use client';\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport useMeasure from 'react-use-measure';\nimport { AnimatePresence, motion, MotionConfig } from 'motion/react';\nimport { cn } from '@/lib/utils';\nimport useClickOutside from '@/hooks/useClickOutside';\nimport { Folder, MessageCircle, User, WalletCards } from 'lucide-react';\n\nconst transition = {\n type: 'spring',\n bounce: 0.1,\n duration: 0.25,\n};\n\nconst ITEMS = [\n {\n id: 1,\n label: 'User',\n title: ,\n content: (\n
\n
\n
\n Ibelick\n
\n \n Edit Profile\n \n
\n ),\n },\n {\n id: 2,\n label: 'Messages',\n title: ,\n content: (\n
\n
You have 3 new messages.
\n \n View more\n \n
\n ),\n },\n {\n id: 3,\n label: 'Documents',\n title: ,\n content: (\n
\n
\n
\n
Project_Proposal.pdf
\n
Meeting_Notes.docx
\n
Financial_Report.xls
\n
\n
\n \n Manage documents\n \n
\n ),\n },\n {\n id: 4,\n label: 'Wallet',\n title: ,\n content: (\n
\n
\n Current Balance\n $1,250.32\n
\n \n View Transactions\n \n
\n ),\n },\n];\n\nexport default function ToolbarExpandable() {\n const [active, setActive] = useState(null);\n const [contentRef, { height: heightContent }] = useMeasure();\n const [menuRef, { width: widthContainer }] = useMeasure();\n const ref = useRef(null);\n const [isOpen, setIsOpen] = useState(false);\n const [maxWidth, setMaxWidth] = useState(0);\n\n useClickOutside(ref, () => {\n setIsOpen(false);\n setActive(null);\n });\n\n useEffect(() => {\n if (!widthContainer || maxWidth > 0) return;\n\n setMaxWidth(widthContainer);\n }, [widthContainer, maxWidth]);\n\n return (\n \n
\n
\n
\n \n {isOpen ? (\n \n
\n {ITEMS.map((item) => {\n const isSelected = active === item.id;\n\n return (\n \n \n {item.content}\n
\n \n );\n })}\n
\n \n ) : null}\n \n
\n
\n {ITEMS.map((item) => (\n {\n if (!isOpen) setIsOpen(true);\n if (active === item.id) {\n setIsOpen(false);\n setActive(null);\n return;\n }\n\n setActive(item.id);\n }}\n >\n {item.title}\n \n ))}\n
\n
\n
\n \n );\n}\n", "type": "registry:ui" }, { "path": "hooks/useClickOutside.tsx", "content": "import { RefObject, useEffect } from 'react';\n\nfunction useClickOutside(\n ref: RefObject,\n handler: (event: MouseEvent | TouchEvent) => void\n): void {\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent | TouchEvent) => {\n if (!ref || !ref.current || ref.current.contains(event.target as Node)) {\n return;\n }\n\n handler(event);\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('touchstart', handleClickOutside);\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('touchstart', handleClickOutside);\n };\n }, [ref, handler]);\n}\n\nexport default useClickOutside;\n", "type": "registry:hook" } ] }