{
  "name": "Popover",
  "source": "src/components/Popover.tsx",
  "propsType": "PopoverProps",
  "description": "Popover — Figma `Popover` (825:1853).\n\nSITS BETWEEN TOOLTIP AND MODAL. A tooltip is a hint that cannot hold\nfocusable content; a modal is a task that takes over the page. A popover\nholds interactive content but stays attached to the control that opened it.\n\n`usePopover` contains focus, closes on Escape or an outside click, and hides\nthe rest of the page from assistive tech while open — the same guarantees\nModal gives. What differs is the framing, and it is deliberate: no visible\nscrim, anchored to its trigger, and `surface/raised` rather than Modal's\n`surface/overlay`. It reads as attached to the page rather than replacing it.",
  "import": "import { Popover } from 'ionbase-ui';",
  "status": "stable",
  "summary": "An anchored panel that holds interactive content. Sits between Tooltip and Modal.",
  "useWhen": [
    "the content is interactive — a form, a filter, a list of actions — but should stay attached to the control that opened it",
    "the surrounding page should stay visible and in context"
  ],
  "useInstead": [
    {
      "when": "the content is a short hint with nothing focusable in it",
      "use": "Tooltip",
      "why": "a tooltip cannot be focused or scrolled and closes when the pointer leaves"
    },
    {
      "when": "the task takes over the page or must be completed before anything else",
      "use": "Modal"
    },
    {
      "when": "you only need the list surface and will position it yourself",
      "use": "Menu"
    }
  ],
  "variants": {
    "placement": {
      "top": {
        "use": "above the trigger"
      },
      "bottom": {
        "use": "below the trigger — the usual choice for a control in a header"
      },
      "left": {
        "use": "to the left of the trigger"
      },
      "right": {
        "use": "to the right of the trigger"
      }
    },
    "size": {
      "sm": {
        "use": "a couple of actions or one short field"
      },
      "md": {
        "use": "the default"
      },
      "lg": {
        "use": "a small form or a filter panel"
      }
    }
  },
  "slots": {
    "children": {
      "accepts": "Button",
      "note": "the trigger. Must forward both a ref and DOM props — every component in this library does"
    },
    "content": {
      "accepts": "any"
    },
    "title": {
      "accepts": "text",
      "note": "also gives the dialog its accessible name"
    },
    "footer": {
      "accepts": "Button",
      "note": "action row, right-aligned"
    }
  },
  "a11y": {
    "role": "dialog",
    "guarantees": [
      "focus is contained while open, Escape and outside clicks close it, and the rest of the page is hidden from assistive tech",
      "`placement` is a preference, not a guarantee — it flips when there is no room, and the arrow follows"
    ],
    "requires": [
      "`title`, or `aria-label` on the popover — a dialog with no name announces nothing about what opened"
    ],
    "notes": [
      "`placement` names where the POPOVER sits, not where the arrow points."
    ]
  },
  "antiPatterns": [
    {
      "dont": "a function-component trigger that drops its ref",
      "why": "it renders, but the popover has nothing to position against"
    },
    {
      "dont": "using a Popover where a Modal belongs",
      "why": "a popover closes on an outside click; a task that must be finished should not be dismissible by a stray click"
    },
    {
      "dont": "nesting a Popover inside another Popover",
      "why": "two overlapping focus containments, and dismissing the outer one takes the inner one with it"
    }
  ],
  "stylesheet": "src/styles/popover.css",
  "tokens": [
    "--border-subtle",
    "--border-width-default",
    "--border-width-thick",
    "--font-family-sans",
    "--font-weight-medium",
    "--font-weight-regular",
    "--icon-secondary",
    "--icon-size-md",
    "--ion-duration-base",
    "--ion-ease-out",
    "--ion-popover-width",
    "--ion-shadow-shadow-lg",
    "--radius-md",
    "--radius-sm",
    "--ring-focus",
    "--spacing-12",
    "--spacing-16",
    "--spacing-32",
    "--spacing-8",
    "--surface-hover",
    "--surface-raised",
    "--text-default",
    "--text-secondary",
    "--type-body",
    "--type-body-line-height",
    "--type-body-sm",
    "--type-body-sm-line-height"
  ],
  "props": {
    "children": {
      "type": "React.ReactElement<unknown, string | React.JSXElementConstructor<any>>",
      "required": true,
      "origin": "own",
      "description": "The element that opens it. Must accept a ref and DOM props."
    },
    "content": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Panel contents."
    },
    "title": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Heading. Also gives the dialog its accessible name."
    },
    "footer": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Action row, right-aligned."
    },
    "placement": {
      "type": "PopoverPlacement | undefined",
      "required": false,
      "origin": "own",
      "description": "Matches the Figma `Placement` variant, and names where the POPOVER sits —\nnot where the arrow points. A preference, not a guarantee: it flips when\nthere is no room, and the arrow follows.",
      "values": [
        "top",
        "bottom",
        "left",
        "right"
      ]
    },
    "size": {
      "type": "PopoverSize | undefined",
      "required": false,
      "origin": "own",
      "description": "Matches the Figma `Size` variant. Widths only; height always hugs.",
      "values": [
        "sm",
        "md",
        "lg"
      ]
    },
    "showClose": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own",
      "description": "Show the close button. Defaults to `true`."
    },
    "hideArrow": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own",
      "description": "Hide the caret."
    },
    "closeLabel": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    },
    "isOpen": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "onOpenChange": {
      "type": "((isOpen: boolean) => void) | undefined",
      "required": false,
      "origin": "own"
    },
    "className": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    }
  },
  "propCounts": {
    "own": 12,
    "aria": 0,
    "dom": 0,
    "other": 0
  }
}
