{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "feedback-action",
  "type": "registry:component",
  "title": "Feedback Action",
  "description": "Trigger quick user feedback actions through subtle animated interaction buttons.",
  "dependencies": [
    "motion",
    "react-icons"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "components/watermelon/feedback-action.tsx",
      "type": "registry:component",
      "content": "import React, { useState, useEffect } from 'react';\nimport { motion, AnimatePresence, MotionConfig } from 'motion/react';\nimport { LuCircleDotDashed } from 'react-icons/lu';\nimport { FaArrowRotateRight } from 'react-icons/fa6';\nimport { TbAlertOctagonFilled } from 'react-icons/tb';\nimport { cn } from '@/lib/utils';\n\ninterface InlineFeedbackProps {\n  errorMessage?: string;\n  loadingMessage?: string;\n  onRetry?: () => void;\n}\n\nexport const FeedbackAction: React.FC<InlineFeedbackProps> = ({\n  errorMessage = 'Sync Failed',\n  loadingMessage = 'Syncing',\n  onRetry,\n}) => {\n  const [status, setStatus] = useState<'error' | 'loading'>('error');\n\n  const handleRetry = () => {\n    setStatus('loading');\n    onRetry?.();\n  };\n\n  useEffect(() => {\n    if (status === 'loading') {\n      const timer = setTimeout(() => {\n        setStatus('error');\n      }, 3500);\n      return () => clearTimeout(timer);\n    }\n  }, [status]);\n\n  return (\n    <div className=\"flex h-14 items-center gap-3\">\n      <MotionConfig\n        transition={{ type: 'spring', bounce: 0.25, duration: 0.6 }}\n      >\n        <motion.div\n          animate={{ width: 'auto' }}\n          layout\n          initial={false}\n          className={cn(\n            'relative z-20 flex items-center justify-center overflow-hidden border px-6 py-4',\n            status === 'error'\n              ? 'border-neutral-200 bg-neutral-100 dark:border-neutral-800 dark:bg-neutral-900'\n              : 'border-neutral-200 bg-neutral-100 dark:border-neutral-800 dark:bg-neutral-900',\n          )}\n          style={{\n            borderRadius: 32,\n          }}\n        >\n          <motion.div\n            initial={{ opacity: 0, filter: 'blur(8px)' }}\n            animate={{ opacity: 1, filter: 'blur(0px)' }}\n            exit={{ opacity: 0, filter: 'blur(8px)' }}\n            transition={{ type: 'spring', stiffness: 300, damping: 24 }}\n            className=\"flex items-center gap-2\"\n          >\n            <AnimatePresence mode=\"popLayout\">\n              <motion.div\n                layout\n                key={status}\n                initial={{ opacity: 0, scale: 0.25, filter: 'blur(2px)' }}\n                animate={{ opacity: 1, scale: 1, filter: 'blur(0px)' }}\n                exit={{ opacity: 0, scale: 0.25, filter: 'blur(2px)' }}\n                transition={{ type: 'spring', bounce: 0, duration: 0.3 }}\n              >\n                {status === 'error' ? (\n                  <TbAlertOctagonFilled\n                    size={26}\n                    className={cn('text-red-500 dark:text-red-500')}\n                  />\n                ) : (\n                  <LuCircleDotDashed\n                    size={26}\n                    strokeWidth={2.8}\n                    className={cn(\n                      'animate-spin text-neutral-700 dark:text-neutral-200',\n                    )}\n                  />\n                )}\n              </motion.div>\n            </AnimatePresence>\n\n            <AnimatedText\n              text={status === 'error' ? errorMessage : loadingMessage}\n              className={cn(\n                'text-xl font-semibold',\n                status === 'error'\n                  ? 'text-red-500'\n                  : 'text-neutral-700 dark:text-neutral-200',\n              )}\n            />\n          </motion.div>\n        </motion.div>\n\n        <AnimatePresence mode=\"popLayout\">\n          {status === 'error' && (\n            <motion.button\n              initial={{\n                opacity: 0,\n                x: -55,\n                filter: 'blur(4px)',\n                scale: 0.8,\n              }}\n              animate={{ opacity: 1, x: 0, filter: 'blur(0px)', scale: 1 }}\n              exit={{ opacity: 1, x: -55, filter: 'blur(4px)', scale: 0.8 }}\n              transition={{ type: 'spring', stiffness: 260, damping: 20 }}\n              whileHover={{ scale: 1.06 }}\n              whileTap={{ scale: 0.94 }}\n              onClick={handleRetry}\n              className={cn(\n                'z-10 flex h-14 w-14 items-center justify-center rounded-full bg-neutral-900 text-white dark:bg-neutral-100 dark:text-black',\n              )}\n            >\n              <FaArrowRotateRight size={22} />\n            </motion.button>\n          )}\n        </AnimatePresence>\n      </MotionConfig>\n    </div>\n  );\n};\n\nfunction AnimatedText({\n  text,\n  className,\n  delayStep = 0.014,\n}: {\n  text: string;\n  className?: string;\n  delayStep?: number;\n}) {\n  const chars = text.split('');\n\n  return (\n    <span style={{ display: 'inline-flex' }}>\n      <AnimatePresence mode=\"popLayout\" initial={false}>\n        <motion.span\n          layout\n          key={text}\n          style={{ display: 'inline-flex', willChange: 'transform' }}\n        >\n          {chars.map((char, i) => (\n            <motion.span\n              key={i}\n              initial={{ y: 10, opacity: 0, scale: 0.5, filter: 'blur(2px)' }}\n              animate={{ y: 0, opacity: 1, scale: 1, filter: 'blur(0px)' }}\n              exit={{ y: -10, opacity: 0, scale: 0.5, filter: 'blur(2px)' }}\n              transition={{\n                type: 'spring',\n                stiffness: 240,\n                damping: 16,\n                mass: 1.2,\n                delay: i * delayStep,\n              }}\n              style={{\n                display: 'inline-block',\n                whiteSpace: char === ' ' ? 'pre' : undefined,\n              }}\n              className={className}\n            >\n              {char}\n            </motion.span>\n          ))}\n        </motion.span>\n      </AnimatePresence>\n    </span>\n  );\n}\n"
    }
  ]
}
