{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "hover-card", "type": "registry:ui", "title": "Hover Card", "files": [ { "path": "ui/hover-card.tsrx", "type": "registry:ui", "target": "components/ui/hover-card.tsrx", "content": "// Base UI base hover-card — runs on @octanejs/base-ui's `PreviewCard`, which is Base UI's name for\n// this family. Class strings from the maintainer-supplied radix source.\n//\n// THE OPEN/CLOSED DIALECT HAD TO BE REWRITTEN, and this is the one that would have failed loudest.\n// The radix source for this family uses the OLDER spelling — `data-[state=open]:animate-in`,\n// `data-[state=closed]:animate-out` — where the other menu families in this base use `data-open:`.\n// Base UI publishes NO `data-state` attribute at all (verified by rendering an open card and\n// querying for one: there is none). Copied across, every entry and exit utility would match nothing\n// and the card would pop in and out with no animation whatsoever.\n//\n// data-[state=open]:… -> data-open:…\n// data-[state=closed]:… -> data-closed:…\n//\n// The transform-origin variable is renamed for the same reason as every other overlay here:\n// `--radix-hover-card-content-transform-origin` -> `--transform-origin`.\n//\n// PART TREE. Radix has Portal > Content; Base UI splits positioning into its own layer, the same\n// shape this base's popover and dropdown-menu use:\n//\n// radix Root > Portal > Content\n// Base UI Root > Portal > Positioner > Popup\n//\n// Positioning props are therefore destructured and forwarded to the Positioner. Swept onto `Popup`\n// by a rest spread they are inert — `side=\"top\"` would silently leave the card on its default side\n// and also land on the DOM as an invalid attribute.\nimport { createElement } from 'octane';\nimport { PreviewCard as PreviewCardPrimitive } from '@octanejs/base-ui/preview-card';\n\nimport { cn } from '@/lib/utils';\n\nexport interface BaseUiPositioningProps {\n\t/** Forwarded to the Positioner; see the note at the top of this file. */\n\tside?: 'top' | 'right' | 'bottom' | 'left';\n\tsideOffset?: number;\n\talign?: 'start' | 'center' | 'end';\n\talignOffset?: number;\n\tanchor?: unknown;\n\tpositionMethod?: 'absolute' | 'fixed';\n\tcollisionBoundary?: unknown;\n\tcollisionPadding?: unknown;\n\tcollisionAvoidance?: unknown;\n\tarrowPadding?: number;\n\tsticky?: boolean;\n\tdisableAnchorTracking?: boolean;\n}\n\nexport function HoverCard(props: Record) @{\n\t\n}\n\nexport function HoverCardTrigger(props: Record) @{\n\t\n}\n\nexport interface HoverCardContentProps extends Record, BaseUiPositioningProps {\n\tclassName?: string;\n}\n\nexport function HoverCardContent({\n\tclassName,\n\talign = 'center',\n\tsideOffset = 4,\n\tside,\n\talignOffset,\n\tanchor,\n\tpositionMethod,\n\tcollisionBoundary,\n\tcollisionPadding,\n\tcollisionAvoidance,\n\tarrowPadding,\n\tsticky,\n\tdisableAnchorTracking,\n\t...props\n}: HoverCardContentProps) {\n\treturn createElement(PreviewCardPrimitive.Portal, {\n\t\t'data-slot': 'hover-card-portal',\n\t\tchildren: createElement(PreviewCardPrimitive.Positioner, {\n\t\t\talign,\n\t\t\tsideOffset,\n\t\t\tside,\n\t\t\talignOffset,\n\t\t\tanchor,\n\t\t\tpositionMethod,\n\t\t\tcollisionBoundary,\n\t\t\tcollisionPadding,\n\t\t\tcollisionAvoidance,\n\t\t\tarrowPadding,\n\t\t\tsticky,\n\t\t\tdisableAnchorTracking,\n\t\t\tchildren: createElement(PreviewCardPrimitive.Popup, {\n\t\t\t\t'data-slot': 'hover-card-content',\n\t\t\t\tclassName: cn(\n\t\t\t\t\t'z-50 w-64 origin-(--transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95',\n\t\t\t\t\tclassName,\n\t\t\t\t),\n\t\t\t\t...props,\n\t\t\t}),\n\t\t}),\n\t});\n}\n" } ], "dependencies": [ "@octanejs/base-ui@0.1.36" ], "registryDependencies": [ "@octane/utils" ] }