Presence
Headless Presence; covers CSS animations, CSS transitions, View Transitions.
| Package | @vizejs/ui/presence |
| Maturity | stable |
| Own the source | vize lib pull presence |
| Requires | — |
| Aliases | enter exit, mount animation, presence |
| Covers | CSS animations, CSS transitions, View Transitions |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/ui
Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.
import { Presence } from "@vizejs/ui/presence";
Or copy the source into your project with vize lib pull presence (see Source Distribution).
Try it
This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.
Open the interactive example · Styling these components
Copy the example
<!-- Presence host that mounts and unmounts details through explicit enter and exit phases. -->
<script setup lang="ts">
import { nextTick, ref, useId, useTemplateRef } from "vue";
import { Presence } from "@vizejs/ui/presence";
const open = ref(false);
const detailsId = useId();
const presence = useTemplateRef<InstanceType<typeof Presence>>("presence");
async function toggle(): Promise<void> {
open.value = !open.value;
await nextTick();
// No CSS animation is attached here, so finish the phase explicitly.
presence.value?.completeAnimation();
}
</script>
<template>
<div>
<button type="button" :aria-expanded="open" :aria-controls="detailsId" @click="toggle">
Shipping details
</button>
<Presence ref="presence" :present="open">
<template #default="{ status }">
<p :id="detailsId" :data-status="status">Orders ship within two business days.</p>
</template>
</Presence>
</div>
</template>
API
Presence
Source: src/families/overlays/presence/presence.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
present |
boolean |
false |
Whether the content should occupy the tree. |
forceMount |
boolean |
false |
Keep the slot mounted even while presence would otherwise unmount it. |
respectReducedMotion |
boolean |
true |
Skip enter and exit animation when prefers-reduced-motion: reduce matches. |
motion |
"fade" | "scale" | "slide" |
undefined |
Named enter/exit recipe published on data-vize-motion, pairing the host with the packaged motion stylesheet (@vizejs/ui/motion). |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
{ readonly present: boolean; readonly status: PresenceStatus } |
Present contents. Receives presence status for styling hooks. |
Exposed
| Member | Type | Description |
|---|---|---|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
isPresent |
— | |
status |
— | |
completeAnimation |
— |
Behavior
Normative state × input → outcome table for presence.vue (@vizejs/ui/presence).
Every row is proven by the named test in
src/families/overlays/presence/presence.test.ts or
src/families/overlays/presence/presence-ssr.test.ts; compile-only assertions
live in src/families/overlays/presence/presence.types.test-d.ts.
| # | State | Input | Outcome | Proven by |
|---|---|---|---|---|
| P1 | unmounted | present=false render |
slot stays unmounted | keeps unmounted content out of the tree |
| P2 | unmounted | present becomes true |
host mounts in entering until completion |
enters through an explicit completion step |
| P3 | entering | completeAnimation or host animationend |
status becomes present |
enters through an explicit completion step |
| P4 | present | present becomes false |
status becomes exiting and the host stays mounted |
exits through an explicit completion step |
| P5 | exiting | completeAnimation |
host unmounts | exits through an explicit completion step |
| P6 | entering | present becomes false before completion |
enter is canceled and the host unmounts | cancels an in-flight enter |
| P7 | any | reduced motion | enter and exit skip to the terminal phase | skips motion when the user prefers it |
| P8 | unmounted | forceMount |
slot stays mounted with unmounted status |
force-mounts hidden content |
| P9 | present | render | exposed element is the rendered node |
exposes the rendered element for composition |
| P10 | SSR | present=true |
byte-identical markup starts in present |
SSR test |
| P11 | public types | invalid status or mutating readonly refs | compilation rejects misuse | src/families/overlays/presence/presence.types.test-d.ts |
| P12 | any | motion recipe prop |
data-vize-motion publishes the recipe; omitted prop renders no attribute |
publishes the named motion recipe for the packaged stylesheet |