{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "notch-nav",
  "title": "Notch Nav",
  "description": "A Notch style trigger that reveals the navigation menu from above.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/react/atlasui/notch-nav.tsx",
      "content": "\"use client\";\n\nimport {\n  type ReactNode,\n  createContext,\n  useContext,\n  useEffect,\n  useRef,\n  useState,\n} from \"react\";\n\nimport { AnimatePresence, type Variants, motion, stagger } from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\ninterface NotchNavContextValue {\n  open: boolean;\n  toggle: () => void;\n  contentRef: React.RefObject<HTMLDivElement | null>;\n  contentHeight: number;\n  offsetY: number;\n  setOffsetY: (y: number) => void;\n}\n\nconst NotchNavContext = createContext<NotchNavContextValue | null>(null);\n\nconst useNotchNav = () => {\n  const ctx = useContext(NotchNavContext);\n  if (!ctx) {\n    throw new Error(\"NotchNav components must be used within <NotchNav />\");\n  }\n  return ctx;\n};\n\nconst NotchNavContentContext = createContext<boolean | null>(null);\n\nconst useNotchNavContent = () => {\n  const ctx = useContext(NotchNavContentContext);\n  if (!ctx) {\n    throw new Error(\"<NotchNavItem /> must be used within <NotchNavContent />\");\n  }\n  return ctx;\n};\n\nconst NotchNav = ({ children }: { children: ReactNode }) => {\n  const [open, setOpen] = useState(false);\n  const toggle = () => setOpen((p) => !p);\n\n  const contentRef = useRef<HTMLDivElement>(null);\n  const [contentHeight, setContentHeight] = useState(0);\n\n  const [offsetY, setOffsetY] = useState(20);\n\n  useEffect(() => {\n    if (!open || !contentRef.current) return;\n\n    const { height } = contentRef.current.getBoundingClientRect();\n    setContentHeight((prev) => (prev !== height ? height : prev));\n  }, [open]);\n\n  return (\n    <NotchNavContext.Provider\n      value={{ open, toggle, contentRef, contentHeight, offsetY, setOffsetY }}\n    >\n      <div className=\"relative flex flex-col items-center\">{children}</div>\n    </NotchNavContext.Provider>\n  );\n};\n\ninterface PathProps {\n  d: string;\n  variants: Variants;\n  transition?: { duration: number };\n}\n\nconst Path = (props: PathProps) => (\n  <motion.path\n    fill=\"transparent\"\n    strokeWidth=\"1\"\n    stroke=\"#171717\"\n    strokeLinecap=\"round\"\n    {...props}\n  />\n);\n\nconst NotchNavTrigger = ({ className }: { className?: string }) => {\n  const { open, toggle, contentHeight, offsetY } = useNotchNav();\n\n  return (\n    <motion.button\n      type=\"button\"\n      aria-expanded={open}\n      onClick={toggle}\n      onKeyDown={(e) => {\n        if (e.key === \"Enter\" || e.key === \" \") {\n          e.preventDefault();\n          toggle();\n        }\n      }}\n      initial={{ y: 0 }}\n      animate={{ y: open ? contentHeight + offsetY : 0 }}\n      transition={{\n        type: \"spring\",\n        mass: 0.9,\n        damping: 20,\n        stiffness: 300,\n        delay: 0.2,\n      }}\n      className={cn(\n        \"absolute top-0 flex h-12 w-48 items-center justify-center rounded-b-4xl bg-[#b3eb14] text-neutral-900\",\n        \"before:absolute before:top-0 before:-left-[14px] before:h-[15.5px] before:w-[30px] before:bg-[radial-gradient(circle_at_0_100%,transparent_14px,#b3eb14_15px)] before:bg-size-[50%_100%] before:bg-no-repeat before:content-['']\",\n        \"after:absolute after:top-0 after:left-full after:h-[15px] after:w-[30px] after:bg-[radial-gradient(circle_at_100%_100%,transparent_15px,#b3eb14_15px)] after:bg-size-[50%_100%] after:bg-no-repeat after:content-['']\",\n        open && \"-top-px\",\n        className\n      )}\n    >\n      <motion.svg\n        animate={open ? \"open\" : \"closed\"}\n        width=\"23\"\n        height=\"23\"\n        viewBox=\"0 0 23 23\"\n      >\n        <Path\n          d=\"M 2 2.5 L 20 2.5\"\n          variants={{\n            closed: { d: \"M 2 2.5 L 20 2.5\" },\n            open: { d: \"M 3 16.5 L 17 2.5\" },\n          }}\n        />\n        <Path\n          d=\"M 2 9.423 L 20 9.423\"\n          variants={{\n            closed: { opacity: 1 },\n            open: { opacity: 0 },\n          }}\n          transition={{ duration: 0.1 }}\n        />\n        <Path\n          d=\"M 2 16.346 L 20 16.346\"\n          variants={{\n            closed: { d: \"M 2 16.346 L 20 16.346\" },\n            open: { d: \"M 3 2.5 L 17 16.346\" },\n          }}\n        />\n      </motion.svg>\n    </motion.button>\n  );\n};\n\ninterface NotchNavContentProps {\n  children: ReactNode;\n  offsetY?: number;\n  className?: string;\n}\n\nconst NotchNavContent = ({\n  children,\n  offsetY = 20,\n  className,\n}: NotchNavContentProps) => {\n  const { open, contentRef, setOffsetY } = useNotchNav();\n\n  useEffect(() => {\n    setOffsetY(offsetY);\n  }, [offsetY, setOffsetY]);\n\n  const contentVariants = {\n    closed: {\n      y: \"-100%\",\n      transition: {\n        delayChildren: stagger(0.05, { from: \"last\" }),\n        delay: 0.2,\n      },\n    },\n    open: {\n      y: offsetY,\n      transition: {\n        type: \"spring\",\n        mass: 0.9,\n        damping: 20,\n        stiffness: 300,\n        delay: 0.2,\n        delayChildren: stagger(0.1, { startDelay: 0.3 }),\n      } as const,\n    },\n  };\n\n  return (\n    <NotchNavContentContext.Provider value={true}>\n      <AnimatePresence>\n        <motion.div\n          ref={contentRef}\n          variants={contentVariants}\n          initial=\"closed\"\n          animate={open ? \"open\" : \"closed\"}\n          className={cn(\n            \"flex w-[90svw] max-w-96 flex-col gap-2 rounded-4xl bg-[#b3eb14] px-6 py-8\",\n            className\n          )}\n        >\n          {children}\n        </motion.div>\n      </AnimatePresence>\n    </NotchNavContentContext.Provider>\n  );\n};\n\ninterface NotchNavItemProps {\n  href: string;\n  children: ReactNode;\n  className?: string;\n}\n\nconst NotchNavItem = ({ href, children, className }: NotchNavItemProps) => {\n  useNotchNavContent();\n\n  const itemVariants = {\n    closed: { opacity: 0, y: 20 },\n    open: {\n      opacity: 1,\n      y: 0,\n      transition: { duration: 0.3 as number, ease: \"easeOut\" },\n    } as const,\n  };\n\n  return (\n    <motion.a\n      href={href}\n      variants={itemVariants}\n      className={cn(\n        \"group relative flex h-8 flex-col justify-center overflow-hidden border-b border-neutral-900/50 p-1 text-neutral-900 uppercase\",\n        className\n      )}\n    >\n      <span className=\"sr-only\">{children}</span>\n\n      <span\n        aria-hidden\n        className=\"absolute top-0 transition-all duration-300 ease-out group-hover:-top-full\"\n      >\n        {children}\n      </span>\n\n      <span\n        aria-hidden\n        className=\"absolute top-full font-medium italic transition-all duration-300 ease-out group-hover:top-0\"\n      >\n        {children}\n      </span>\n    </motion.a>\n  );\n};\n\nexport { NotchNav, NotchNavContent, NotchNavItem, NotchNavTrigger };\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}