{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "menu",
  "title": "Menu",
  "description": "Dropdown menu on Base UI with soft-rect items and settle motion.",
  "dependencies": [
    "@base-ui/react",
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "@atroui/utils",
    "@atroui/motion"
  ],
  "files": [
    {
      "path": "registry/default/ui/menu.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\nimport { Check, ChevronRight } from \"lucide-react\"\nimport {\n  AnimatePresence,\n  LayoutGroup,\n  motion,\n  useReducedMotion,\n} from \"motion/react\"\n\nimport {\n  layoutTween,\n  menuItemVariants,\n  menuPopupMotion,\n} from \"@/lib/motion\"\nimport { cn } from \"@/lib/utils\"\n\n/** Layered pop elevation — ring-as-border + cast stack + top light. */\nconst overlayElevation = \"ds-elev-pop\"\n\ntype MenuOpenContextValue = {\n  open: boolean\n}\n\nconst MenuOpenContext = React.createContext<MenuOpenContextValue | null>(null)\n\ntype MenuHighlightContextValue = {\n  layoutId: string\n  activeId: string | null\n  setActiveId: (id: string | null) => void\n  reduce: boolean | null\n}\n\nconst MenuHighlightContext =\n  React.createContext<MenuHighlightContextValue | null>(null)\n\nfunction useMenuOpen() {\n  const ctx = React.useContext(MenuOpenContext)\n  if (!ctx) {\n    throw new Error(\"Menu parts must be used within <Menu> or <MenuSub>\")\n  }\n  return ctx.open\n}\n\nfunction Menu({\n  open: openProp,\n  defaultOpen = false,\n  onOpenChange,\n  ...props\n}: MenuPrimitive.Root.Props) {\n  const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n  const isControlled = openProp !== undefined\n  const open = isControlled ? openProp : uncontrolledOpen\n\n  const handleOpenChange = React.useCallback<\n    NonNullable<MenuPrimitive.Root.Props[\"onOpenChange\"]>\n  >(\n    (next, eventDetails) => {\n      if (!isControlled) setUncontrolledOpen(next)\n      onOpenChange?.(next, eventDetails)\n    },\n    [isControlled, onOpenChange]\n  )\n\n  return (\n    <MenuOpenContext.Provider value={{ open }}>\n      <MenuPrimitive.Root\n        data-slot=\"menu\"\n        open={open}\n        onOpenChange={handleOpenChange}\n        {...props}\n      />\n    </MenuOpenContext.Provider>\n  )\n}\n\nfunction MenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\n  return <MenuPrimitive.Portal data-slot=\"menu-portal\" {...props} />\n}\n\nfunction MenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\n  return <MenuPrimitive.Trigger data-slot=\"menu-trigger\" {...props} />\n}\n\nfunction MenuContent({\n  align = \"start\",\n  alignOffset = 0,\n  side = \"bottom\",\n  sideOffset = 6,\n  className,\n  render,\n  onMouseLeave,\n  ...props\n}: MenuPrimitive.Popup.Props &\n  Pick<\n    MenuPrimitive.Positioner.Props,\n    \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n  >) {\n  const open = useMenuOpen()\n  const reduce = useReducedMotion()\n  const groupId = React.useId()\n  const [activeId, setActiveId] = React.useState<string | null>(null)\n\n  const highlight = React.useMemo<MenuHighlightContextValue>(\n    () => ({\n      layoutId: `${groupId}-ink`,\n      activeId,\n      setActiveId,\n      reduce: reduce ?? false,\n    }),\n    [activeId, groupId, reduce]\n  )\n\n  return (\n    <AnimatePresence>\n      {open ? (\n        <MenuPrimitive.Portal keepMounted key=\"menu-portal\">\n          <MenuPrimitive.Positioner\n            className=\"isolate z-50 outline-none\"\n            align={align}\n            alignOffset={alignOffset}\n            side={side}\n            sideOffset={sideOffset}\n          >\n            <LayoutGroup id={groupId}>\n              <MenuHighlightContext.Provider value={highlight}>\n                <MenuPrimitive.Popup\n                  data-slot=\"menu-content\"\n                  className={cn(\n                    \"z-50 max-h-(--available-height) min-w-40 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-[var(--radius)] bg-popover p-0.5 text-popover-foreground outline-none\",\n                    \"data-closed:overflow-hidden\",\n                    overlayElevation,\n                    className\n                  )}\n                  render={render ?? <motion.div {...menuPopupMotion(reduce)} />}\n                  onMouseLeave={(event) => {\n                    setActiveId(null)\n                    onMouseLeave?.(event)\n                  }}\n                  {...props}\n                />\n              </MenuHighlightContext.Provider>\n            </LayoutGroup>\n          </MenuPrimitive.Positioner>\n        </MenuPrimitive.Portal>\n      ) : null}\n    </AnimatePresence>\n  )\n}\n\nfunction MenuHighlight({\n  itemId,\n  tone = \"default\",\n}: {\n  itemId: string\n  tone?: \"default\" | \"destructive\"\n}) {\n  const highlight = React.useContext(MenuHighlightContext)\n  if (!highlight || highlight.reduce || highlight.activeId !== itemId) {\n    return null\n  }\n  return (\n    <motion.span\n      layoutId={highlight.layoutId}\n      className={cn(\n        \"absolute inset-0 z-0 rounded-[calc(var(--radius)-2px)]\",\n        tone === \"destructive\" ? \"bg-destructive/10\" : \"bg-muted/80\"\n      )}\n      transition={layoutTween}\n      aria-hidden\n    />\n  )\n}\n\nconst itemBase =\n  \"relative flex cursor-default items-center gap-2 rounded-[calc(var(--radius)-2px)] px-2 py-0.5 text-[0.8125rem] leading-snug outline-none select-none\"\n\nfunction useMenuItemMotion(itemId: string) {\n  const highlight = React.useContext(MenuHighlightContext)\n  const reduce = highlight?.reduce ?? false\n\n  const arm = React.useCallback(() => {\n    highlight?.setActiveId(itemId)\n  }, [highlight, itemId])\n\n  return {\n    reduce,\n    arm,\n    rowMotion: reduce ? undefined : menuItemVariants,\n  }\n}\n\nfunction MenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n  return <MenuPrimitive.Group data-slot=\"menu-group\" {...props} />\n}\n\nfunction MenuLabel({\n  className,\n  inset,\n  ...props\n}: MenuPrimitive.GroupLabel.Props & {\n  inset?: boolean\n}) {\n  return (\n    <MenuPrimitive.GroupLabel\n      data-slot=\"menu-label\"\n      data-inset={inset}\n      className={cn(\n        \"px-2 py-1 text-[0.6875rem] font-medium tracking-wide text-muted-foreground data-[inset]:pl-7\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction MenuItem({\n  className,\n  inset,\n  variant = \"default\",\n  onMouseEnter,\n  onFocus,\n  children,\n  ...props\n}: MenuPrimitive.Item.Props & {\n  inset?: boolean\n  variant?: \"default\" | \"destructive\"\n}) {\n  const itemId = React.useId()\n  const { reduce, arm, rowMotion } = useMenuItemMotion(itemId)\n\n  return (\n    <MenuPrimitive.Item\n      data-slot=\"menu-item\"\n      data-inset={inset}\n      data-variant={variant}\n      className={cn(\n        itemBase,\n        reduce\n          ? \"data-highlighted:bg-muted data-highlighted:text-foreground data-[variant=destructive]:data-highlighted:bg-destructive/10\"\n          : \"data-highlighted:text-foreground\",\n        \"data-disabled:pointer-events-none data-disabled:opacity-50\",\n        \"data-[variant=destructive]:text-destructive\",\n        \"data-[inset]:pl-7\",\n        \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5\",\n        className\n      )}\n      render={\n        rowMotion ? <motion.div variants={rowMotion} /> : undefined\n      }\n      onMouseEnter={(event) => {\n        arm()\n        onMouseEnter?.(event)\n      }}\n      onFocus={(event) => {\n        arm()\n        onFocus?.(event)\n      }}\n      {...props}\n    >\n      <MenuHighlight itemId={itemId} tone={variant} />\n      <span className=\"relative z-[1] flex min-w-0 flex-1 items-center gap-2\">\n        {children}\n      </span>\n    </MenuPrimitive.Item>\n  )\n}\n\nfunction MenuSub({\n  open: openProp,\n  defaultOpen = false,\n  onOpenChange,\n  ...props\n}: MenuPrimitive.SubmenuRoot.Props) {\n  const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n  const isControlled = openProp !== undefined\n  const open = isControlled ? openProp : uncontrolledOpen\n\n  const handleOpenChange = React.useCallback<\n    NonNullable<MenuPrimitive.SubmenuRoot.Props[\"onOpenChange\"]>\n  >(\n    (next, eventDetails) => {\n      if (!isControlled) setUncontrolledOpen(next)\n      onOpenChange?.(next, eventDetails)\n    },\n    [isControlled, onOpenChange]\n  )\n\n  return (\n    <MenuOpenContext.Provider value={{ open }}>\n      <MenuPrimitive.SubmenuRoot\n        data-slot=\"menu-sub\"\n        open={open}\n        onOpenChange={handleOpenChange}\n        {...props}\n      />\n    </MenuOpenContext.Provider>\n  )\n}\n\nfunction MenuSubTrigger({\n  className,\n  inset,\n  children,\n  onMouseEnter,\n  onFocus,\n  ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n  inset?: boolean\n}) {\n  const itemId = React.useId()\n  const { reduce, arm, rowMotion } = useMenuItemMotion(itemId)\n\n  return (\n    <MenuPrimitive.SubmenuTrigger\n      data-slot=\"menu-sub-trigger\"\n      data-inset={inset}\n      className={cn(\n        itemBase,\n        reduce\n          ? \"data-highlighted:bg-muted data-highlighted:text-foreground data-popup-open:bg-muted data-popup-open:text-foreground\"\n          : \"data-highlighted:text-foreground data-popup-open:text-foreground\",\n        \"data-[inset]:pl-7\",\n        \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5\",\n        className\n      )}\n      render={\n        rowMotion ? <motion.div variants={rowMotion} /> : undefined\n      }\n      onMouseEnter={(event) => {\n        arm()\n        onMouseEnter?.(event)\n      }}\n      onFocus={(event) => {\n        arm()\n        onFocus?.(event)\n      }}\n      {...props}\n    >\n      <MenuHighlight itemId={itemId} />\n      <span className=\"relative z-[1] flex min-w-0 flex-1 items-center gap-2\">\n        {children}\n        <ChevronRight className=\"ml-auto size-3.5 text-muted-foreground\" />\n      </span>\n    </MenuPrimitive.SubmenuTrigger>\n  )\n}\n\nfunction MenuSubContent({\n  align = \"start\",\n  alignOffset = -3,\n  side = \"right\",\n  sideOffset = 0,\n  className,\n  ...props\n}: React.ComponentProps<typeof MenuContent>) {\n  return (\n    <MenuContent\n      data-slot=\"menu-sub-content\"\n      className={cn(\"min-w-36\", className)}\n      align={align}\n      alignOffset={alignOffset}\n      side={side}\n      sideOffset={sideOffset}\n      {...props}\n    />\n  )\n}\n\nfunction MenuCheckboxItem({\n  className,\n  children,\n  checked,\n  inset,\n  onMouseEnter,\n  onFocus,\n  ...props\n}: MenuPrimitive.CheckboxItem.Props & {\n  inset?: boolean\n}) {\n  const itemId = React.useId()\n  const { reduce, arm, rowMotion } = useMenuItemMotion(itemId)\n\n  return (\n    <MenuPrimitive.CheckboxItem\n      data-slot=\"menu-checkbox-item\"\n      data-inset={inset}\n      className={cn(\n        itemBase,\n        \"pr-2 pl-7\",\n        reduce\n          ? \"data-highlighted:bg-muted data-highlighted:text-foreground\"\n          : \"data-highlighted:text-foreground\",\n        \"data-disabled:pointer-events-none data-disabled:opacity-50\",\n        \"data-[inset]:pl-7\",\n        className\n      )}\n      render={\n        rowMotion ? <motion.div variants={rowMotion} /> : undefined\n      }\n      checked={checked}\n      onMouseEnter={(event) => {\n        arm()\n        onMouseEnter?.(event)\n      }}\n      onFocus={(event) => {\n        arm()\n        onFocus?.(event)\n      }}\n      {...props}\n    >\n      <MenuHighlight itemId={itemId} />\n      <span className=\"pointer-events-none absolute left-2 z-[1] flex size-3.5 items-center justify-center\">\n        <MenuPrimitive.CheckboxItemIndicator>\n          <Check className=\"size-3\" />\n        </MenuPrimitive.CheckboxItemIndicator>\n      </span>\n      <span className=\"relative z-[1] flex min-w-0 flex-1 items-center gap-2\">\n        {children}\n      </span>\n    </MenuPrimitive.CheckboxItem>\n  )\n}\n\nfunction MenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {\n  return <MenuPrimitive.RadioGroup data-slot=\"menu-radio-group\" {...props} />\n}\n\nfunction MenuRadioItem({\n  className,\n  children,\n  inset,\n  onMouseEnter,\n  onFocus,\n  ...props\n}: MenuPrimitive.RadioItem.Props & {\n  inset?: boolean\n}) {\n  const itemId = React.useId()\n  const { reduce, arm, rowMotion } = useMenuItemMotion(itemId)\n\n  return (\n    <MenuPrimitive.RadioItem\n      data-slot=\"menu-radio-item\"\n      data-inset={inset}\n      className={cn(\n        itemBase,\n        \"pr-2 pl-7\",\n        reduce\n          ? \"data-highlighted:bg-muted data-highlighted:text-foreground\"\n          : \"data-highlighted:text-foreground\",\n        \"data-disabled:pointer-events-none data-disabled:opacity-50\",\n        className\n      )}\n      render={\n        rowMotion ? <motion.div variants={rowMotion} /> : undefined\n      }\n      onMouseEnter={(event) => {\n        arm()\n        onMouseEnter?.(event)\n      }}\n      onFocus={(event) => {\n        arm()\n        onFocus?.(event)\n      }}\n      {...props}\n    >\n      <MenuHighlight itemId={itemId} />\n      <span className=\"pointer-events-none absolute left-2 z-[1] flex size-3.5 items-center justify-center\">\n        <MenuPrimitive.RadioItemIndicator>\n          <Check className=\"size-3\" />\n        </MenuPrimitive.RadioItemIndicator>\n      </span>\n      <span className=\"relative z-[1] flex min-w-0 flex-1 items-center gap-2\">\n        {children}\n      </span>\n    </MenuPrimitive.RadioItem>\n  )\n}\n\nfunction MenuSeparator({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      role=\"separator\"\n      aria-orientation=\"horizontal\"\n      data-slot=\"menu-separator\"\n      className={cn(\"-mx-1 my-1 h-px bg-border-subtle\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction MenuShortcut({ className, ...props }: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"menu-shortcut\"\n      className={cn(\n        \"ml-auto font-mono text-[0.6875rem] tracking-wide text-muted-foreground\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Menu,\n  MenuCheckboxItem,\n  MenuContent,\n  MenuGroup,\n  MenuItem,\n  MenuLabel,\n  MenuPortal,\n  MenuRadioGroup,\n  MenuRadioItem,\n  MenuSeparator,\n  MenuShortcut,\n  MenuSub,\n  MenuSubContent,\n  MenuSubTrigger,\n  MenuTrigger,\n}\n",
      "type": "registry:ui",
      "target": "components/ui/menu.tsx"
    }
  ],
  "type": "registry:ui"
}