Popover
Attach interactive supporting content to a trigger without blocking the page.
Usage
Anchored
Keep the popup attached to its trigger while the surrounding layout changes.
Keep the popup attached to its trigger while the surrounding layout changes.
<!-- Popover / Anchored -->
<script setup lang="ts">
import { PopoverRoot, PopoverTrigger, PopoverContent, PopoverArrow, PopoverTitle, PopoverDescription, PopoverClose } from '@sectile/vue/popover'
import { TextField } from '@sectile/vue/text'
</script>
<template>
<PopoverRoot side="bottom" align="center" :close-on-interact-outside="false">
<PopoverTrigger>Edit profile</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverTitle>Profile details</PopoverTitle>
<PopoverDescription>Change the public display name.</PopoverDescription>
<label>Display name <TextField default-value="Sectile" /></label>
<PopoverClose>Save changes</PopoverClose>
</PopoverContent>
</PopoverRoot>
</template>Controlled
Let the parent own the current value and apply accepted changes back to the component.
Let the parent own the current value and apply accepted changes back to the component.
<!-- Popover / Controlled -->
<script setup lang="ts">
import { PopoverRoot, PopoverTrigger, PopoverContent, PopoverArrow, PopoverTitle, PopoverDescription, PopoverClose } from '@sectile/vue/popover'
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<PopoverRoot v-model:open="open" side="bottom" align="center">
<PopoverTrigger>Edit profile</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverTitle>Profile details</PopoverTitle>
<PopoverDescription>Change the public display name.</PopoverDescription>
<PopoverClose>Save changes</PopoverClose>
</PopoverContent>
</PopoverRoot>
</template>Examples
Collision
Flip or shift the popup when its preferred side would leave the viewport.
Flip or shift the popup when its preferred side would leave the viewport.
<!-- Popover / Collision -->
<script setup lang="ts">
import { PopoverRoot, PopoverTrigger, PopoverContent, PopoverArrow, PopoverTitle, PopoverDescription, PopoverClose } from '@sectile/vue/popover'
</script>
<template>
<PopoverRoot
side="right"
align="center"
:collision-padding="16"
:avoid-collisions="true"
:close-on-interact-outside="false"
>
<PopoverTrigger>Edit profile</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverTitle>Profile details</PopoverTitle>
<PopoverDescription>Flip or shift when space runs out.</PopoverDescription>
<PopoverClose>Done</PopoverClose>
</PopoverContent>
</PopoverRoot>
</template>Outside interaction
closeOnInteractOutside controls whether a pointer interaction outside the content closes it. Elements in interactOutsideExclusions stay interactive in a modal and do not count as outside. For conditional decisions, call preventDefault() from the interact-outside event.
<PopoverRoot
:interact-outside-exclusions="[ignoredElement]"
@interact-outside="(event) => {
if (event.isInside(temporarilyIgnoredElement)) event.preventDefault()
}"
/>Floating positioning
This component uses the shared positioning engine. Use the live positioning example to change side, align, offsets, collision boundaries, strategy, and tracking while inspecting the resolved placement.
API
Vue package: @sectile/vue/popover
PopoverRootPopoverTriggerPopoverAnchorPopoverPortalPopoverContentPopoverTitlePopoverDescriptionPopoverClosePopoverArrow
Props
PopoverRootProps
alignAlignment of positioned content relative to its anchor.
arrowPaddingMinimum space kept between an arrow and the edge of positioned content.
autoFocusWhether focus moves into the component when it opens.
avoidCollisionsWhether positioned content may flip or shift to remain visible.
closeOnInteractOutsideWhether interaction outside the content closes it.
collisionBoundaryBoundary used to keep positioned content visible.
collisionPaddingSpace kept between positioned content and its collision boundary.
defaultOpenInitial uncontrolled open state.
disabledWhether interaction is unavailable.
hideWhenDetachedWhether positioned content hides when its anchor leaves the layout.
initialFocusElement or resolver that receives focus when the component opens.
interactOutsideExclusionsElements that stay interactive and do not count as outside interaction.
labelAccessible name announced for the control.
modalWhether open content blocks interaction with the surrounding page.
openWhether the associated popup or disclosure is open.
positionWhether the popup is positioned relative to its trigger.
restoreFocusWhether focus returns to the trigger when open content closes.
sidePreferred side of the anchor for positioned content.
sideOffsetDistance between positioned content and its anchor.
strategyCSS positioning strategy used for anchored content.
trackingUpdate strategy used while anchored content is open.
trapFocusWhether keyboard focus stays inside open content.
unmountOnExitWhether presence-managed content is removed from the DOM after its exit motion completes.
PopoverPartProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
PopoverPortalProps
deferWhether Teleport target resolution waits until the end of the current mount or update tick.
disabledWhether interaction is unavailable.
toTeleport target for portalled content.
Slots
PopoverRootSlotProps
disabledWhether interaction is unavailable.
openWhether the associated popup or disclosure is open.
Other types
PopoverOpenChangeHandler
type PopoverOpenChangeHandler = PopupFactoryOptions['onOpenChange']PopoverInteractOutsideHandler
type PopoverInteractOutsideHandler = NonNullable<PopupFactoryOptions['onInteractOutside']>Parts
Shared scope: [data-scope="popover"]. Combine it with a part selector to keep styles local to this component.
| Part | Selector | Role | Extra attributes |
|---|---|---|---|
trigger | [data-part="trigger"] | Opens, closes, or activates the associated content. | — |
anchor | [data-part="anchor"] | Provides the positioning reference for floating content. | — |
content | [data-part="content"] | Contains the component content shown for the active state. | — |
title | [data-part="title"] | Labels the associated content. | — |
description | [data-part="description"] | Describes the associated content or decision. | — |
close | [data-part="close"] | Closes or dismisses the current surface. | — |
arrow | [data-part="arrow"] | Visually connects floating content to its anchor. | — |
Keyboard interaction
| Key | Behavior |
|---|---|
| Enter / Space | Activate the trigger or focused action. |
| Tab / Shift+Tab | Move through available controls; modal content keeps focus inside. |
| Escape | Close the popup and restore focus when configured. |
Accessibility
The trigger exposes expanded state and popup ownership; optional title and description label the floating content.
See the corresponding WAI-ARIA pattern for the host accessibility contract.
