{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "notch-nav-html",
  "title": "Notch Nav",
  "description": "A Notch style trigger that reveals the navigation menu from above built with HTML, CSS, JavaScript and Motion.",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "registry/html/atlasui/notch-nav/index.html",
      "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Notch Nav - Atlas UI</title>\n    <link rel=\"stylesheet\" href=\"style.css\" />\n  </head>\n  <body>\n    <div id=\"notch-nav\">\n      <button id=\"notch-nav-trigger\"></button>\n      <div id=\"notch-nav-content\">\n        <a href=\"#\" class=\"notch-nav-item\">Home</a>\n        <a href=\"#\" class=\"notch-nav-item\">About</a>\n        <a href=\"#\" class=\"notch-nav-item\">Services</a>\n        <a href=\"#\" class=\"notch-nav-item\">Portfolio</a>\n        <a href=\"#\" class=\"notch-nav-item\">Contact</a>\n      </div>\n    </div>\n  </body>\n\n  <script type=\"module\" src=\"script.js\"></script>\n</html>\n",
      "type": "registry:file",
      "target": "~/notch-nav/index.html"
    },
    {
      "path": "registry/html/atlasui/notch-nav/style.css",
      "content": ":root {\n  --background: light-dark(\n    oklch(100% 0.00011 271.152),\n    oklch(18.22% 0.00002 271.152)\n  );\n  --foreground: light-dark(\n    oklch(18.22% 0.00002 271.152),\n    oklch(98.511% 0.00011 271.152)\n  );\n}\n\nhtml {\n  color-scheme: light dark;\n}\n\n* {\n  margin: 0;\n  padding: 0;\n  box-sizing: border-box;\n}\n\nbody {\n  background-color: var(--background);\n}\n\n#notch-nav {\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n}\n\n#notch-nav-trigger {\n  all: unset;\n  position: absolute;\n  top: 0;\n\n  width: 12rem;\n  height: 3rem;\n\n  display: flex;\n  align-items: center;\n  justify-content: center;\n\n  background-color: #b3eb14;\n  color: #171717;\n\n  border-bottom-left-radius: 2rem;\n  border-bottom-right-radius: 2rem;\n}\n\n#notch-nav-trigger::before {\n  content: \"\";\n  position: absolute;\n  top: 0;\n  left: -14px;\n\n  width: 30px;\n  height: 15.5px;\n\n  background-repeat: no-repeat;\n  background-size: 50% 100%;\n  background-image: radial-gradient(\n    circle at 0 100%,\n    transparent 14px,\n    #b3eb14 15px\n  );\n}\n\n#notch-nav-trigger::after {\n  content: \"\";\n  position: absolute;\n  top: 0;\n  left: 100%;\n\n  width: 30px;\n  height: 15px;\n\n  background-repeat: no-repeat;\n  background-size: 50% 100%;\n  background-image: radial-gradient(\n    circle at 100% 100%,\n    transparent 15px,\n    #b3eb14 15px\n  );\n}\n\n#notch-nav-trigger svg {\n  width: 23px;\n  height: 23px;\n}\n\n#notch-nav-trigger .line {\n  stroke: #171717;\n  stroke-width: 1.5;\n  stroke-linecap: round;\n}\n\n#notch-nav-trigger:focus-visible {\n  outline: 2px solid #171717;\n  outline-offset: 4px;\n}\n\n#notch-nav-content {\n  position: absolute;\n  top: 0;\n\n  width: 90svw;\n  max-width: 24rem;\n  padding: 2rem 1.5rem;\n\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n\n  background-color: #b3eb14;\n  border-radius: 2rem;\n\n  transform: translateY(-100%);\n}\n\n.notch-nav-item {\n  position: relative;\n  height: 2rem;\n  padding: 0.25rem;\n\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n\n  overflow: hidden;\n\n  color: #171717;\n  text-decoration: none;\n  text-transform: uppercase;\n  font-size: 16px;\n\n  border-bottom: 1px solid #171717;\n\n  opacity: 0;\n  transform: translateY(20px);\n\n  font-family:\n    system-ui,\n    -apple-system,\n    BlinkMacSystemFont,\n    \"Segoe UI\",\n    Roboto,\n    Oxygen,\n    Ubuntu,\n    Cantarell,\n    \"Open Sans\",\n    \"Helvetica Neue\",\n    sans-serif;\n}\n\n.item-label {\n  position: absolute;\n  inset: 0;\n\n  display: flex;\n  align-items: center;\n\n  transition: transform 0.25s ease-out;\n}\n\n.item-label.secondary {\n  transform: translateY(100%);\n  font-style: italic;\n  font-weight: 500;\n}\n\n.notch-nav-item:hover .primary {\n  transform: translateY(-100%);\n}\n\n.notch-nav-item:hover .secondary {\n  transform: translateY(0);\n}\n",
      "type": "registry:file",
      "target": "~/notch-nav/style.css"
    },
    {
      "path": "registry/html/atlasui/notch-nav/script.js",
      "content": "import { animate, stagger } from \"motion\";\n\nlet open = false;\nconst DEFAULT_OFFSET_Y = 20;\n\nconst trigger = document.getElementById(\"notch-nav-trigger\");\nconst content = document.getElementById(\"notch-nav-content\");\nconst items = document.querySelectorAll(\".notch-nav-item\");\n\nconst getOffsetY = () => {\n  const attr = content.getAttribute(\"data-offset-y\");\n\n  if (attr === null || attr === \"\") {\n    return DEFAULT_OFFSET_Y;\n  }\n\n  const value = Number(attr);\n  return Number.isFinite(value) ? value : DEFAULT_OFFSET_Y;\n};\n\nconst offsetY = getOffsetY();\n\nif (!trigger.dataset.enhanced) {\n  trigger.innerHTML = `\n    <svg\n      width=\"23\"\n      height=\"23\"\n      viewBox=\"0 0 23 23\"\n      fill=\"none\"\n    >\n      <path class=\"line top\" />\n      <path class=\"line middle\" />\n      <path class=\"line bottom\" />\n    </svg>\n  `;\n  trigger.dataset.enhanced = \"true\";\n}\n\nconst paths = {\n  top: trigger.querySelector(\".top\"),\n  middle: trigger.querySelector(\".middle\"),\n  bottom: trigger.querySelector(\".bottom\"),\n};\n\nconst CLOSED = {\n  top: \"M 2 2.5 L 20 2.5\",\n  middle: \"M 2 9.423 L 20 9.423\",\n  bottom: \"M 2 16.346 L 20 16.346\",\n};\n\nconst OPEN = {\n  top: \"M 3 16.5 L 17 2.5\",\n  middle: \"\",\n  bottom: \"M 3 2.5 L 17 16.346\",\n};\n\npaths.top.setAttribute(\"d\", CLOSED.top);\npaths.middle.setAttribute(\"d\", CLOSED.middle);\npaths.bottom.setAttribute(\"d\", CLOSED.bottom);\n\nconst animateTriggerOpen = () => {\n  animate(\n    paths.top,\n    { d: OPEN.top },\n    { duration: 0.25, easing: \"ease-in-out\" },\n  );\n  animate(\n    paths.bottom,\n    { d: OPEN.bottom },\n    { duration: 0.25, easing: \"ease-in-out\" },\n  );\n  animate(paths.middle, { opacity: 0 }, { duration: 0.1 });\n};\n\nconst animateTriggerClose = () => {\n  animate(\n    paths.top,\n    { d: CLOSED.top },\n    { duration: 0.25, easing: \"ease-in-out\" },\n  );\n  animate(\n    paths.bottom,\n    { d: CLOSED.bottom },\n    { duration: 0.25, easing: \"ease-in-out\" },\n  );\n  animate(paths.middle, { opacity: 1 }, { duration: 0.1, delay: 0.15 });\n};\n\nconst getContentHeight = () => content.getBoundingClientRect().height;\n\nconst openNav = () => {\n  open = true;\n\n  const height = getContentHeight();\n\n  // Move trigger\n  animate(\n    trigger,\n    { y: height + offsetY },\n    {\n      type: \"spring\",\n      stiffness: 300,\n      damping: 20,\n      mass: 0.9,\n      delay: 0.2,\n    },\n  );\n\n  // Content slide in\n  animate(\n    content,\n    { y: offsetY },\n    {\n      type: \"spring\",\n      stiffness: 300,\n      damping: 20,\n      mass: 0.9,\n      delay: 0.2,\n    },\n  );\n\n  // Stagger items in\n  animate(\n    items,\n    { opacity: [0, 1], y: [20, 0] },\n    {\n      delay: stagger(0.1, { startDelay: 0.3 }),\n      duration: 0.3,\n      easing: \"ease-out\",\n    },\n  );\n};\n\nconst closeNav = () => {\n  open = false;\n\n  // Move trigger back\n  animate(\n    trigger,\n    { y: 0 },\n    {\n      type: \"spring\",\n      stiffness: 300,\n      damping: 20,\n      mass: 0.9,\n      delay: 0.2,\n    },\n  );\n\n  // Stagger items out (reverse)\n  animate(\n    items,\n    { opacity: [1, 0], y: [0, 20] },\n    {\n      delay: stagger(0.05, { from: \"last\" }),\n      duration: 0.2,\n      easing: \"ease-in\",\n    },\n  );\n\n  // Content slide out\n  animate(\n    content,\n    { y: \"-100%\" },\n    {\n      duration: 0.25,\n      easing: \"ease-in\",\n      delay: 0.2,\n    },\n  );\n};\n\ntrigger.addEventListener(\"click\", () => {\n  if (open) {\n    closeNav();\n    animateTriggerClose();\n  } else {\n    openNav();\n    animateTriggerOpen();\n  }\n});\n\nitems.forEach((item) => {\n  // Prevent double-init\n  if (item.dataset.enhanced) return;\n\n  const text = item.textContent.trim();\n  item.textContent = \"\";\n\n  const primary = document.createElement(\"span\");\n  primary.className = \"item-label primary\";\n  primary.textContent = text;\n\n  const secondary = document.createElement(\"span\");\n  secondary.className = \"item-label secondary\";\n  secondary.textContent = text;\n\n  item.append(primary, secondary);\n  item.dataset.enhanced = \"true\";\n});\n",
      "type": "registry:file",
      "target": "~/notch-nav/script.js"
    }
  ],
  "meta": {
    "framework": "html"
  },
  "type": "registry:file"
}