Pathfinderby Commenda
Components

Popover

Compact anchored forms and read-only previews.

Import Popover and optional PopoverGroup from @commenda/pathfinder/popover.

API reference

PropTypeBehavior
modeConditional"form"|"preview"form; click versus hover/focus
triggerRequiredReactElement<any, string | React.JSXElementConstructor<any>>Required; forward native props/ref
titleRequiredstringRequired accessible heading
descriptionReactNodeSupporting text and content
childrenRequiredReactNodeSupporting text and content
positionConfigObjectView fieldsbottom / start, collision-aware
openConditionalbooleanApplication can control opening
defaultOpenbooleanApplication can control opening
onOpenChangeConditional(open: boolean) => voidApplication can control opening
footerConfigOverlayFooterConfigView fieldsForm only
focusConfigOverlayFocusConfigView fieldsForm only
loadingConfigObjectView fieldsPreview only
classNamestringPopup classes
positionConfigObject fields
FieldTypeRequirement
side"top" | "bottom" | "left" | "right"Optional
align"start" | "end" | "center"Optional
footerConfigObject fields
FieldTypeRequirement
primaryActionOverlayActionOptional
secondaryActionOverlayActionOptional
leadingContentReactNodeOptional
cancelLabelstringOptional
focusConfigObject fields
FieldTypeRequirement
initialFocusRefRefObject<HTMLElement | null>Optional
returnFocusRefRefObject<HTMLElement | null>Optional
loadingConfigObject fields
FieldTypeRequirement
isLoadingbooleanRequired
labelstringOptional

Forms use Base UI Popover; previews use PreviewCard. Width is 320px, clamped to the viewport; offset is 4px, radius 10px. Use Dialog or Sheet for longer tasks. Form footer actions have the same shape as Dialog, including native form submission. Cancel closes; primary actions stay open until the application closes them.

Preview recipes

Entity, record, file, and person previews compose existing components. Keep them read-only. The trigger stays a real link and touch activation follows its destination. General previews allow one destination; the Figma person recipe permits up to two. Preview hover open and close delays are 150ms; keyboard focus also opens the preview without moving focus into it.

Loading

Applications own fetching, cancellation, errors, and cached data. Skeletons match the content area and announce the loading state.

Dialog and Sheet provide a local scope automatically. Wrap page siblings with PopoverGroup to ensure opening one closes another; standalone popovers remain independent. Controlled callers must honor onOpenChange(false). There is no global singleton or required app provider. Read the overlay rules.

Design rules

Figma guidance and reviewed implementation decisions for this component. Rule IDs remain stable for source comments and AI references.

Popover

  • POPOVER-001: Width320, radius10, menu shadow, 0.5px pearl300 edge, offset4, no backdrop. Form header16px start/8px end, top12/bottom4; content16px horizontal, footer12px vertical. Forms contain one or two fields; use larger surfaces for longer tasks.
  • POPOVER-002: Read-only previews open/close after150ms hover delays and support keyboard focus. Keep trigger destination on touch. No edit controls in hover previews. Person permits two links as an explicit exception to the general one-link recommendation.
  • POPOVER-003: Coordinate within the nearest local overlay/PopoverGroup. Fetching, caching, loading, permissions and application state remain outside the component.

Motion and edge cases

Occasional overlays use motion for spatial consistency. Motion paths and timings follow Kakashi: Dialog fades and moves from 95% scale with a 2% vertical offset in 200ms both ways; Popover fades from 95% scale and an 8px offset toward its trigger in 150ms both ways. Popover direction follows the resolved placement after collision handling. Right Sheet slides in for 500ms and out for 300ms; bottom Sheet slides for 500ms both ways. Sheet panels do not fade during normal motion, and modal backdrops follow the panel duration.

Pathfinder retains its foundation ease-out curve for Dialog/Popover and drawer curve (0.32,0.72,0,1) for Sheets. These are deliberate curve choices; this is not a copy of Kakashi’s legacy Radix keyframe implementation. Base UI continues to own presence, focus and dismissal. Transitions use a single transform value plus opacity where relevant, so Tailwind v4’s separate scale/translate properties cannot bypass interpolation. Closing or reopening mid-transition reverses from the current rendered position.

Keyboard opening and dismissal remain immediate, including Close and Cancel activation. Reduced motion removes scale and translation: Dialog/Popover keep their fade, while Sheets change position immediately and their modal backdrop can fade. Drag writes only the popup transform, never layout or inherited animation variables. Programmatic openings animate by default; explicit keyboard interactions suppress motion.

On this page