{
  "schemaVersion": 1,
  "name": "context-menu",
  "useFor": "Use for shortcuts to actions on an item in a list (an email in the inbox, a contact). Every action must also be reachable another way, such as a row's menu button.",
  "constraints": [
    "Actions that exist only in the context menu",
    "A context menu on text people need to select",
    "Nested submenus beyond one level"
  ],
  "documentation": "",
  "source": "Extrapolated from the Inkbox console (Figma 427:2715): the email list items, nav rows and the raised panel",
  "exports": [
    "ContextMenu",
    "ContextMenuCheckboxItem",
    "ContextMenuContent",
    "ContextMenuGroup",
    "ContextMenuItem",
    "ContextMenuLabel",
    "ContextMenuPortal",
    "ContextMenuRadioGroup",
    "ContextMenuRadioItem",
    "ContextMenuSeparator",
    "ContextMenuShortcut",
    "ContextMenuSub",
    "ContextMenuSubContent",
    "ContextMenuSubTrigger",
    "ContextMenuTrigger"
  ],
  "client": true,
  "docsUrl": "https://inkbox-ds.vercel.app/components/context-menu",
  "markdownUrl": "https://inkbox-ds.vercel.app/r/context-menu.md",
  "examples": [
    {
      "path": "examples/context-menu.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { ArchiveIcon, ArrowBendUpLeftIcon, ArrowBendUpRightIcon, EnvelopeOpenIcon, ProhibitIcon, TrashIcon, WarningIcon } from \"@phosphor-icons/react/ssr\";\n\nimport {\n  ContextMenu,\n  ContextMenuCheckboxItem,\n  ContextMenuContent,\n  ContextMenuItem,\n  ContextMenuLabel,\n  ContextMenuRadioGroup,\n  ContextMenuRadioItem,\n  ContextMenuSeparator,\n  ContextMenuShortcut,\n  ContextMenuSub,\n  ContextMenuSubContent,\n  ContextMenuSubTrigger,\n  ContextMenuTrigger,\n} from \"@/components/ui/context-menu\";\n\nexport function Preview() {\n  const [starred, setStarred] = React.useState(false);\n  const [folder, setFolder] = React.useState(\"inbox\");\n  return (\n    <ContextMenu>\n      <ContextMenuTrigger className=\"mx-auto grid w-full max-w-96 gap-1 rounded-control bg-subtle p-3\">\n        <span className=\"flex justify-between text-body text-fg\">\n          Ray Liao <span className=\"text-fg-muted\">Yesterday</span>\n        </span>\n        <span className=\"text-body text-fg\">Inkbox A2A: publish your Agent Card</span>\n        <span className=\"truncate text-body text-fg-brand\">Hello @acme, This is Ray, cofounder of Inkbox.</span>\n        <span className=\"mt-2 text-caption text-fg-muted\">Right-click or long-press the email</span>\n      </ContextMenuTrigger>\n      <ContextMenuContent className=\"w-60\">\n        <ContextMenuItem>\n          <ArrowBendUpLeftIcon />\n          Reply\n          <ContextMenuShortcut>R</ContextMenuShortcut>\n        </ContextMenuItem>\n        <ContextMenuItem>\n          <ArrowBendUpRightIcon />\n          Forward\n          <ContextMenuShortcut>F</ContextMenuShortcut>\n        </ContextMenuItem>\n        <ContextMenuItem>\n          <EnvelopeOpenIcon weight=\"fill\" />\n          Mark as unread\n        </ContextMenuItem>\n        <ContextMenuCheckboxItem checked={starred} onCheckedChange={(v) => setStarred(v === true)}>\n          Starred\n        </ContextMenuCheckboxItem>\n        <ContextMenuSub>\n          <ContextMenuSubTrigger>\n            <ArchiveIcon weight=\"fill\" />\n            Move to\n          </ContextMenuSubTrigger>\n          <ContextMenuSubContent className=\"w-44\">\n            <ContextMenuLabel>Folders</ContextMenuLabel>\n            <ContextMenuRadioGroup value={folder} onValueChange={setFolder}>\n              <ContextMenuRadioItem value=\"inbox\">Inbox</ContextMenuRadioItem>\n              <ContextMenuRadioItem value=\"sent\">Sent</ContextMenuRadioItem>\n              <ContextMenuRadioItem value=\"spam\">Spam</ContextMenuRadioItem>\n            </ContextMenuRadioGroup>\n          </ContextMenuSubContent>\n        </ContextMenuSub>\n        <ContextMenuSeparator />\n        <ContextMenuItem>\n          <WarningIcon weight=\"fill\" />\n          Report spam\n        </ContextMenuItem>\n        <ContextMenuItem>\n          <ProhibitIcon />\n          Block sender\n        </ContextMenuItem>\n        <ContextMenuItem variant=\"destructive\">\n          <TrashIcon weight=\"fill\" />\n          Delete\n          <ContextMenuShortcut>⌫</ContextMenuShortcut>\n        </ContextMenuItem>\n      </ContextMenuContent>\n    </ContextMenu>\n  );\n}\n",
      "exports": [
        "Preview"
      ],
      "requires": [
        "context-menu"
      ],
      "packages": [
        "@phosphor-icons/react"
      ],
      "previews": [
        {
          "name": "Preview",
          "url": "https://inkbox-ds.vercel.app/preview/context-menu/Preview"
        }
      ]
    }
  ],
  "type": "ui",
  "title": "Context Menu",
  "description": "The dropdown menu's panel and rows, opened with a right click or a long press on an area.",
  "surface": "site",
  "kinds": [],
  "requires": [
    "theme",
    "surface",
    "utils"
  ],
  "packages": [
    "radix-ui",
    "@phosphor-icons/react"
  ],
  "files": [
    {
      "path": "components/ui/context-menu.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { ContextMenu as ContextMenuPrimitive } from \"radix-ui\";\nimport { CaretRightIcon, CheckIcon } from \"@phosphor-icons/react/ssr\";\n\nimport { usePortalContainer } from \"@/lib/surface\";\nimport { cn } from \"@/lib/utils\";\n\n// A right-click menu, extrapolated from the console (Figma 427:2715), drawn as the dropdown menu: the panel is a raised white panel (8px corners, the floating\n// shadow) with 4px of padding; items are 36px rows with 8px corners like the rail's nav rows, a 20px glyph in the\n// action-glyph purple 10px from a 14px ink label, and the lilac under the highlighted row. Section labels are 13px in\n// the label purple (\"Channels\"), separators the rail's hairline, shortcuts 12px muted, destructive items red. The\n// panel grows out of its trigger from 96 percent with a fade; highlighting a row is instant (menus are used by keyboard\n// and many times a day).\nconst CONTENT =\n  \"z-50 max-h-(--radix-context-menu-content-available-height) min-w-48 overflow-x-hidden overflow-y-auto rounded-control bg-surface p-1 text-fg shadow-floating outline-none data-[state=closed]:animate-pop-out data-[state=open]:animate-pop-in\";\nconst ITEM =\n  \"relative flex h-9 cursor-default items-center gap-2.5 rounded-control px-2.5 font-sans text-body leading-tight text-fg outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-subtle data-[inset]:pl-10.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-5.5 [&_svg:not([class*='text-'])]:text-icon-secondary\";\n\nfunction ContextMenu(props: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {\n  return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />;\n}\n\nfunction ContextMenuPortal(props: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {\n  const container = usePortalContainer();\n  return <ContextMenuPrimitive.Portal data-slot=\"context-menu-portal\" container={container} {...props} />;\n}\n\nfunction ContextMenuTrigger({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {\n  return <ContextMenuPrimitive.Trigger data-slot=\"context-menu-trigger\" className={cn(\"select-none\", className)} {...props} />;\n}\n\nfunction ContextMenuContent({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {\n  return (\n    <ContextMenuPortal>\n      <ContextMenuPrimitive.Content data-slot=\"context-menu-content\" className={cn(CONTENT, \"origin-(--radix-context-menu-content-transform-origin)\", className)} {...props} />\n    </ContextMenuPortal>\n  );\n}\n\nfunction ContextMenuGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {\n  return <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />;\n}\n\nfunction ContextMenuItem({ className, inset, variant = \"default\", ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Item> & { inset?: boolean; variant?: \"default\" | \"destructive\" }) {\n  return (\n    <ContextMenuPrimitive.Item\n      data-slot=\"context-menu-item\"\n      data-inset={inset || undefined}\n      data-variant={variant}\n      className={cn(ITEM, \"data-[variant=destructive]:text-danger data-[variant=destructive]:[&_svg]:text-danger\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction ContextMenuCheckboxItem({ className, children, checked, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {\n  return (\n    <ContextMenuPrimitive.CheckboxItem data-slot=\"context-menu-checkbox-item\" checked={checked} className={cn(ITEM, \"pl-10.5\", className)} {...props}>\n      <span className=\"pointer-events-none absolute left-2.5 flex size-5.5 items-center justify-center\">\n        <ContextMenuPrimitive.ItemIndicator>\n          <CheckIcon weight=\"bold\" className=\"size-4.5 text-fg-brand\" />\n        </ContextMenuPrimitive.ItemIndicator>\n      </span>\n      {children}\n    </ContextMenuPrimitive.CheckboxItem>\n  );\n}\n\nfunction ContextMenuRadioGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) {\n  return <ContextMenuPrimitive.RadioGroup data-slot=\"context-menu-radio-group\" {...props} />;\n}\n\n// The selected choice wears the console's radio mark: a pink ring around white.\nfunction ContextMenuRadioItem({ className, children, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {\n  return (\n    <ContextMenuPrimitive.RadioItem data-slot=\"context-menu-radio-item\" className={cn(ITEM, \"pl-10.5\", className)} {...props}>\n      <span className=\"pointer-events-none absolute left-2.5 flex size-5.5 items-center justify-center\">\n        <ContextMenuPrimitive.ItemIndicator>\n          <span className=\"block size-3.5 rounded-pill border-[3.5px] border-pink bg-surface\" />\n        </ContextMenuPrimitive.ItemIndicator>\n      </span>\n      {children}\n    </ContextMenuPrimitive.RadioItem>\n  );\n}\n\nfunction ContextMenuLabel({ className, inset, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Label> & { inset?: boolean }) {\n  return <ContextMenuPrimitive.Label data-slot=\"context-menu-label\" data-inset={inset || undefined} className={cn(\"px-2.5 pt-2 pb-1 font-sans text-body-sm leading-tight text-fg-label data-[inset]:pl-10.5\", className)} {...props} />;\n}\n\nfunction ContextMenuSeparator({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {\n  return <ContextMenuPrimitive.Separator data-slot=\"context-menu-separator\" className={cn(\"-mx-1 my-1 h-px bg-line-subtle\", className)} {...props} />;\n}\n\nfunction ContextMenuShortcut({ className, ...props }: React.ComponentProps<\"span\">) {\n  return <span data-slot=\"context-menu-shortcut\" className={cn(\"ml-auto pl-4 font-sans text-caption text-fg-muted\", className)} {...props} />;\n}\n\nfunction ContextMenuSub(props: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {\n  return <ContextMenuPrimitive.Sub data-slot=\"context-menu-sub\" {...props} />;\n}\n\nfunction ContextMenuSubTrigger({ className, inset, children, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n  return (\n    <ContextMenuPrimitive.SubTrigger data-slot=\"context-menu-sub-trigger\" data-inset={inset || undefined} className={cn(ITEM, \"data-[state=open]:bg-subtle\", className)} {...props}>\n      {children}\n      <CaretRightIcon className=\"ml-auto size-4.5 text-fg-muted\" />\n    </ContextMenuPrimitive.SubTrigger>\n  );\n}\n\nfunction ContextMenuSubContent({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {\n  return (\n    <ContextMenuPortal>\n      <ContextMenuPrimitive.SubContent data-slot=\"context-menu-sub-content\" className={cn(CONTENT, \"max-h-(--radix-context-menu-content-available-height) origin-(--radix-context-menu-content-transform-origin)\", className)} {...props} />\n    </ContextMenuPortal>\n  );\n}\n\nexport {\n  ContextMenu,\n  ContextMenuCheckboxItem,\n  ContextMenuContent,\n  ContextMenuGroup,\n  ContextMenuItem,\n  ContextMenuLabel,\n  ContextMenuPortal,\n  ContextMenuRadioGroup,\n  ContextMenuRadioItem,\n  ContextMenuSeparator,\n  ContextMenuShortcut,\n  ContextMenuSub,\n  ContextMenuSubContent,\n  ContextMenuSubTrigger,\n  ContextMenuTrigger,\n};\n"
    }
  ]
}
