{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "unlimited-nested-menu",
  "type": "registry:component",
  "title": "Unlimited Nested Menu",
  "description": "A dropdown where each branch morphs into a stacked sub-panel, no depth limit, fully keyboard driven.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://lab.moumen.dev/r/lab-theme.json"
  ],
  "files": [
    {
      "path": "registry/lab/unlimited-nested-menu/unlimited-nested-menu.tsx",
      "type": "registry:component",
      "target": "@components/lab/unlimited-nested-menu.tsx",
      "content": "\"use client\";\n\nimport {\n  useCallback,\n  useEffect,\n  useId,\n  useLayoutEffect,\n  useRef,\n  useState,\n  type CSSProperties,\n  type KeyboardEvent,\n  type ReactNode,\n} from \"react\";\nimport {\n  AnimatePresence,\n  MotionConfig,\n  animate,\n  motion,\n  useIsPresent,\n  useReducedMotion,\n} from \"motion/react\";\n\n// Unlimited nested menu - iOS-style stacked drill-down.\n//\n// The main dropdown never changes. Click a branch item and its children open as\n// a NEW panel anchored right under that item, laid OVER the menu below it - the\n// clicked item's name becomes the new panel's title (its header sits exactly\n// where the item was, so the row appears to turn into the title). Do it again\n// and the grandchildren stack the same way. There is no depth limit; parents\n// stay visible and dimmed behind, and clicking one pops back to it.\n//\n// Motion (motion/react):\n//   - Opening the MENU: the root panel reveals from the trigger, scale + fade.\n//   - Drilling a branch: a shared-element morph - the child panel mounts clipped\n//     to just its header, which sits EXACTLY where the clicked row is and keeps\n//     the row's own icon, then opens - the clip expands downward while the\n//     title's weight crossfades plain -> bold (a measured, imperative animate()\n//     sequence, since the morph targets depend on the clicked row's geometry).\n//   - Any close (pop a level, or close the whole menu): AnimatePresence fades\n//     the leaving panel (or the whole stack) in place - shorter than the enter,\n//     no drift - with none of the exit-snapshot bookkeeping.\n//\n// Positioning is JS-measured against the popup origin, with a viewport-edge\n// correction (--nm-shift-x) so a full-width panel near the screen edge slides to\n// stay on-screen. Requires the lab-theme tokens. Fully Tailwind, no CSS files.\n\nconst EASE = [0.22, 1, 0.36, 1] as const;\nconst POP_S = 0.22; // per-panel enter\nconst EXIT_S = 0.15; // exits are quicker + quieter than the enter\n\n// Panel shadows: the front panel owns the stack's elevation; panels behind it\n// collapse to a crisp hairline so shadows don't compound with depth.\nconst SHADOW_ELEV =\n  \"shadow-[0_0_0_1px_rgba(0,0,0,0.07),0_14px_34px_-10px_rgba(0,0,0,0.26),0_5px_14px_-6px_rgba(0,0,0,0.12)]\";\nconst SHADOW_BEHIND = \"shadow-[0_0_0_1px_rgba(0,0,0,0.05),0_1px_2px_-1px_rgba(0,0,0,0.08)]\";\n\nexport interface NestedMenuItem {\n  id?: string;\n  label: string;\n  icon?: ReactNode;\n  hint?: string;\n  danger?: boolean;\n  disabled?: boolean;\n  items?: NestedMenuItem[];\n}\n\nexport interface NestedMenuState {\n  open: boolean;\n  depth: number;\n  title: string;\n  path: string[];\n  count: number;\n  lastPick: string | null;\n}\n\ninterface Frame {\n  node: NestedMenuItem | null;\n  fromIndex: number | null;\n  anchor: { top: number; left: number };\n  morph?: { labelX: number; labelCY: number } | null;\n}\n\nexport default function NestedMenu({\n  items,\n  rootTitle = \"Actions\",\n  triggerLabel = \"Open menu\",\n  dim = true,\n  animate: animateProp = true,\n  align = \"start\",\n  open: controlledOpen,\n  defaultOpen = false,\n  onOpenChange,\n  onSelect,\n  onStateChange,\n  inspect = false,\n  className = \"\",\n}: {\n  items: NestedMenuItem[];\n  rootTitle?: string;\n  triggerLabel?: string;\n  dim?: boolean;\n  animate?: boolean;\n  align?: \"start\" | \"end\";\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  onSelect?: (item: NestedMenuItem, path: string[]) => void;\n  onStateChange?: (state: NestedMenuState) => void;\n  inspect?: boolean;\n  className?: string;\n}) {\n  const [openU, setOpenU] = useState(defaultOpen);\n  const open = controlledOpen ?? openU;\n  const setOpen = useCallback(\n    (value: boolean) => {\n      if (controlledOpen === undefined) setOpenU(value);\n      onOpenChange?.(value);\n    },\n    [controlledOpen, onOpenChange],\n  );\n\n  const [frames, setFrames] = useState<Frame[]>([{ node: null, fromIndex: null, anchor: { top: 0, left: 0 } }]);\n  const [activeIndex, setActiveIndex] = useState(0);\n  const [lastPick, setLastPick] = useState<string | null>(null);\n\n  const top = frames[frames.length - 1];\n  const topItems = top.node ? top.node.items ?? [] : items;\n  const depth = frames.length - 1;\n  const path = frames.slice(1).map((f) => f.node!.label);\n\n  const rootRef = useRef<HTMLDivElement>(null);\n  const triggerRef = useRef<HTMLButtonElement>(null);\n  const stackRef = useRef<HTMLDivElement>(null);\n  const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n  const pendingFocus = useRef<number | null>(null);\n  const inspectDrilled = useRef(false);\n  itemRefs.current = [];\n\n  const popupId = useId();\n\n  const resetToRoot = useCallback(() => {\n    setFrames([{ node: null, fromIndex: null, anchor: { top: 0, left: 0 } }]);\n    setActiveIndex(0);\n  }, []);\n\n  const openMenu = useCallback(() => {\n    resetToRoot();\n    pendingFocus.current = 0;\n    setOpen(true);\n  }, [resetToRoot, setOpen]);\n\n  // Close is logical-immediate (open -> false, focus returns now); Animate-\n  // Presence keeps the popup mounted a beat so the whole stack fades out.\n  const closeMenu = useCallback(\n    (returnFocus: boolean) => {\n      setOpen(false);\n      if (returnFocus) requestAnimationFrame(() => triggerRef.current?.focus());\n    },\n    [setOpen],\n  );\n\n  // Open a branch: measure the clicked item so the child lands right under it,\n  // and where its label sits so the child's title can morph out of the row.\n  const drill = useCallback((item: NestedMenuItem, index: number, el?: HTMLElement | null) => {\n    if (!item.items?.length) return;\n    const origin = stackRef.current;\n    const node = el ?? itemRefs.current[index];\n    let anchor = { top: 0, left: 0 };\n    let morph: { labelX: number; labelCY: number } | null = null;\n    if (origin && node) {\n      const o = origin.getBoundingClientRect();\n      const r = node.getBoundingClientRect();\n      // Left: the PARENT panel's left so the stack is a clean vertical staircase.\n      const panelEl = node.closest(\"[data-nm-panel]\");\n      const left = panelEl ? panelEl.getBoundingClientRect().left - o.left : 0;\n      anchor = { top: r.top - o.top, left };\n      const labelEl = (node.querySelector(\"[data-nm-label]\") ?? node) as HTMLElement;\n      const lr = labelEl.getBoundingClientRect();\n      morph = {\n        labelX: lr.left - (o.left + anchor.left),\n        labelCY: lr.top + lr.height / 2 - (o.top + anchor.top),\n      };\n    }\n    setFrames((f) => [...f, { node: item, fromIndex: index, anchor, morph }]);\n    setActiveIndex(0);\n    pendingFocus.current = 0;\n  }, []);\n\n  // Pop back to a given depth (default: one level). AnimatePresence fades the\n  // removed panel out on its own - no exit snapshot to manage.\n  const popTo = useCallback(\n    (target = depth - 1) => {\n      if (target < 0 || target >= depth) return;\n      const removed = frames[frames.length - 1];\n      setFrames((f) => f.slice(0, target + 1));\n      const restore = target === depth - 1 ? removed.fromIndex ?? 0 : 0;\n      setActiveIndex(restore);\n      pendingFocus.current = restore;\n    },\n    [depth, frames],\n  );\n\n  const select = useCallback(\n    (item: NestedMenuItem) => {\n      if (item.disabled) return;\n      setLastPick(item.label);\n      onSelect?.(item, path);\n      closeMenu(true);\n    },\n    [closeMenu, onSelect, path],\n  );\n\n  const focusIndex = useCallback((index: number) => {\n    setActiveIndex(index);\n    itemRefs.current[index]?.focus();\n  }, []);\n\n  const nextEnabled = useCallback(\n    (from: number, delta: number) => {\n      const n = topItems.length;\n      for (let step = 1; step <= n; step += 1) {\n        const i = (from + delta * step + n * step) % n;\n        if (!topItems[i]?.disabled) return i;\n      }\n      return from;\n    },\n    [topItems],\n  );\n\n  useLayoutEffect(() => {\n    if (!open) return;\n    if (pendingFocus.current != null) {\n      const i = pendingFocus.current;\n      pendingFocus.current = null;\n      requestAnimationFrame(() => itemRefs.current[i]?.focus());\n    }\n  }, [open, frames.length]);\n\n  useEffect(() => {\n    if (!inspect) {\n      inspectDrilled.current = false;\n      return;\n    }\n    openMenu();\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [inspect]);\n  useEffect(() => {\n    if (!inspect || !open || depth > 0 || inspectDrilled.current) return;\n    inspectDrilled.current = true;\n    const id = window.setTimeout(() => {\n      const first = topItems[0];\n      if (first?.items?.length) drill(first, 0, itemRefs.current[0]);\n    }, 60);\n    return () => clearTimeout(id);\n  }, [inspect, open, depth, topItems, drill]);\n\n  useEffect(() => {\n    if (!open) return undefined;\n    const onDown = (e: PointerEvent) => {\n      if (!rootRef.current?.contains(e.target as Node)) closeMenu(false);\n    };\n    document.addEventListener(\"pointerdown\", onDown);\n    return () => document.removeEventListener(\"pointerdown\", onDown);\n  }, [open, closeMenu]);\n\n  // Keep the whole stack inside the viewport horizontally: shift the ORIGIN (not\n  // each panel) so the staircase slides together and the drill math stays intact.\n  useLayoutEffect(() => {\n    if (!open) return undefined;\n    const el = stackRef.current;\n    if (!el) return undefined;\n    const GUTTER = 8;\n    let raf = 0;\n    const place = () => {\n      raf = 0;\n      el.style.setProperty(\"--nm-shift-x\", \"0px\");\n      const rect = el.getBoundingClientRect();\n      const vw = document.documentElement.clientWidth;\n      let shift = 0;\n      const overRight = rect.right - (vw - GUTTER);\n      if (overRight > 0) shift = -overRight;\n      if (rect.left + shift < GUTTER) shift = GUTTER - rect.left;\n      el.style.setProperty(\"--nm-shift-x\", `${Math.round(shift)}px`);\n    };\n    const schedule = () => {\n      if (!raf) raf = requestAnimationFrame(place);\n    };\n    place();\n    window.addEventListener(\"resize\", schedule);\n    window.addEventListener(\"scroll\", schedule, true);\n    return () => {\n      if (raf) cancelAnimationFrame(raf);\n      window.removeEventListener(\"resize\", schedule);\n      window.removeEventListener(\"scroll\", schedule, true);\n    };\n  }, [open]);\n\n  useEffect(() => {\n    onStateChange?.({\n      open,\n      depth,\n      title: top.node ? top.node.label : rootTitle,\n      path,\n      count: topItems.length,\n      lastPick,\n    });\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [open, depth, topItems, lastPick]);\n\n  function onKeyDown(e: KeyboardEvent<HTMLDivElement>) {\n    const item = topItems[activeIndex];\n    switch (e.key) {\n      case \"ArrowDown\":\n        e.preventDefault();\n        focusIndex(nextEnabled(activeIndex, 1));\n        break;\n      case \"ArrowUp\":\n        e.preventDefault();\n        focusIndex(nextEnabled(activeIndex, -1));\n        break;\n      case \"Home\":\n        e.preventDefault();\n        focusIndex(nextEnabled(-1, 1));\n        break;\n      case \"End\":\n        e.preventDefault();\n        focusIndex(nextEnabled(0, -1));\n        break;\n      case \"ArrowRight\":\n        if (item?.items?.length) {\n          e.preventDefault();\n          drill(item, activeIndex, itemRefs.current[activeIndex]);\n        }\n        break;\n      case \"Enter\":\n      case \" \":\n        e.preventDefault();\n        if (item?.items?.length) drill(item, activeIndex, itemRefs.current[activeIndex]);\n        else if (item) select(item);\n        break;\n      case \"ArrowLeft\":\n      case \"Backspace\":\n        if (depth > 0) {\n          e.preventDefault();\n          popTo(depth - 1);\n        }\n        break;\n      case \"Escape\":\n        e.preventDefault();\n        if (depth > 0) popTo(depth - 1);\n        else closeMenu(true);\n        break;\n      case \"Tab\":\n        closeMenu(false);\n        break;\n      default:\n        break;\n    }\n  }\n\n  return (\n    <MotionConfig reducedMotion=\"user\">\n      <div\n        ref={rootRef}\n        className={`group/nm relative inline-block ${className}`}\n        data-open={open ? \"true\" : \"false\"}\n      >\n        <button\n          ref={triggerRef}\n          type=\"button\"\n          className=\"inline-flex items-center gap-2 rounded-[0.625rem] bg-card px-3 py-2 text-sm font-medium text-foreground shadow-border [transition:box-shadow_250ms_var(--ease-smooth-out)] hover:shadow-border-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring [&>svg]:text-muted-foreground\"\n          aria-haspopup=\"menu\"\n          aria-expanded={open}\n          aria-controls={popupId}\n          onClick={() => (open ? closeMenu(true) : openMenu())}\n        >\n          <MenuIcon />\n          <span>{triggerLabel}</span>\n          <motion.span\n            className=\"inline-flex text-muted-foreground/70\"\n            animate={{ rotate: open ? 180 : 0 }}\n            transition={{ duration: 0.25, ease: EASE }}\n          >\n            <ChevronDownIcon />\n          </motion.span>\n        </button>\n\n        <AnimatePresence>\n          {open && (\n            <motion.div\n              key=\"popup\"\n              id={popupId}\n              ref={stackRef}\n              initial={false}\n              exit={{ opacity: 0, pointerEvents: \"none\" }}\n              transition={{ duration: animateProp ? EXIT_S : 0, ease: EASE }}\n              className={`absolute top-[calc(100%+0.375rem)] z-40 w-[17rem] [transform:translateX(var(--nm-shift-x,0px))] ${\n                align === \"end\" ? \"right-0\" : \"left-0\"\n              }`}\n              data-align={align}\n            >\n              <AnimatePresence>\n                {frames.map((frame, d) => {\n                  const isTop = d === frames.length - 1;\n                  const title = frame.node ? frame.node.label : rootTitle;\n                  const panelItems = frame.node ? frame.node.items ?? [] : items;\n                  return (\n                    <Panel\n                      key={frame.node?.id ?? frame.node?.label ?? \"root\"}\n                      depth={d}\n                      title={title}\n                      items={panelItems}\n                      anchor={frame.anchor}\n                      morphFrom={frame.morph}\n                      nodeIcon={frame.node?.icon}\n                      isTop={isTop}\n                      dim={dim}\n                      animate={animateProp}\n                      activeIndex={isTop ? activeIndex : -1}\n                      itemRefs={isTop ? itemRefs : null}\n                      onItemEnter={isTop ? (i) => { if (!panelItems[i].disabled) setActiveIndex(i); } : undefined}\n                      onItemActivate={\n                        isTop\n                          ? (item, i, el) =>\n                              item.disabled ? undefined : item.items?.length ? drill(item, i, el) : select(item)\n                          : undefined\n                      }\n                      onBehindClick={!isTop ? () => popTo(d) : undefined}\n                      onBack={isTop && d > 0 ? () => popTo(d - 1) : undefined}\n                      onKeyDown={isTop ? onKeyDown : undefined}\n                      inspect={inspect}\n                    />\n                  );\n                })}\n              </AnimatePresence>\n            </motion.div>\n          )}\n        </AnimatePresence>\n      </div>\n    </MotionConfig>\n  );\n}\n\nfunction Panel({\n  depth,\n  title,\n  items,\n  anchor,\n  morphFrom,\n  nodeIcon,\n  isTop,\n  dim,\n  animate: animateProp,\n  activeIndex,\n  itemRefs,\n  onItemEnter,\n  onItemActivate,\n  onBack,\n  onBehindClick,\n  onKeyDown,\n  inspect,\n}: {\n  depth: number;\n  title: string;\n  items: NestedMenuItem[];\n  anchor: { top: number; left: number };\n  morphFrom?: { labelX: number; labelCY: number } | null;\n  nodeIcon?: ReactNode;\n  isTop: boolean;\n  dim: boolean;\n  animate: boolean;\n  activeIndex: number;\n  itemRefs: React.MutableRefObject<(HTMLButtonElement | null)[]> | null;\n  onItemEnter?: (index: number) => void;\n  onItemActivate?: (item: NestedMenuItem, index: number, el: HTMLElement) => void;\n  onBack?: () => void;\n  onBehindClick?: () => void;\n  onKeyDown?: (e: KeyboardEvent<HTMLDivElement>) => void;\n  inspect?: boolean;\n}) {\n  const panelRef = useRef<HTMLDivElement>(null);\n  const reduced = useReducedMotion();\n  // False while AnimatePresence fades this panel out after a pop - it is a\n  // frozen snapshot then: no pointer events, hidden from the tree.\n  const present = useIsPresent();\n\n  // The shared-element morph. The targets depend on the clicked row's measured\n  // geometry, so this is an imperative motion animate() pass, run once before\n  // first paint: the panel opens out of the row (clip expands downward), the\n  // title glides from the row label's seat while its weight crossfades\n  // plain -> bold, and the list + divider fade in under it.\n  useLayoutEffect(() => {\n    const el = panelRef.current;\n    if (!el || !animateProp || !morphFrom || reduced) return;\n    const titleEl = el.querySelector<HTMLElement>(\"[data-nm-title]\");\n    const headEl = el.querySelector<HTMLElement>(\"[data-nm-header]\");\n    const plainEl = el.querySelector<HTMLElement>(\"[data-nm-title-plain]\");\n    const boldEl = el.querySelector<HTMLElement>(\"[data-nm-title-bold]\");\n    const listEl = el.querySelector<HTMLElement>(\"[data-nm-list]\");\n    if (!titleEl || !headEl) return;\n    const p = el.getBoundingClientRect();\n    const t = titleEl.getBoundingClientRect();\n    const dx = morphFrom.labelX - (t.left - p.left);\n    const dy = morphFrom.labelCY - (t.top + t.height / 2 - p.top);\n    const clip = Math.max(0, p.height - headEl.getBoundingClientRect().height);\n    const opts = { duration: POP_S, ease: EASE } as const;\n    // -48px (not 0): a clip-path clips the element's OWN box-shadow, and\n    // inset(0) sits exactly on the border box - it would slice the ring off.\n    animate(\n      el,\n      { clipPath: [`inset(0px 0px ${clip}px 0px round 12px)`, \"inset(-48px -48px -48px -48px round 12px)\"] },\n      opts,\n    );\n    animate(titleEl, { x: [dx, 0], y: [dy, 0] }, opts);\n    if (plainEl) animate(plainEl, { opacity: [1, 0] }, opts);\n    if (boldEl) animate(boldEl, { opacity: [0, 1] }, opts);\n    if (listEl) animate(listEl, { opacity: [0, 1] }, opts);\n    animate(headEl, { borderBottomColor: [\"rgba(0,0,0,0)\", \"rgba(0,0,0,0.06)\"] }, opts);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  const shadowClass = inspect\n    ? isTop\n      ? \"shadow-none outline outline-[1.5px] outline-dashed outline-[#ef4444]\"\n      : \"shadow-none outline outline-[1.5px] outline-dashed outline-[#3b82f6]\"\n    : isTop\n      ? SHADOW_ELEV\n      : `${SHADOW_BEHIND} cursor-pointer`;\n\n  const positionStyle: CSSProperties =\n    depth === 0\n      ? { position: \"relative\", zIndex: 10 }\n      : { top: `${anchor.top}px`, left: `${anchor.left}px`, zIndex: 10 + depth };\n\n  // Enter treatment: the root reveals from the trigger; a measured sub-panel\n  // morphs (imperative, above); an unmeasured sub-panel pops in as a fallback.\n  const enterProps = !animateProp\n    ? { initial: false as const }\n    : morphFrom\n      ? { initial: false as const }\n      : depth === 0\n        ? {\n            initial: { opacity: 0, scale: 0.96, y: -4 },\n            animate: { opacity: 1, scale: 1, y: 0 },\n          }\n        : {\n            initial: { opacity: 0, scale: 0.95, y: -6 },\n            animate: { opacity: 1, scale: 1, y: 0 },\n          };\n\n  return (\n    <motion.div\n      ref={panelRef}\n      data-nm-panel\n      {...enterProps}\n      exit={{ opacity: 0 }}\n      transition={{ duration: animateProp ? POP_S : 0, ease: EASE, opacity: { duration: animateProp ? EXIT_S : 0, ease: EASE } }}\n      className={[\n        \"absolute w-[17rem] origin-top rounded-xl bg-popover\",\n        \"[transition:box-shadow_220ms_var(--ease-smooth-out)]\",\n        shadowClass,\n      ].join(\" \")}\n      data-active={isTop ? \"true\" : \"false\"}\n      style={{ ...positionStyle, pointerEvents: present ? undefined : \"none\" }}\n      onClick={onBehindClick}\n      aria-hidden={present && isTop ? undefined : \"true\"}\n    >\n      {/* Opaque panel + veil scrim so stacked layers dim without bleeding\n          through (panel opacity would reveal every layer behind). */}\n      {!isTop && present && (\n        <motion.span\n          className=\"absolute inset-0 z-[5] rounded-[inherit] bg-popover pointer-events-none\"\n          initial={{ opacity: 0 }}\n          animate={{ opacity: dim ? 0.62 : 0 }}\n          transition={{ duration: animateProp ? POP_S : 0, ease: EASE }}\n          aria-hidden=\"true\"\n        />\n      )}\n\n      {/* Sub headers mirror an item row's geometry exactly AND keep the item's\n          own icon, so the morph's start frame IS the clicked row - the only\n          thing that changes as it becomes the title is the label's weight.\n          The icon doubles as the back button. */}\n      <div\n        data-nm-header\n        className={[\n          \"flex items-center border-b border-foreground/[0.06]\",\n          depth > 0 ? \"min-h-9 gap-2.5 px-[0.875rem]\" : \"min-h-10 gap-1.5 py-1 pr-2 pl-[0.875rem]\",\n          inspect && depth > 0 ? \"outline outline-[1.5px] outline-dashed outline-[#f59e0b] -outline-offset-[1.5px]\" : \"\",\n        ].join(\" \")}\n      >\n        {depth > 0 &&\n          (onBack ? (\n            <button\n              type=\"button\"\n              className=\"relative inline-flex h-4 w-4 flex-none cursor-pointer items-center justify-center text-muted-foreground hover:text-foreground before:absolute before:-inset-1.5 before:rounded-lg before:content-[''] before:[transition:background-color_250ms_var(--ease-smooth-out)] hover:before:bg-accent [&>svg]:relative\"\n              tabIndex={-1}\n              onMouseDown={(e) => e.preventDefault()}\n              onClick={(e) => {\n                e.stopPropagation();\n                onBack();\n              }}\n              aria-label=\"Back\"\n            >\n              {nodeIcon ?? <ChevronLeftIcon />}\n            </button>\n          ) : (\n            <span\n              className=\"relative inline-flex h-4 w-4 flex-none items-center justify-center text-muted-foreground [&>svg]:relative\"\n              aria-hidden=\"true\"\n            >\n              {nodeIcon ?? <ChevronLeftIcon />}\n            </span>\n          ))}\n        <span\n          data-nm-title\n          className=\"relative min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap text-sm text-foreground\"\n        >\n          {/* Two stacked copies: the bold one is the real header text, the plain\n              one matches the row label. The morph crossfades them - smoother\n              than animating font-weight, which steps without a variable font. */}\n          <span data-nm-title-plain className=\"absolute inset-0 font-normal opacity-0 pointer-events-none\" aria-hidden=\"true\">\n            {title}\n          </span>\n          <span data-nm-title-bold className=\"font-semibold tracking-[-0.006em]\">\n            {title}\n          </span>\n        </span>\n      </div>\n\n      <div\n        data-nm-list\n        className=\"flex max-h-[18rem] flex-col gap-px overflow-y-auto overscroll-contain p-1.5\"\n        role={isTop && present ? \"menu\" : undefined}\n        aria-label={isTop && present ? title : undefined}\n        onKeyDown={onKeyDown}\n      >\n        {items.map((item, index) => {\n          const branch = (item.items?.length ?? 0) > 0;\n          const active = isTop && present && index === activeIndex;\n          const rowClass = [\n            \"group/item flex w-full min-h-9 items-center gap-2.5 rounded-lg px-2 text-left text-sm text-foreground [transition:background-color_250ms_var(--ease-smooth-out)]\",\n            \"hover:bg-accent focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring\",\n            \"aria-disabled:text-muted-foreground/70 aria-disabled:cursor-default aria-disabled:hover:bg-transparent\",\n            \"data-[danger=true]:text-destructive data-[danger=true]:hover:bg-destructive/10 data-[danger=true]:data-[highlighted=true]:bg-destructive/10\",\n            active ? \"bg-accent\" : \"\",\n            \"[@media(pointer:coarse)]:min-h-11\",\n          ].join(\" \");\n          const inner = (\n            <>\n              {item.icon && (\n                <span className=\"inline-flex flex-none text-muted-foreground group-data-[danger=true]/item:text-destructive group-aria-[disabled=true]/item:text-muted-foreground/50\">\n                  {item.icon}\n                </span>\n              )}\n              <span data-nm-label className=\"min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap\">\n                {item.label}\n              </span>\n              {branch ? (\n                <span className=\"inline-flex flex-none text-muted-foreground\" aria-hidden=\"true\">\n                  <ChevronRightIcon />\n                </span>\n              ) : item.hint ? (\n                <span className=\"flex-none text-xs tabular-nums text-muted-foreground\">{item.hint}</span>\n              ) : null}\n            </>\n          );\n          if (!isTop || !present) {\n            return (\n              <div key={item.id ?? item.label ?? index} className={rowClass} data-danger={item.danger ? \"true\" : undefined}>\n                {inner}\n              </div>\n            );\n          }\n          return (\n            <button\n              key={item.id ?? item.label ?? index}\n              ref={(el) => {\n                if (itemRefs) itemRefs.current[index] = el;\n              }}\n              type=\"button\"\n              role=\"menuitem\"\n              className={rowClass}\n              data-highlighted={active ? \"true\" : undefined}\n              data-danger={item.danger ? \"true\" : undefined}\n              aria-haspopup={branch ? \"menu\" : undefined}\n              aria-expanded={branch ? false : undefined}\n              aria-disabled={item.disabled ? \"true\" : undefined}\n              tabIndex={active ? 0 : -1}\n              onClick={(e) => {\n                e.stopPropagation();\n                onItemActivate?.(item, index, e.currentTarget);\n              }}\n              onMouseEnter={() => onItemEnter?.(index)}\n            >\n              {inner}\n            </button>\n          );\n        })}\n        {items.length === 0 && <p className=\"px-2 py-3 text-[0.8125rem] text-muted-foreground\">Nothing here yet</p>}\n      </div>\n\n      {inspect && isTop && present && (\n        <span\n          className={`absolute left-0 top-[calc(100%+0.3rem)] z-[7] whitespace-nowrap rounded-[0.25rem] bg-white px-[0.3125rem] py-[0.0625rem] text-[0.625rem] font-medium leading-normal shadow-[0_1px_2px_rgba(0,0,0,0.08)] pointer-events-none ${\n            depth > 0 ? \"border border-[#fecaca] text-[#dc2626]\" : \"border border-[#bfdbfe] text-[#2563eb]\"\n          }`}\n        >\n          {depth > 0 ? \"opens under the item · its name is the title\" : \"click a › to stack a panel over this one\"}\n        </span>\n      )}\n    </motion.div>\n  );\n}\n\nfunction Svg({ children, size = 16 }: { children: ReactNode; size?: number }) {\n  return (\n    <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n      {children}\n    </svg>\n  );\n}\n\nfunction ChevronRightIcon() { return <Svg size={15}><path d=\"m9 18 6-6-6-6\" /></Svg>; }\nfunction ChevronLeftIcon() { return <Svg><path d=\"m15 18-6-6 6-6\" /></Svg>; }\nfunction ChevronDownIcon() { return <Svg size={15}><path d=\"m6 9 6 6 6-6\" /></Svg>; }\nfunction MenuIcon() { return <Svg><path d=\"M4 6h16M4 12h16M4 18h16\" /></Svg>; }\n"
    }
  ]
}
