Vize

use-user-activation

Track sticky and transient user activation with the User Activation API.

Package @vizejs/composable/use-user-activation
Own the source vize lib pull composable:use-user-activation
Runtime exports useUserActivation
Gzip budget 2048 B

Minimal setup

Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).

vp install @vizejs/composable

Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.

import { useUserActivation } from "@vizejs/composable/use-user-activation";

Try it

Wait for the first interaction

Know whether the reader has interacted with the page before using APIs that require it.

Open the interactive example

What to observe: The message changes after the first click or key press anywhere on the page.

Browsers require user activation for audio, popups and some permissions. isActive reports transient activation.

Compare the initial and interacted states
Wait for the first interaction: initial state
Initial state
Wait for the first interaction: state after the verified interactions
After the verified interactions

Copy the example

Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.

<script setup lang="ts">
import { useUserActivation } from "@vizejs/composable/use-user-activation";

const { hasBeenActive } = useUserActivation();
</script>

<template>
  <div class="composable-example">
    <p>Wait for the reader's first interaction before playing sound or opening a popup.</p>
    <button type="button">Interact with the page</button>
    <output aria-live="polite">{{
      hasBeenActive ? "The page may now play sound." : "Waiting for the first interaction."
    }}</output>
  </div>
</template>

Runtime contract

Utility Category Stability SSR Hydration Cleanup Targets Host globals Uses
useUserActivation input experimental deterministic-fallback caller-managed caller, reactive-scope web, desktop window tryOnScopeDispose

API

useUserActivation

Track sticky and transient user activation with the User Activation API. The state is refreshed on activation-triggering events of target (immediately and again after a microtask) and polled while isActive is true so its expiry is observed. Listeners and the timer are removed when the owning reactive scope stops; outside a scope call stop(). Server rendering: no listeners or timers, supported, hasBeenActive, and isActive are false.

function useUserActivation(options: UseUserActivationOptions = {}): UserActivationControls
const { isActive } = useUserActivation();
const canOpenPopup = computed(() => isActive.value);

Types

UserActivationLike

Minimal navigator.userActivation (UserActivation).

Member Type Description
hasBeenActive boolean Whether the page ever had sticky activation.
isActive boolean Whether the page currently has transient activation.

UseUserActivationOptions

Options for useUserActivation.

Member Type Description
userActivation? MaybeRefOrGetter<UserActivationLike | null | undefined> User activation state for alternate runtimes and tests.
target? MaybeRefOrGetter<EventTarget | null | undefined> Target whose activation-triggering events refresh the state.
events? readonly string[] Events that refresh the state.
interval? number Poll interval in milliseconds while isActive is true, so its expiry is observed. 0 disables polling.
scheduler? IntervalScheduler Timer host for polling.

UserActivationControls

Reactive state returned by useUserActivation.

Member Type Description
supported ComputedRef<boolean> Whether the User Activation API is available.
hasBeenActive Readonly<Ref<boolean>> Sticky activation: the user interacted with the page at least once.
isActive Readonly<Ref<boolean>> Transient activation: a gated API (popup, fullscreen, clipboard) may be called now.
refresh () => void Re-read the activation state.
stop () => void Remove listeners and timers. Idempotent.