{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dropdown-menu",
  "title": "Dropdown Menu",
  "description": "A menu of actions that opens from a trigger.",
  "dependencies": [
    "@base-ui/react@^1.9.0"
  ],
  "registryDependencies": [
    "https://sproutboat.com/ikada/r/theme.json",
    "https://sproutboat.com/ikada/r/cn.json",
    "https://sproutboat.com/ikada/r/icons.json",
    "https://sproutboat.com/ikada/r/instant.json",
    "https://sproutboat.com/ikada/r/portal.json"
  ],
  "files": [
    {
      "path": "registry/ikada/ui/dropdown-menu.tsx",
      "content": "\"use client\";\n\nimport { Menu } from \"@base-ui/react/menu\";\nimport type { ComponentProps } from \"react\";\nimport { cn, floatingSurface, popupMotion, type WithClass } from \"@/components/ikada/lib/cn\";\nimport { InstantProvider, instantAttr, useInstant, useInstantOpen } from \"@/components/ikada/lib/instant\";\nimport { CheckIcon } from \"@/components/ikada/lib/icons\";\nimport { usePortalContainer } from \"@/components/ikada/lib/portal\";\n\n/**\n * A menu of actions that opens from a trigger. Arrives at the trigger on the snappy spring and\n * leaves in 110ms; opened with a key it appears at once. Compose with DropdownMenuTrigger and DropdownMenuContent.\n */\nexport function DropdownMenu({ onOpenChange, ...props }: ComponentProps<typeof Menu.Root>) {\n  const [instant, handle] = useInstantOpen(onOpenChange);\n  return (\n    <InstantProvider value={instant}>\n      <Menu.Root onOpenChange={handle} {...props} />\n    </InstantProvider>\n  );\n}\nexport const DropdownMenuTrigger = Menu.Trigger;\nexport const DropdownMenuGroup = Menu.Group;\n/** A group of radio items: exactly one is chosen, with `value` and `onValueChange`. */\nexport const DropdownMenuRadioGroup = Menu.RadioGroup;\n\nexport interface DropdownMenuContentProps extends Omit<ComponentProps<typeof Menu.Popup>, \"className\"> {\n  className?: string;\n  side?: ComponentProps<typeof Menu.Positioner>[\"side\"];\n  align?: ComponentProps<typeof Menu.Positioner>[\"align\"];\n}\n\n/**\n * A 12px layer holding 8px items with 4px padding (8 + 4). When any child is a checkbox\n * item, every item gets the same fixed 1.5rem gutter (--sb-gutter), so item text lines up\n * whether or not that row shows a check.\n */\nexport function DropdownMenuContent({\n  className,\n  side = \"bottom\",\n  align = \"end\",\n  children,\n  ref,\n  ...props\n}: DropdownMenuContentProps) {\n  const instant = useInstant();\n  const container = usePortalContainer();\n  return (\n    <Menu.Portal container={container}>\n      <Menu.Positioner side={side} align={align} sideOffset={6} collisionPadding={8} className=\"z-(--sb-z-dropdown)\">\n        <Menu.Popup\n          data-slot=\"dropdown-menu-content\"\n          ref={ref}\n          className={cn(\n            floatingSurface,\n            popupMotion,\n            \"min-w-48 max-w-(--available-width) overflow-y-auto overscroll-contain p-1 text-sb-base [--sb-gutter:0rem] has-[[role=menuitemcheckbox]]:[--sb-gutter:1.5rem] has-[[role=menuitemradio]]:[--sb-gutter:1.5rem]\",\n            className,\n          )}\n          {...instantAttr(instant)}\n          {...props}\n        >\n          {children}\n        </Menu.Popup>\n      </Menu.Positioner>\n    </Menu.Portal>\n  );\n}\n\nconst itemStyles = [\n  \"relative flex min-h-9 min-w-0 cursor-default wrap-anywhere items-center gap-2 rounded-md py-1.5 pe-2.5 ps-[calc(0.625rem+var(--sb-gutter))] text-sb-base outline-hidden select-none\",\n  \"transition-colors duration-(--sb-duration-hover) ease-hover\",\n  \"data-disabled:opacity-50 data-highlighted:bg-hover pointer-coarse:min-h-11\",\n].join(\" \");\n\nexport interface DropdownMenuItemProps extends Omit<ComponentProps<typeof Menu.Item>, \"className\"> {\n  className?: string;\n  /** Destructive items use the danger text color. */\n  destructive?: boolean;\n}\n\nexport function DropdownMenuItem({ className, destructive = false, ...props }: DropdownMenuItemProps) {\n  return (\n    <Menu.Item\n      data-slot=\"dropdown-menu-item\"\n      className={cn(itemStyles, destructive && \"text-danger-fg\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function DropdownMenuCheckboxItem({\n  className,\n  children,\n  ...props\n}: WithClass<ComponentProps<typeof Menu.CheckboxItem>>) {\n  return (\n    <Menu.CheckboxItem data-slot=\"dropdown-menu-checkbox-item\" className={cn(itemStyles, className)} {...props}>\n      <span aria-hidden=\"true\" className=\"absolute start-2.5 grid size-4 place-items-center\">\n        <Menu.CheckboxItemIndicator\n          className={cn(\n            \"flex transition-[opacity,scale] duration-(--sb-duration-hover) ease-out\",\n            \"data-starting-style:scale-(--sb-scale-icon) data-starting-style:opacity-0\",\n            \"data-ending-style:scale-(--sb-scale-icon) data-ending-style:opacity-0\",\n          )}\n        >\n          <CheckIcon />\n        </Menu.CheckboxItemIndicator>\n      </span>\n      {children}\n    </Menu.CheckboxItem>\n  );\n}\n\nexport function DropdownMenuRadioItem({\n  className,\n  children,\n  ...props\n}: WithClass<ComponentProps<typeof Menu.RadioItem>>) {\n  return (\n    <Menu.RadioItem data-slot=\"dropdown-menu-radio-item\" className={cn(itemStyles, className)} {...props}>\n      <span aria-hidden=\"true\" className=\"absolute start-2.5 grid size-4 place-items-center\">\n        <Menu.RadioItemIndicator\n          className={cn(\n            \"flex transition-[opacity,scale] duration-(--sb-duration-hover) ease-out\",\n            \"data-starting-style:scale-(--sb-scale-icon) data-starting-style:opacity-0\",\n            \"data-ending-style:scale-(--sb-scale-icon) data-ending-style:opacity-0\",\n          )}\n        >\n          <CheckIcon />\n        </Menu.RadioItemIndicator>\n      </span>\n      {children}\n    </Menu.RadioItem>\n  );\n}\n\nexport function DropdownMenuLabel({ className, ...props }: WithClass<ComponentProps<typeof Menu.GroupLabel>>) {\n  return (\n    <Menu.GroupLabel\n      data-slot=\"dropdown-menu-label\"\n      className={cn(\"px-2.5 pt-1.5 pb-1 text-sb-xs font-semibold text-fg-muted\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function DropdownMenuSeparator({ className, ...props }: WithClass<ComponentProps<typeof Menu.Separator>>) {\n  return (\n    <Menu.Separator\n      data-slot=\"dropdown-menu-separator\"\n      className={cn(\"mx-1.5 my-1 h-px bg-hairline-strong/70\", className)}\n      {...props}\n    />\n  );\n}\n",
      "type": "registry:ui",
      "target": "@components/ikada/dropdown-menu.tsx"
    }
  ],
  "categories": [
    "overlays"
  ],
  "type": "registry:ui"
}