{
  "name": "context-menu",
  "type": "registry:ui",
  "title": "Context Menu",
  "description": "Context Menu presents secondary actions at the pointer after a right click or long press.",
  "registryDependencies": [
    "@siteplane/base"
  ],
  "dependencies": [
    "@base-ui/react@1.5.0",
    "lucide-react@1.18.0"
  ],
  "files": [
    {
      "path": "src/components/ui/context-menu.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport { ContextMenu as ContextMenuPrimitive } from \"@base-ui/react/context-menu\";\nimport { ChevronRightIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  SiteplaneUIPortalScope,\n  useResolvedControlSize,\n  type SiteplaneControlSize,\n} from \"@/components/ui/siteplane-provider\";\nimport {\n  MenuItemCheck,\n  contextMenuSwitchThumbClassName,\n  menuCheckboxItemClassName,\n  menuCheckboxItemDefaultGridClassName,\n  menuCheckboxItemSwitchGridClassName,\n  menuGroupLabelClassName,\n  menuItemClassName,\n  menuPopupClassName,\n  menuPopupWidthClassNames,\n  menuRadioItemClassName,\n  menuSeparatorClassName,\n  menuShortcutClassName,\n  menuSubTriggerClassName,\n  type MenuPopupWidth,\n  menuSwitchTrackClassName,\n} from \"@/components/ui/menu-shared\";\n\nexport const ContextMenu: typeof ContextMenuPrimitive.Root =\n  ContextMenuPrimitive.Root;\n\nexport const ContextMenuPortal: typeof ContextMenuPrimitive.Portal =\n  ContextMenuPrimitive.Portal;\n\nexport function ContextMenuTrigger({\n  className,\n  children,\n  ...props\n}: ContextMenuPrimitive.Trigger.Props): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.Trigger\n      className={className}\n      data-slot=\"context-menu-trigger\"\n      {...props}\n    >\n      {children}\n    </ContextMenuPrimitive.Trigger>\n  );\n}\n\nexport function ContextMenuPopup({\n  children,\n  className,\n  sideOffset = 0,\n  align = \"start\",\n  alignOffset,\n  side = \"bottom\",\n  anchor,\n  portalProps,\n  width = \"auto\",\n  ...props\n}: ContextMenuPrimitive.Popup.Props & {\n  align?: ContextMenuPrimitive.Positioner.Props[\"align\"];\n  sideOffset?: ContextMenuPrimitive.Positioner.Props[\"sideOffset\"];\n  alignOffset?: ContextMenuPrimitive.Positioner.Props[\"alignOffset\"];\n  side?: ContextMenuPrimitive.Positioner.Props[\"side\"];\n  anchor?: ContextMenuPrimitive.Positioner.Props[\"anchor\"];\n  portalProps?: ContextMenuPrimitive.Portal.Props;\n  width?: MenuPopupWidth;\n}): React.ReactElement {\n  return (\n    <ContextMenuPortal {...portalProps}>\n      <SiteplaneUIPortalScope>\n        <ContextMenuPrimitive.Positioner\n          align={align}\n          alignOffset={alignOffset}\n          anchor={anchor}\n          className=\"z-50\"\n          data-slot=\"context-menu-positioner\"\n          side={side}\n          sideOffset={sideOffset}\n        >\n          <ContextMenuPrimitive.Popup\n            className={cn(\n              menuPopupClassName,\n              menuPopupWidthClassNames[width],\n              className,\n            )}\n            data-slot=\"context-menu-popup\"\n            {...props}\n          >\n            <div className=\"max-h-(--available-height) w-full overflow-y-auto p-1\">\n              {children}\n            </div>\n          </ContextMenuPrimitive.Popup>\n        </ContextMenuPrimitive.Positioner>\n      </SiteplaneUIPortalScope>\n    </ContextMenuPortal>\n  );\n}\n\nexport function ContextMenuGroup(\n  props: ContextMenuPrimitive.Group.Props,\n): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />\n  );\n}\n\nexport function ContextMenuItem({\n  className,\n  inset,\n  variant = \"default\",\n  ...props\n}: ContextMenuPrimitive.Item.Props & {\n  inset?: boolean;\n  variant?: \"default\" | \"destructive\";\n}): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.Item\n      className={cn(menuItemClassName, className)}\n      data-inset={inset}\n      data-slot=\"context-menu-item\"\n      data-variant={variant}\n      {...props}\n    />\n  );\n}\n\nexport function ContextMenuLinkItem({\n  className,\n  inset,\n  variant = \"default\",\n  closeOnClick = true,\n  ...props\n}: ContextMenuPrimitive.LinkItem.Props & {\n  inset?: boolean;\n  variant?: \"default\" | \"destructive\";\n}): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.LinkItem\n      className={cn(menuItemClassName, className)}\n      closeOnClick={closeOnClick}\n      data-inset={inset}\n      data-slot=\"context-menu-link-item\"\n      data-variant={variant}\n      {...props}\n    />\n  );\n}\n\nexport function ContextMenuCheckboxItem({\n  className,\n  children,\n  checked,\n  size,\n  variant = \"default\",\n  ...props\n}: ContextMenuPrimitive.CheckboxItem.Props & {\n  size?: SiteplaneControlSize;\n  variant?: \"default\" | \"switch\";\n}): React.ReactElement {\n  const resolvedSize = useResolvedControlSize(size);\n\n  return (\n    <ContextMenuPrimitive.CheckboxItem\n      checked={checked}\n      className={cn(\n        menuCheckboxItemClassName,\n        variant === \"switch\"\n          ? menuCheckboxItemSwitchGridClassName\n          : menuCheckboxItemDefaultGridClassName,\n        className,\n      )}\n      data-size={resolvedSize}\n      data-slot=\"context-menu-checkbox-item\"\n      {...props}\n    >\n      {variant === \"switch\" ? (\n        <>\n          <span className=\"col-start-1\">{children}</span>\n          <ContextMenuPrimitive.CheckboxItemIndicator\n            className={menuSwitchTrackClassName}\n            keepMounted\n          >\n            <span className={contextMenuSwitchThumbClassName} />\n          </ContextMenuPrimitive.CheckboxItemIndicator>\n        </>\n      ) : (\n        <>\n          <ContextMenuPrimitive.CheckboxItemIndicator className=\"col-start-1 -ms-0.5\">\n            <MenuItemCheck />\n          </ContextMenuPrimitive.CheckboxItemIndicator>\n          <span className=\"col-start-2\">{children}</span>\n        </>\n      )}\n    </ContextMenuPrimitive.CheckboxItem>\n  );\n}\n\nexport function ContextMenuRadioGroup(\n  props: ContextMenuPrimitive.RadioGroup.Props,\n): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.RadioGroup\n      data-slot=\"context-menu-radio-group\"\n      {...props}\n    />\n  );\n}\n\nexport function ContextMenuRadioItem({\n  className,\n  children,\n  ...props\n}: ContextMenuPrimitive.RadioItem.Props): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.RadioItem\n      className={cn(menuRadioItemClassName, className)}\n      data-slot=\"context-menu-radio-item\"\n      {...props}\n    >\n      <ContextMenuPrimitive.RadioItemIndicator className=\"col-start-1 -ms-0.5\">\n        <MenuItemCheck />\n      </ContextMenuPrimitive.RadioItemIndicator>\n      <span className=\"col-start-2\">{children}</span>\n    </ContextMenuPrimitive.RadioItem>\n  );\n}\n\nexport function ContextMenuGroupLabel({\n  className,\n  inset,\n  ...props\n}: ContextMenuPrimitive.GroupLabel.Props & {\n  inset?: boolean;\n}): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.GroupLabel\n      className={cn(menuGroupLabelClassName, className)}\n      data-inset={inset}\n      data-slot=\"context-menu-label\"\n      {...props}\n    />\n  );\n}\n\nexport function ContextMenuSeparator({\n  className,\n  ...props\n}: ContextMenuPrimitive.Separator.Props): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.Separator\n      className={cn(menuSeparatorClassName, className)}\n      data-slot=\"context-menu-separator\"\n      {...props}\n    />\n  );\n}\n\nexport function ContextMenuShortcut({\n  className,\n  ...props\n}: React.ComponentProps<\"kbd\">): React.ReactElement {\n  return (\n    <kbd\n      className={cn(menuShortcutClassName, className)}\n      data-slot=\"context-menu-shortcut\"\n      {...props}\n    />\n  );\n}\n\nexport function ContextMenuSub(\n  props: ContextMenuPrimitive.SubmenuRoot.Props,\n): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.SubmenuRoot data-slot=\"context-menu-sub\" {...props} />\n  );\n}\n\nexport function ContextMenuSubTrigger({\n  className,\n  inset,\n  children,\n  ...props\n}: ContextMenuPrimitive.SubmenuTrigger.Props & {\n  inset?: boolean;\n}): React.ReactElement {\n  return (\n    <ContextMenuPrimitive.SubmenuTrigger\n      className={cn(menuSubTriggerClassName, className)}\n      data-inset={inset}\n      data-slot=\"context-menu-sub-trigger\"\n      {...props}\n    >\n      {children}\n      <ChevronRightIcon className=\"ms-auto -me-0.5 opacity-80\" />\n    </ContextMenuPrimitive.SubmenuTrigger>\n  );\n}\n\nexport function ContextMenuSubPopup({\n  className,\n  sideOffset = 0,\n  alignOffset,\n  align = \"start\",\n  ...props\n}: ContextMenuPrimitive.Popup.Props & {\n  align?: ContextMenuPrimitive.Positioner.Props[\"align\"];\n  sideOffset?: ContextMenuPrimitive.Positioner.Props[\"sideOffset\"];\n  alignOffset?: ContextMenuPrimitive.Positioner.Props[\"alignOffset\"];\n  width?: MenuPopupWidth;\n}): React.ReactElement {\n  const defaultAlignOffset = align !== \"center\" ? -5 : undefined;\n\n  return (\n    <ContextMenuPopup\n      align={align}\n      alignOffset={alignOffset ?? defaultAlignOffset}\n      className={className}\n      data-slot=\"context-menu-sub-content\"\n      side=\"inline-end\"\n      sideOffset={sideOffset}\n      {...props}\n    />\n  );\n}\n\nexport { ContextMenuPrimitive };\n"
    },
    {
      "path": "src/components/ui/icons.tsx",
      "type": "registry:ui",
      "content": "import type React from \"react\";\n\n// Siteplane-UI-Haken-Glyphe (bewusst andere Geometrie als lucide `Check`).\n// Einzige Quelle fuer den statischen Selected-Marker in Select, Combobox, Menu,\n// ContextMenu und Drawer. (Die Checkbox nutzt eine eigene, ueber\n// `siteplane-checkbox-check` animierte Variante und bleibt davon unberuehrt.)\nexport function CheckIcon(props: React.ComponentProps<\"svg\">): React.ReactElement {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      fill=\"none\"\n      height=\"24\"\n      stroke=\"currentColor\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      strokeWidth=\"2\"\n      viewBox=\"0 0 24 24\"\n      width=\"24\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...props}\n    >\n      <path d=\"M5.252 12.7 10.2 18.63 18.748 5.37\" />\n    </svg>\n  );\n}\n"
    },
    {
      "path": "src/components/ui/menu-shared.tsx",
      "type": "registry:ui",
      "content": "import type React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { CheckIcon } from \"@/components/ui/icons\";\nimport { surfaceClassNames } from \"@/components/ui/surface\";\nimport { shortcutClassName } from \"@/components/ui/typography\";\n\n// Eine Quelle fuer das gesamte Menu-Styling. `Menu` (@base-ui/react/menu) und\n// `ContextMenu` (@base-ui/react/context-menu) wrappen unterschiedliche Primitive,\n// teilen aber exakt dieselbe Optik. Frueher waren beide Dateien byte-fuer-byte\n// Zwillinge; jetzt importieren sie diese Konstanten, damit eine Styling-Aenderung\n// garantiert beide Familien erreicht.\n//\n// WICHTIG: alle Klassen sind literale Strings — Tailwind v4 scannt den Quelltext,\n// dynamisch zusammengebaute Klassen wuerden nicht generiert. Die slot-gebundenen\n// Switch-Thumb-Selektoren existieren deshalb je einmal pro Familie.\n\nexport const menuPopupClassName = cn(\n  surfaceClassNames.floatingOverlay,\n  \"flex not-[class*='min-w-']:min-w-32 origin-(--transform-origin) rounded-lg outline-none before:rounded-[inherit] focus:outline-none\",\n);\n\nexport type MenuPopupWidth = \"auto\" | \"trigger\" | \"content\" | \"at-least-trigger\";\n\nexport const menuPopupWidthClassNames: Record<MenuPopupWidth, string> = {\n  auto: \"\",\n  content: \"w-max max-w-(--available-width)\",\n  trigger: \"min-w-0 w-(--anchor-width)\",\n  \"at-least-trigger\":\n    \"min-w-(--anchor-width) w-max max-w-(--available-width)\",\n};\n\n// Menuezeilen folgen derselben globalen controlSize-Achse wie ihr Trigger,\n// behalten als wiederholte Listenelemente aber eine kompaktere eigene\n// Geometrie. `default` bleibt die bestehende Dashboard-Dichte; lg entspricht\n// der jeweiligen Button-Hoehe, xl bleibt bewusst unter dem 56px-CTA-Format.\nconst menuRowSizeClassName =\n  \"in-[[data-control-size=sm]]:min-h-7 in-[[data-control-size=sm]]:py-0.5 in-[[data-control-size=sm]]:text-sm in-[[data-control-size=lg]]:min-h-10 in-[[data-control-size=lg]]:text-base in-[[data-control-size=xl]]:min-h-12 in-[[data-control-size=xl]]:text-base sm:in-[[data-control-size=sm]]:min-h-6 sm:in-[[data-control-size=sm]]:text-sm sm:in-[[data-control-size=lg]]:min-h-9 sm:in-[[data-control-size=lg]]:text-base sm:in-[[data-control-size=xl]]:min-h-11 sm:in-[[data-control-size=xl]]:text-base\";\n\nconst menuRowIconSizeClassName =\n  \"in-[[data-control-size=sm]]:[&_svg:not([class*='size-'])]:size-4 in-[[data-control-size=lg]]:[&_svg:not([class*='size-'])]:size-4.5 in-[[data-control-size=xl]]:[&_svg:not([class*='size-'])]:size-5 sm:in-[[data-control-size=sm]]:[&_svg:not([class*='size-'])]:size-3.5 sm:in-[[data-control-size=lg]]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-control-size=xl]]:[&_svg:not([class*='size-'])]:size-5\";\n\n// Item + LinkItem teilen sich exakt dieselbe Klasse.\nexport const menuItemClassName = cn(\n  \"flex min-h-8 cursor-pointer select-none items-center gap-2 whitespace-nowrap rounded-sm px-2 py-1 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-inset:ps-8 data-[variant=destructive]:text-destructive-foreground data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&>svg:not([class*='opacity-'])]:opacity-80 [&>svg:not([class*='size-'])]:size-4.5 sm:[&>svg:not([class*='size-'])]:size-4 [&>svg]:pointer-events-none [&>svg]:-mx-0.5 [&>svg]:shrink-0\",\n  menuRowSizeClassName,\n  menuRowIconSizeClassName,\n);\n\nexport const menuCheckboxItemClassName = cn(\n  \"grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-pointer items-center gap-2 whitespace-nowrap rounded-sm py-1 ps-2 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n  menuRowSizeClassName,\n  menuRowIconSizeClassName,\n);\n\nexport const menuCheckboxItemSwitchGridClassName = \"grid-cols-[1fr_auto] gap-4 pe-1.5\";\nexport const menuCheckboxItemDefaultGridClassName = \"grid-cols-[.75rem_1fr] pe-4\";\n\nexport const menuSwitchTrackClassName =\n  \"inset-shadow-[0_1px_--theme(--color-black/4%)] inline-flex h-[calc(var(--thumb-size)+2px)] w-[calc(var(--thumb-size)*2-2px)] shrink-0 items-center rounded-full p-px outline-none transition-[background-color,box-shadow] duration-(--motion-duration-base) [--thumb-size:--spacing(5)] in-[[data-size=sm]]:[--thumb-size:--spacing(4)] in-[[data-size=lg]]:[--thumb-size:--spacing(6)] in-[[data-size=xl]]:[--thumb-size:--spacing(7)] focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background data-checked:bg-primary data-unchecked:bg-input data-disabled:opacity-64 motion-reduce:transition-none sm:[--thumb-size:--spacing(4)] sm:in-[[data-size=sm]]:[--thumb-size:--spacing(3.5)] sm:in-[[data-size=lg]]:[--thumb-size:--spacing(5)] sm:in-[[data-size=xl]]:[--thumb-size:--spacing(6)]\";\n\n// Slot-gebunden -> je ein literaler String pro Familie (Tailwind-Scan).\nexport const menuSwitchThumbClassName =\n  \"pointer-events-none block aspect-square h-full in-[[data-slot=menu-checkbox-item][data-checked]]:origin-[var(--thumb-size)_50%] origin-left in-[[data-slot=menu-checkbox-item][data-checked]]:translate-x-[calc(var(--thumb-size)-4px)] in-[[data-slot=menu-checkbox-item]:active]:not-data-disabled:scale-x-110 in-[[data-slot=menu-checkbox-item]:active]:rounded-[var(--thumb-size)/calc(var(--thumb-size)*1.10)] rounded-(--thumb-size) bg-background shadow-sm/5 will-change-transform [transition:translate_var(--motion-duration-base),border-radius_var(--motion-duration-base),scale_var(--motion-duration-micro)_var(--motion-duration-micro),transform-origin_var(--motion-duration-base)] motion-reduce:transition-none\";\n\nexport const contextMenuSwitchThumbClassName =\n  \"pointer-events-none block aspect-square h-full in-[[data-slot=context-menu-checkbox-item][data-checked]]:origin-[var(--thumb-size)_50%] origin-left in-[[data-slot=context-menu-checkbox-item][data-checked]]:translate-x-[calc(var(--thumb-size)-4px)] in-[[data-slot=context-menu-checkbox-item]:active]:not-data-disabled:scale-x-110 in-[[data-slot=context-menu-checkbox-item]:active]:rounded-[var(--thumb-size)/calc(var(--thumb-size)*1.10)] rounded-(--thumb-size) bg-background shadow-sm/5 will-change-transform [transition:translate_var(--motion-duration-base),border-radius_var(--motion-duration-base),scale_var(--motion-duration-micro)_var(--motion-duration-micro),transform-origin_var(--motion-duration-base)] motion-reduce:transition-none\";\n\nexport const menuRadioItemClassName = cn(\n  \"grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-pointer grid-cols-[.75rem_1fr] items-center gap-2 whitespace-nowrap rounded-sm py-1 ps-2 pe-4 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n  menuRowSizeClassName,\n  menuRowIconSizeClassName,\n);\n\nexport const menuGroupLabelClassName =\n  \"px-2 py-1.5 font-medium text-muted-foreground text-xs data-inset:ps-9 in-[[data-control-size=sm]]:py-1 in-[[data-control-size=lg]]:py-2 in-[[data-control-size=lg]]:text-sm in-[[data-control-size=xl]]:py-2.5 in-[[data-control-size=xl]]:text-sm sm:data-inset:ps-8\";\n\nexport const menuSeparatorClassName =\n  \"mx-2 my-1 h-px bg-border in-[[data-control-size=lg]]:my-1.5 in-[[data-control-size=xl]]:my-2\";\n\nexport const menuShortcutClassName = shortcutClassName;\n\nexport const menuSubTriggerClassName = cn(\n  \"flex min-h-8 cursor-pointer items-center gap-2 whitespace-nowrap rounded-sm px-2 py-1 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-popup-open:bg-accent data-inset:ps-8 data-highlighted:text-accent-foreground data-popup-open:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&>svg:not(:last-child)]:-mx-0.5 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none\",\n  menuRowSizeClassName,\n  menuRowIconSizeClassName,\n);\n\n// Statischer Haken im Default-Checkbox-/Radio-Item (eine Glyphe, kein Inline-SVG).\nexport function MenuItemCheck(): React.ReactElement {\n  return <CheckIcon />;\n}\n"
    },
    {
      "path": "src/components/ui/typography.ts",
      "type": "registry:ui",
      "content": "export const codeInlineClassName =\n  \"rounded-(--code-inline-radius) border border-border bg-muted px-1.5 py-0.5 font-mono [font-size:var(--code-inline-font-size)] text-foreground\";\n\nexport const codeBlockBaseClassName =\n  \"relative w-full overflow-x-auto rounded-lg border border-border bg-muted/50 font-mono text-foreground leading-relaxed\";\n\nexport const codeBlockSizeClassNames = {\n  default: \"px-3.5 py-3 text-xs\",\n  sm: \"px-3 py-2 [font-size:var(--code-block-sm-font-size)]\",\n} as const;\n\nexport const kbdClassName =\n  \"pointer-events-none inline-flex h-5 min-w-5 shrink-0 select-none items-center justify-center gap-1 whitespace-nowrap rounded-(--kbd-radius) bg-muted px-1 font-medium font-sans text-muted-foreground text-xs [&_svg:not([class*='size-'])]:size-3\";\n\nexport const shortcutClassName =\n  \"ms-auto font-medium font-sans text-muted-foreground/72 text-xs tracking-normal\";\n"
    }
  ],
  "categories": [
    "overlays"
  ],
  "docs": "# Context Menu\n\n> Siteplane UI release `0.1.1`.\n\n## Public Purpose\n\nContext Menu presents secondary actions at the pointer after a right click or\nlong press. Keep primary actions visible outside the menu.\n\n## Import\n\n`import { ContextMenu, ContextMenuCheckboxItem, ContextMenuGroup, ContextMenuGroupLabel, ContextMenuItem, ContextMenuLinkItem, ContextMenuPopup, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubPopup, ContextMenuSubTrigger, ContextMenuTrigger } from \"@/components/ui/context-menu\";`\n\n## Public API\n\n- `ContextMenuPopup width` accepts `\"auto\"`, `\"trigger\"`, `\"content\"`,\n  or `\"at-least-trigger\"`; use the prop instead of hardcoded width classes.\n- Popup placement is controlled by `side`, `align`, `sideOffset`, and\n  `alignOffset`. Defaults are bottom, start, and zero side offset.\n- Use `inset` on items, group labels, and submenu triggers to align rows\n  without leading icons.\n- `ContextMenuCheckboxItem size` accepts `\"sm\"`, `\"default\"`, `\"lg\"`,\n  and `\"xl\"`.\n- All item, selection, label, separator, and submenu rows inherit the\n  provider `controlSize`; repeated rows use the compact menu geometry from the\n  global size contract rather than the 56px XL CTA height.\n- `ContextMenuLinkItem closeOnClick` defaults to `true`; set it to\n  `false` only when navigation must leave the menu open.\n- Use `disabled` for unavailable actions.\n- Use `ContextMenuLinkItem` for navigation instead of adding link behavior to\n  a command item.\n\n## Public Motion\n\n- Popup and submenu scale, fade, placement, and reduced-motion behavior are\n  native to Context Menu.\n- Active items and submenu triggers use a pointer cursor.\n- Do not add a second popup transition.\n\n## Public Accessibility\n\n- The trigger target needs visible context that explains what will receive the\n  actions.\n- Preserve right-click, long-press, keyboard, focus, Escape, and dismissal\n  behavior.\n- Keep disabled items unavailable and visibly distinct.\n- Checkbox and radio items must retain their selection indicators.\n\n## Public Agent Guidance\n\n- Use Context Menu only for pointer-related secondary actions.\n- Keep primary actions visible and discoverable elsewhere.\n- Use width, placement, inset, size, disabled, and link props instead of local\n  menu styling.\n- Preserve native item, submenu, selection, cursor, and focus behavior.\n\n## Public Links\n\n- [Documentation and preview](https://ui.siteplane.io/docs/components/overlays/context-menu)\n\n- [Registry source](https://ui.siteplane.io/r/context-menu.json)\n",
  "meta": {
    "siteplane:agentContractVersion": 1,
    "siteplane:docs": "https://ui.siteplane.io/docs/components/overlays/context-menu",
    "siteplane:releaseVersion": "0.1.1",
    "siteplane:sourceOwned": true
  },
  "devDependencies": []
}
