id: popover
label: Popover
family: family-a-overlay
category: Overlay
intent: Show contextual floating content
description: Floating popover component
composable: true
capabilities: OpenClose, FocusTrap
required_parts: ["PopoverTrigger", "PopoverContent"]
optional_parts: []
tags: ["popover", "floating", "tooltip", "overlay", "context"]
keywords:
pain: Popovers lose sync between trigger state and content visibility
promise: Trigger and content visibility governed by shared state contract
why: |
PopoverPrimitive uses VisibilityState across trigger and content. ARIA attributes and positioning are derived automatically. This guarantees consistent overlay behavior without manual sync.
rules: ["CR-001", "CR-004"]
use_cases: ["context actions", "tooltips with actions"]
related: ["dialog", "alert_dialog", "drawer", "sheet", "modal", "confirm_dialog", "tooltip", "hover_card"]
file: popover_ui.css
tokens: popover-*, space-*, radius-*, shadow-*, motion-*
foundation: spacing, radius, shadow, motion
states: ["open", "closed"]
island: popover_boundary.rs
pillar: overlay
badges: ["SSR Safe", "Hydration Safe", "Token Driven", "Deterministic API", "Zero Drift", "Island Architecture"]
before: |
// ❌ Typical
view! {
<button on:click=toggle>"Open"</button>
{if open { view! { <div>"Popover"</div> } }}
}
after: |
// ✅ CanonRS
view! {
<Popover>
<button data-rs-popover-trigger="">"Open"</button>
<PopoverContent>"Popover"</PopoverContent>
</Popover>
}
boundary_type: interaction
ix_group: ix_overlay
block: []
blocks_primitives: [stack]