Skip to content

PreviewCard

PreviewCard is a lookless ContentControl whose Content is the trigger and whose PreviewContent is the hover-revealed panel; it is the WPF port of the web family née HoverCard. Unlike Popover it is non-modal end to end: it never traps or moves focus, matching the web’s MoveFocusInside = false. Opening and closing are driven by hover-intent timers (OpenDelay, CloseDelay) shared between the trigger and the popup content, so the pointer can travel from one to the other without the card closing.

xmlns:navius="clr-namespace:Navius.Wpf.Primitives.Controls;assembly=Navius.Wpf.Primitives"
<navius:NaviusPreviewCard Side="Bottom" OpenDelay="600" CloseDelay="300">
<navius:NaviusButton Content="@navius" />
<navius:NaviusPreviewCard.PreviewContent>
<StackPanel>
<TextBlock Text="Navius" FontWeight="Bold" />
<TextBlock Text="A Blazor-native design system." />
</StackPanel>
</navius:NaviusPreviewCard.PreviewContent>
</navius:NaviusPreviewCard>

Like Popover, no NaviusOverlayLayer is required: PreviewCard hosts its panel through a native Popup (NaviusAnchoredPopup) and pushes directly onto OverlayStack.GetFor(window).

Property Type Default From Description
PreviewContent object? null NaviusPreviewCard Content of the preview panel.
Side PlacementSide Bottom NaviusPreviewCard Which side of the trigger the panel is placed against.
Align PlacementAlign Center NaviusPreviewCard Cross-axis alignment relative to the trigger.
SideOffset double 6 NaviusPreviewCard Gap, in DIPs, between the trigger and the panel along Side.
AlignOffset double 0 NaviusPreviewCard Offset, in DIPs, along the cross axis.
OpenDelay int 600 NaviusPreviewCard Hover-intent delay, in ms, before the card opens.
CloseDelay int 300 NaviusPreviewCard Grace delay, in ms, before the card closes after the pointer leaves or focus moves away.
IsOpen bool false NaviusPreviewCard Open state. Two-way bindable by default.
Content object - ContentControl The trigger.

There is no Modal property at all (not even a dead always-false one): the web contract hardcodes Modal to false for this family and nothing in the WPF port reads a PreviewCard-specific value.

Key Behavior
Focus (Tab into the trigger) Opens immediately (GotKeyboardFocus), with no OpenDelay.
Blur (Tab out of the trigger) Starts the close-delay timer (LostKeyboardFocus).
Escape Closes immediately via the shared OverlayStack Escape routing (CloseOnEscape is set true when the session opens); there is no dedicated key handler in this family, unlike Tooltip.

Pointer enter on the trigger starts the open-delay timer (or opens immediately if already open); pointer leave on the trigger or the popup content starts the close-delay timer; pointer enter on the popup content cancels a pending close, letting the pointer travel from trigger to card without flicker. These are pointer, not keyboard, interactions, but share the same timer state machine.

NaviusPreviewCard does not override OnCreateAutomationPeer and applies no AutomationProperties to its popup content: the web contract itself has no role or Title/Description parts for this family, and focus never moves into the card (MoveFocusInside is effectively false, matched by TrapFocus = false/RestoreFocus = false when the session is pushed), so the trigger keeps focus throughout the entire hover interaction. The unit suite (PreviewCardTests.cs) exercises the hover-intent timers, the shared open/close state machine between the trigger and the popup content, and the non-modal, non-restoring session options.

  • Trigger and Positioner collapse onto the root control, the same pattern as Popover; there is no separate NaviusPreviewCardBackdrop (the web contract itself notes it is “rarely used since preview cards are non-modal”).
  • Modal is dropped entirely rather than kept as a dead always-false property, since OverlayOptions.Modal already defaults to false and nothing reads a PreviewCard-specific flag.
  • The trigger and the popup content share one hover-intent state machine (a single DispatcherTimer pair) on the control instance, mirroring the web’s pointer-enter/leave callbacks wired on both the Trigger and the Popup so the “stay open while hovering the card itself” behavior carries over.
  • The trigger is rendered as a focusable Border template part rather than a true Hyperlink/Button-style element; it still supports Tab stops and GotKeyboardFocus/LostKeyboardFocus.
  • No arrow glyph in the default template, the same NaviusAnchoredPopup limitation as Popover/Tooltip.
  • No cancelable dismiss callbacks are exposed as public events.
  • Known residual (M6 audit): GotKeyboardFocus stops the pending open timer and opens immediately, but does not stop a pending close timer. If focus arrives while a CloseDelay close is already pending (e.g. the pointer just left the trigger), the card can open and then still be closed by the still-running close timer. Low severity, not covered by any current test.

The PreviewCard Gallery page rendered at the pinned commit, in each theme.

PreviewCard Gallery page in the light theme

PreviewCard Gallery page in the dark theme

PreviewCard Gallery page in the high contrast theme