{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "focus-frame-button",
  "type": "registry:ui",
  "title": "Focus Frame Button",
  "description": "A framed button that locks on like a viewfinder on hover: the hairline folds into its corners, the brackets snap shut while the label rolls up and a fresh return arrow slides in.",
  "dependencies": [],
  "registryDependencies": [],
  "cssVars": {
    "theme": {}
  },
  "files": [
    {
      "path": "components/tweenui/focus-frame-button.tsx",
      "type": "registry:component",
      "target": "components/tweenui/focus-frame-button.tsx",
      "content": "import type { ComponentPropsWithRef } from 'react';\nimport { cn } from '@/lib/utils';\n\nexport interface FocusFrameButtonProps extends ComponentPropsWithRef<'button'> {\n  children: string;\n}\n\nconst roll =\n  'block transition-transform duration-600 ease-(--expo) group-hover:-translate-y-full group-focus-visible:-translate-y-full motion-reduce:transition-none';\n\nconst RollLabel = ({ children }: { children: string }) => {\n  return (\n    <span className=\"relative block h-5 overflow-hidden leading-5\">\n      <span className={roll}>{children}</span>\n      <span aria-hidden=\"true\" className={roll}>\n        {children}\n      </span>\n    </span>\n  );\n};\n\nconst ReturnArrow = ({ className }: { className?: string }) => {\n  return (\n    <svg\n      viewBox=\"0 0 20 20\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth={1.6}\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n      className={cn('size-4 flex-none', className)}\n    >\n      <path d=\"M3 3.5v4.57a4 4 0 0 0 4 4h10m-4.43-4.43L17 12.07l-4.43 4.43\" />\n    </svg>\n  );\n};\n\nconst slide =\n  '-translate-x-full transition-transform duration-600 ease-(--expo) group-hover:translate-x-0 group-focus-visible:translate-x-0 motion-reduce:transition-none';\n\nconst rail =\n  'pointer-events-none absolute bg-[#045f64]/35 transition-transform delay-200 duration-500 ease-(--expo) group-hover:delay-0 group-focus-visible:delay-0 motion-reduce:transition-none dark:bg-[#c6f56f]/35';\n\nconst rails = [\n  'top-0 left-0 h-px w-1/2 origin-left group-hover:scale-x-0 group-focus-visible:scale-x-0',\n  'top-0 right-0 h-px w-1/2 origin-right group-hover:scale-x-0 group-focus-visible:scale-x-0',\n  'bottom-0 left-0 h-px w-1/2 origin-left group-hover:scale-x-0 group-focus-visible:scale-x-0',\n  'right-0 bottom-0 h-px w-1/2 origin-right group-hover:scale-x-0 group-focus-visible:scale-x-0',\n  'top-0 left-0 h-1/2 w-px origin-top group-hover:scale-y-0 group-focus-visible:scale-y-0',\n  'bottom-0 left-0 h-1/2 w-px origin-bottom group-hover:scale-y-0 group-focus-visible:scale-y-0',\n  'top-0 right-0 h-1/2 w-px origin-top group-hover:scale-y-0 group-focus-visible:scale-y-0',\n  'right-0 bottom-0 h-1/2 w-px origin-bottom group-hover:scale-y-0 group-focus-visible:scale-y-0',\n];\n\nconst corner =\n  'pointer-events-none absolute size-2.5 border-[#045f64] transition-transform duration-500 ease-(--expo) group-hover:delay-200 group-hover:duration-700 group-hover:ease-(--snap) group-focus-visible:delay-200 group-focus-visible:duration-700 group-focus-visible:ease-(--snap) motion-reduce:transition-none dark:border-[#c6f56f]';\n\nconst corners = [\n  'top-0 left-0 border-t-[1.5px] border-l-[1.5px] group-hover:translate-1 group-focus-visible:translate-1',\n  'top-0 right-0 border-t-[1.5px] border-r-[1.5px] group-hover:-translate-x-1 group-hover:translate-y-1 group-focus-visible:-translate-x-1 group-focus-visible:translate-y-1',\n  'bottom-0 left-0 border-b-[1.5px] border-l-[1.5px] group-hover:translate-x-1 group-hover:-translate-y-1 group-focus-visible:translate-x-1 group-focus-visible:-translate-y-1',\n  'right-0 bottom-0 border-r-[1.5px] border-b-[1.5px] group-hover:-translate-1 group-focus-visible:-translate-1',\n];\n\nconst FocusFrameButton = ({\n  children,\n  className,\n  type = 'button',\n  ...props\n}: FocusFrameButtonProps) => {\n  return (\n    <button\n      type={type}\n      className={cn(\n        'group relative inline-flex cursor-pointer p-1 text-sm font-medium tracking-wide whitespace-nowrap text-[#045f64] uppercase select-none [--expo:cubic-bezier(0.16,1,0.3,1)] [--snap:cubic-bezier(0.34,1.56,0.64,1)] focus-visible:outline-none disabled:pointer-events-none disabled:opacity-60',\n        className\n      )}\n      {...props}\n    >\n      {rails.map((placement) => (\n        <span key={placement} aria-hidden=\"true\" className={cn(rail, placement)} />\n      ))}\n      {corners.map((placement) => (\n        <span key={placement} aria-hidden=\"true\" className={cn(corner, placement)} />\n      ))}\n      <span className=\"relative flex h-11 items-center gap-2.5 overflow-hidden rounded-[2px] bg-[#c6f56f] px-5 transition-[scale] duration-200 ease-out group-active:scale-[0.97] motion-reduce:transition-none\">\n        <RollLabel>{children}</RollLabel>\n        <span aria-hidden=\"true\" className=\"relative flex size-4 overflow-hidden\">\n          <ReturnArrow className={slide} />\n          <ReturnArrow className={slide} />\n        </span>\n      </span>\n    </button>\n  );\n};\n\nexport default FocusFrameButton;\n"
    }
  ],
  "docs": "Docs, props and examples: https://tween-ui.vercel.app/component/focus-frame-button"
}