Anchored content preview on hover or keyboard focus — Radix
HoverCard equivalent. Trigger is an <a>;
the floating panel reveals after openDelay (default
700ms) with a SafePolygon bridging trigger and content so the
pointer can travel without dismissing. Non-modal, no-op on touch
(navigates the link directly).
trace
{#if trace.length === 0}
hover the link to see events
{:else}
{#each trace.slice(0, 3) as entry (entry.at)}
{entry.event} · {entry.family}{entry.intent ? ' · ' + entry.intent : ''}{fmtTime(entry.at)}
{/each}
{/if}
open {String(open)}
{#if tab === 'live'}
Controls
Soma owns the hover-bridge polygon, open/close timing and dismissal. Eidos adds size on Content (xs..xl). Trigger is rendered as <a>; on touch the preview is a no-op and the link follows.
Hover-close delay (ms). Corridor for pointer to traverse to content.
disabled
boolean
false
Hover/focus do not open the preview.
Trigger
Prop
Type
Default
Description
id
string
auto
—
…native anchor attrs
PrimitiveAnchorAttributes
—
Renders an <a>; all HTML anchor attrs (href, target, rel) flow through.
child
{`Snippet<[{ props }]>`}
—
Opt out of the default <a> and render your own element (e.g. button-triggered hover-card).
Content
Prop
Type
Default
Description
size eidos
ResponsiveProp<'xs' | 'sm' | 'md' | 'lg' | 'xl'>
'md'
Visual size — padding, min-width, font-size.
side
'top' | 'right' | 'bottom' | 'left'
'top'
Side of the trigger.
align
'start' | 'center' | 'end'
'center'
Alignment along the side.
sideOffset
number
8
Distance from trigger.
alignOffset
number
0
Offset along the alignment axis.
avoidCollisions
boolean
true
Flip / shift to avoid viewport edges.
collisionBoundary
Boundary | Boundary[]
[]
Custom boundary element(s).
collisionPadding
number | Record<Side, number>
0
Padding from boundaries.
sticky
'partial' | 'always'
'partial'
Sticking behavior on scroll.
hideWhenDetached
boolean
true
Hide when trigger leaves the viewport.
customAnchor
string | HTMLElement | Measurable | null
—
Anchor to a different element/rect than the trigger.
forceMount
boolean
false
Keep in DOM when closed (for external animation).
{/if}
{#if tab === 'morfo'}
morfo
· declarative contract
Source: src/uix/morfo/components/link-preview.ts.
Trigger emits the hover/focus events; Content stamps
data-state and data-side via the
Floating layer.
Selectors at src/uix/eidos/components/link-preview/link-preview.css.
Trigger paints the <a> directly (underline + hover/open color shift)
— it does NOT render as <Button> like other triggers, because
link previews are navigational anchors rather than action controls.
LinkPreview is decorative for assistive tech — the content
panel is sighted-user enhancement, not a primary information
channel. Screen readers should rely on the link's accessible
name (and surrounding context) to convey the destination. The
preview opens on keyboard focus too so sighted-keyboard users
get the affordance.
Keyboard
Key
Action
Tab
Focus the trigger — preview opens after a short delay (skips on initial mount).
Escape
Close the preview, focus stays on trigger.
Enter
Follow the link's href (native anchor behavior).
Pointer
Gesture
Behavior
Hover trigger
After openDelay (700ms default) the preview opens.
Leave trigger toward content
SafePolygon bridges the gap; preview stays open while pointer is in the triangle.
Leave both
After closeDelay (300ms default) the preview closes.
Touch
No preview — the link is followed directly. Avoids modal hover-trap on mobile.