{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "popover",
  "type": "registry:ui",
  "title": "Popover",
  "description": "Floating panel anchored to a trigger — for pickers, menus, and contextual forms.",
  "dependencies": [
    "@radix-ui/react-popover",
    "@saasflare/ui",
    "motion"
  ],
  "files": [
    {
      "path": "components/ui/popover.tsx",
      "type": "registry:ui",
      "content": "// @toreview\n\"use client\"\n\n/**\n * @fileoverview Popover — premium animated popover with Motion spring entrance for tooltips, menus, and floating content panels.\n * @module packages/ui/components/ui/popover\n * @layer core\n *\n * @component\n * @example\n * import { Popover, PopoverTrigger, PopoverContent } from '@saasflare/ui';\n *\n * <Popover>\n *   <PopoverTrigger>Open</PopoverTrigger>\n *   <PopoverContent>\n *     <p>Popover content here.</p>\n *   </PopoverContent>\n * </Popover>\n */\n\nimport * as React from \"react\"\nimport { m } from \"motion/react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\nimport { cn } from \"@saasflare/ui\"\nimport { useSaasflareProps, type SaasflareComponentProps } from \"@saasflare/ui\"\nimport { useSaasflareMotion, springBouncy } from \"@saasflare/ui\"\n\n/**\n * Floating content panel anchored to a trigger element, opened on click.\n * Root of the composition — owns open state and wires {@link PopoverTrigger},\n * {@link PopoverAnchor}, and {@link PopoverContent} together. Use for small\n * interactive panels (filters, pickers, inline forms); for hover-only previews\n * reach for HoverCard.\n *\n * @component\n * @layer core\n */\nfunction Popover({\n  ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n  return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\n/**\n * Button that toggles the popover open and closed. Also serves as the\n * positioning anchor unless a {@link PopoverAnchor} is rendered.\n *\n * @component\n * @layer core\n */\nfunction PopoverTrigger({\n  ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n  return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\n}\n\n/**\n * Optional element the popover content positions against instead of the\n * trigger.\n *\n * @component\n * @layer core\n */\nfunction PopoverAnchor({\n  ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n  return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />\n}\n\n/**\n * Props for {@link PopoverContent}. Extends the Radix Popover content props\n * with the Saasflare theming axes (`surface`, `radius`, `animated`,\n * `iconWeight`).\n */\ninterface PopoverContentProps\n  extends Omit<React.ComponentProps<typeof PopoverPrimitive.Content>, keyof SaasflareComponentProps>,\n    SaasflareComponentProps {}\n\n/**\n * The floating panel rendered while the popover is open. Portals to the body,\n * enters with a spring scale/fade, and resolves `surface`/`radius`/`animated`\n * against the <SaasflareProvider> context.\n *\n * @component\n * @layer core\n */\nfunction PopoverContent({\n  className,\n  align = \"center\",\n  sideOffset = 4,\n  surface,\n  radius,\n  animated,\n  iconWeight,\n  ...props\n}: PopoverContentProps) {\n  const sf = useSaasflareProps({ surface, radius, animated, iconWeight })\n  const motion = useSaasflareMotion(sf.animated, springBouncy)\n\n  return (\n    <PopoverPrimitive.Portal>\n      <PopoverPrimitive.Content\n        {...props}\n        data-slot=\"popover-content\"\n        align={align}\n        sideOffset={sideOffset}\n        asChild\n      >\n        <m.div\n          data-surface={sf.surface}\n          data-radius={sf.radius}\n          data-animated={String(sf.animated)}\n          initial={motion.disabled ? false : { opacity: 0, scale: 0.95, y: -4 }}\n          animate={{ opacity: 1, scale: 1, y: 0 }}\n          exit={motion.disabled ? undefined : { opacity: 0, scale: 0.95, y: -4 }}\n          transition={motion.transition}\n          className={cn(\n            \"z-50 w-72 origin-[var(--radix-popover-content-transform-origin)] rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden\",\n            className\n          )}\n        />\n      </PopoverPrimitive.Content>\n    </PopoverPrimitive.Portal>\n  )\n}\n\n/** Props for {@link PopoverArrow}. Pure pass-through to the Radix Popover arrow. */\ninterface PopoverArrowProps\n  extends React.ComponentProps<typeof PopoverPrimitive.Arrow> {}\n\n/**\n * Triangular arrow pointing from the popover toward its trigger.\n *\n * Renders inside `<PopoverContent>` (consumes Popper context), so it must be a\n * child of the content panel — rendering it elsewhere positions incorrectly.\n * Position/rotation are computed by Radix from the resolved `side`/`align`; no\n * props are required by default. Fill follows the `bg-popover` token via\n * `fill-popover` so it inherits palette + light/dark automatically. The 1px\n * popover border is not auto-continued onto the arrow (Radix limitation, same\n * as shadcn) and the arrow fill stays token-fixed under non-default\n * `surface` overrides — pass a `className` to adjust either if needed.\n *\n * @component\n * @layer core\n * @example\n * <PopoverContent>\n *   <PopoverArrow />\n *   <p>Popover content here.</p>\n * </PopoverContent>\n */\nfunction PopoverArrow({ className, ...props }: PopoverArrowProps) {\n  return (\n    <PopoverPrimitive.Arrow\n      data-slot=\"popover-arrow\"\n      width={12}\n      height={6}\n      className={cn(\"fill-popover\", className)}\n      {...props}\n    />\n  )\n}\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverArrow, type PopoverContentProps, type PopoverArrowProps }\n",
      "target": "components/ui/popover.tsx"
    }
  ],
  "$meta": {
    "source": "https://ui.saasflare.io/r/popover.json"
  }
}
