{
  "title": "Text Fall Button",
  "description": "A button with dynamic text that falls into place with a smooth, elastic motion on hover or click.",
  "name": "motion-text-fall-button",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [],
  "type": "registry:ui",
  "files": [
    {
      "path": "components/paceui/motion/text-fall-button.tsx",
      "type": "registry:ui",
      "content": "import { type ComponentProps, type MouseEvent, type ReactNode, useEffect } from \"react\";\n\nimport { stagger, useAnimate } from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype TextFallButtonProps = {\n    effectOnHover?: boolean;\n    effectOnLoad?: boolean;\n} & ComponentProps<\"button\">;\n\nconst getText = (node: ReactNode): string => {\n    if (typeof node === \"string\" || typeof node === \"number\") {\n        return String(node);\n    }\n    if (Array.isArray(node)) {\n        return node.map(getText).join(\"\");\n    }\n    return \"\";\n};\n\nexport const TextFallButton = ({\n    className,\n    children,\n    effectOnHover = true,\n    effectOnLoad = true,\n    ...props\n}: TextFallButtonProps) => {\n    const [scope, animate] = useAnimate<HTMLButtonElement>();\n\n    const triggerTextFallEffect = () => {\n        if (!scope.current) return;\n\n        animate(scope.current, { scale: [1, 0.95, 1], y: [0, 4, 0] }, { duration: 0.3, times: [0, 0.33, 1] });\n\n        animate(\n            \".char\",\n            { y: [-60, 0] },\n            {\n                duration: 1,\n                delay: stagger(0.05),\n                type: \"spring\",\n                bounce: 0.5,\n            },\n        );\n    };\n\n    useEffect(() => {\n        if (effectOnLoad) {\n            triggerTextFallEffect();\n        }\n    }, [effectOnLoad]);\n\n    const onClick = (e: MouseEvent<HTMLButtonElement>) => {\n        triggerTextFallEffect();\n        props.onClick?.(e);\n    };\n\n    const textString = getText(children);\n\n    return (\n        <button\n            {...props}\n            ref={scope}\n            onMouseEnter={(e) => {\n                if (effectOnHover) triggerTextFallEffect();\n                props.onMouseEnter?.(e);\n            }}\n            onClick={onClick}\n            className={cn(\"relative overflow-hidden\", className)}>\n            <span className=\"absolute inset-0 flex items-center justify-center\">\n                {textString.split(\"\").map((char, index) => (\n                    <span key={index} className=\"char inline-block\" style={{ whiteSpace: \"pre\" }}>\n                        {char}\n                    </span>\n                ))}\n            </span>\n            <span className=\"opacity-0\">{children}</span>\n        </button>\n    );\n};\n"
    }
  ],
  "mcp": {
    "description": "Provides refined UI interactions and accessible controls. A button with dynamic text that falls into place with a smooth, elastic motion on hover or click. Configurable props include: {; effectOnHover?: boolean;; effectOnLoad?: boolean;. Relies on motion. Optimal for building reusable interface elements and user input flows.",
    "tags": [
      "component",
      "motion",
      "animation"
    ]
  }
}