{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "feedback",
  "type": "registry:component",
  "title": "Feedback",
  "description": "A premium feedback component with morphing icons, smooth transitions, and a refined dark mode experience.",
  "dependencies": [
    "@hugeicons/core-free-icons",
    "@hugeicons/react",
    "lucide-react",
    "motion",
    "react-icons"
  ],
  "files": [
    {
      "path": "components/watermelon/feedback.tsx",
      "type": "registry:component",
      "content": "import React, { useState } from 'react';\nimport { motion, AnimatePresence, LayoutGroup } from 'motion/react';\nimport { X, Sparkle } from 'lucide-react';\nimport { Navigation03Icon } from '@hugeicons/core-free-icons';\nimport { HugeiconsIcon } from '@hugeicons/react';\nimport {\n  FaRegThumbsUp,\n  FaThumbsUp,\n  FaRegThumbsDown,\n  FaThumbsDown,\n} from 'react-icons/fa6';\n\ninterface FeedbackComponentProps {\n  onSubmit?: (data: { rating: 'up' | 'down'; feedback: string }) => void;\n}\n\nconst SPRING_CONFIG = {\n  ease: 'easeInOut' as const,\n  duration: 0.3,\n};\n\nexport const FeedbackComponent: React.FC<FeedbackComponentProps> = ({\n  onSubmit,\n}) => {\n  const [isOpen, setIsOpen] = useState(false);\n  const [activeRating, setActiveRating] = useState<'up' | 'down' | null>(null);\n  const [animatingIcon, setAnimatingIcon] = useState<'up' | 'down' | null>(\n    null,\n  );\n  const [feedback, setFeedback] = useState('');\n  const [isSubmitting, setIsSubmitting] = useState(false);\n\n  const handleOpen = (type: 'up' | 'down') => {\n    if (animatingIcon) return; // Prevent double clicks during animation\n    setActiveRating(type);\n    setAnimatingIcon(type);\n\n    // Wait for the thumb pop animation to finish before expanding the card\n    setTimeout(() => {\n      setIsOpen(true);\n      setAnimatingIcon(null);\n    }, 500);\n  };\n\n  const handleClose = () => {\n    setIsOpen(false);\n    setTimeout(() => {\n      setActiveRating(null);\n      setFeedback('');\n    }, 400);\n  };\n\n  const handleSubmit = (e: React.FormEvent) => {\n    e.preventDefault();\n    if (!activeRating) return;\n    setIsSubmitting(true);\n    setTimeout(() => {\n      onSubmit?.({ rating: activeRating, feedback });\n      setIsSubmitting(false);\n      handleClose();\n    }, 800);\n  };\n\n  return (\n    <div className=\"relative flex min-h-[400px] w-full items-center justify-center px-4\">\n      <LayoutGroup id=\"feedback-group\">\n        <AnimatePresence mode=\"popLayout\">\n          {!isOpen ? (\n            <motion.div\n              key=\"initial-buttons\"\n              className=\"flex gap-4\"\n              initial={{ opacity: 0 }}\n              animate={{ opacity: 1 }}\n              exit={{ opacity: 0, transition: { duration: 0.1 } }}\n            >\n              {(['up', 'down'] as const).map((type) => (\n                <motion.button\n                  key={type}\n                  layoutId={\n                    activeRating === type ? 'feedback-card' : `button-${type}`\n                  }\n                  onClick={() => handleOpen(type)}\n                  whileHover={{ scale: 1.05 }}\n                  whileTap={{ scale: 0.95 }}\n                  transition={SPRING_CONFIG}\n                  className=\"relative flex h-16 w-16 items-center justify-center overflow-visible rounded-[22px] bg-neutral-800 shadow-xl\"\n                >\n                  <AnimatePresence>\n                    {animatingIcon === type && (\n                      <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n                        {[...Array(6)].map((_, i) => {\n                          const angle = (i * 60 * Math.PI) / 180;\n                          const distance = 45;\n                          return (\n                            <motion.div\n                              key={`sparkle-${i}`}\n                              className={`absolute ${\n                                type === 'up'\n                                  ? 'text-neutral-100'\n                                  : 'text-neutral-100'  \n                              }`}\n                              initial={{\n                                scale: 0,\n                                x: 0,\n                                y: 0,\n                                opacity: 1,\n                                rotate: 0,\n                              }}\n                              animate={{\n                                scale: [0, 1.2, 0],\n                                x: Math.cos(angle) * distance,\n                                y: Math.sin(angle) * distance,\n                                opacity: [1, 1, 0],\n                                rotate: [0, 90],\n                              }}\n                              transition={{ duration: 0.5, ease: 'easeOut' }}\n                            >\n                              <Sparkle\n                                className=\"size-3\"\n                                fill=\"currentColor\"\n                              />\n                            </motion.div>\n                          );\n                        })}\n                      </div>\n                    )}\n                  </AnimatePresence>\n\n                  <motion.div\n                    className=\"relative z-10\"\n                    animate={\n                      animatingIcon === type\n                        ? {\n                            scale: [1, 1.8, 1],\n                            rotate: [\n                              0,\n                              type === 'up' ? -35 : 35,\n                              type === 'down' ? 35 : -35,\n                              0,\n                            ],\n                            y: [0, -4, 0],\n                          }\n                        : { scale: 1, rotate: 0, y: 0 }\n                    }\n                    transition={{ duration: 0.5, ease: 'easeOut' }}\n                  >\n                    {type === 'up' ? (\n                      activeRating === 'up' ? (\n                        <FaThumbsUp className=\"h-6 w-6 text-white\" />\n                      ) : (\n                        <FaRegThumbsUp className=\"h-6 w-6 text-white\" />\n                      )\n                    ) : activeRating === 'down' ? (\n                      <FaThumbsDown className=\"h-6 w-6 text-white\" />\n                    ) : (\n                      <FaRegThumbsDown className=\"h-6 w-6 text-white\" />\n                    )}\n                  </motion.div>\n                </motion.button>\n              ))}\n            </motion.div>\n          ) : (\n            <motion.div\n              key=\"modal\"\n              layoutId=\"feedback-card\"\n              className=\"relative z-50 w-xs overflow-hidden rounded-[24px] border border-neutral-200 bg-white p-5 shadow-2xl sm:w-sm sm:rounded-[32px] sm:p-8 dark:border-neutral-800 dark:bg-neutral-900\"\n              transition={SPRING_CONFIG}\n            >\n              <motion.button\n                initial={{ opacity: 0 }}\n                animate={{ opacity: 1 }}\n                exit={{ opacity: 0 }}\n                transition={{ delay: 0.1 }}\n                onClick={(e) => {\n                  e.stopPropagation();\n                  handleClose();\n                }}\n                className=\"absolute top-4 right-4 rounded-full bg-neutral-100 p-1.5 text-neutral-500 transition-all hover:scale-110 hover:text-neutral-700 active:scale-90 sm:top-5 sm:right-5 sm:p-2 dark:bg-neutral-800 dark:text-neutral-400 dark:hover:text-neutral-200\"\n              >\n                <X className=\"h-3.5 w-3.5 sm:h-4 sm:w-4\" strokeWidth={3} />\n              </motion.button>\n\n              <motion.div\n                initial={{ opacity: 0 }}\n                animate={{ opacity: 1 }}\n                exit={{ opacity: 0 }}\n                transition={{ duration: 0.3 }}\n                className=\"relative pt-2\"\n              >\n                <h2 className=\"mb-1.5 pr-8 text-[20px] leading-tight font-bold text-neutral-900 sm:mb-2 sm:text-[24px] dark:text-white\">\n                  Share Feedback\n                </h2>\n\n                <p className=\"mb-5 pr-6 text-[14px] leading-relaxed text-neutral-500 sm:mb-6 sm:text-[16px] dark:text-neutral-400\">\n                  {activeRating === 'up'\n                    ? 'Let us know what you liked most?'\n                    : 'What can we improve?'}\n                </p>\n\n                <form onSubmit={handleSubmit} className=\"space-y-4\">\n                  <div>\n                    <textarea\n                      autoFocus\n                      value={feedback}\n                      onChange={(e) => setFeedback(e.target.value)}\n                      placeholder=\"Type in your feedback (optional)\"\n                      className=\"h-32 w-full resize-none rounded-2xl border border-neutral-200 bg-neutral-100 p-4 text-neutral-800 transition-all outline-none focus:ring-2 focus:ring-black dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-200 dark:focus:ring-white\"\n                    />\n                  </div>\n\n                  <button\n                    type=\"submit\"\n                    disabled={isSubmitting}\n                    className=\"flex items-center gap-2 rounded-xl bg-black px-6 py-3 font-bold text-white shadow-lg transition-all hover:opacity-90 active:scale-95 disabled:opacity-50 dark:bg-white dark:text-black\"\n                  >\n                    <HugeiconsIcon\n                      icon={Navigation03Icon}\n                      size={18}\n                      className=\"fill-current\"\n                    />\n                    <span>{isSubmitting ? 'Sending...' : 'Send Now'}</span>\n                  </button>\n                </form>\n              </motion.div>\n            </motion.div>\n          )}\n        </AnimatePresence>\n      </LayoutGroup>\n    </div>\n  );\n};\n"
    }
  ]
}
