Skip to content

@presage-kit/vue

Vue 3 bindings for Presage. Provides a plugin for dependency injection and composables for reactive adaptation.

Terminal window
pnpm add @presage-kit/core @presage-kit/vue

A Vue 3 plugin that provides the AdaptiveClient to all components via provide/inject.

import { createApp } from 'vue'
import { AdaptivePlugin } from '@presage-kit/vue'
import { createAdaptiveClient } from '@presage-kit/core'
const client = createAdaptiveClient({ /* ... */ })
const app = createApp(App)
app.use(AdaptivePlugin, { client })
app.mount('#app')

Install options: AdaptivePluginOptions

interface AdaptivePluginOptions {
client: AdaptiveClient
}
OptionTypeRequiredDescription
clientAdaptiveClientYesClient from createAdaptiveClient()

Implementation: Calls app.provide() with an injection key symbol, making the client available to all descendant components.

Resolves an adaptation point reactively. Re-evaluates when user context changes.

import { useAdaptive } from '@presage-kit/vue'
const { selectedVariant, resolution, context, track } = useAdaptive('onboarding', {
variants: ['guided-tour', 'standard', 'minimal'] as const,
defaultVariant: 'standard',
})

Parameters:

ParamTypeDescription
adaptationIdstringUnique adaptation point ID
config.variantsreadonly V[]Array of variant IDs
config.defaultVariantNoInfer<V>Default variant (must be in variants)
config.strategyStrategyOptional. Defaults to { type: 'rules' }

Return type:

The returned object uses JavaScript getters backed by Vue computed() refs, making all values reactive.

FieldTypeDescription
selectedVariantV (getter)Currently selected variant
resolutionResolvedAdaptation (getter)Full resolution metadata
contextUserContext (getter)Current user context
track(event: string, props?: Record<string, unknown>) => voidScoped track function

Reactivity: The composable uses useAtom() internally to bridge the core’s atom-based state to Vue’s reactivity system. When the client state changes, all computed values update automatically.

Impressions: Uses Vue’s watch() with { immediate: true } to track presage:impression events when the selected variant changes.

Usage in templates:

<script setup lang="ts">
import { useAdaptive } from '@presage-kit/vue'
const { selectedVariant } = useAdaptive('panel', {
variants: ['compact', 'expanded'] as const,
defaultVariant: 'compact',
})
</script>
<template>
<CompactPanel v-if="selectedVariant === 'compact'" />
<ExpandedPanel v-else />
</template>

Lightweight composable returning only the selected variant string.

import { useVariant } from '@presage-kit/vue'
const variant = useVariant('layout', {
variants: ['sidebar', 'topnav'] as const,
defaultVariant: 'sidebar',
})

Parameters: Same as useAdaptive().

Return type: V — The selected variant string (reactive getter).

Internally delegates to useAdaptive() and returns selectedVariant.

Usage in templates:

<script setup lang="ts">
import { useVariant } from '@presage-kit/vue'
const variant = useVariant('cta-style', {
variants: ['primary', 'secondary'] as const,
defaultVariant: 'primary',
})
</script>
<template>
<button :class="`btn btn--${variant}`">Get Started</button>
</template>

Returns the AdaptiveClient instance from the plugin injection.

import { useAdaptiveClient } from '@presage-kit/vue'
const client = useAdaptiveClient()
client.track('feature_used', { featureId: 'export' })
client.identify('user-789', { role: 'admin' })
const context = client.getContext()

Return type: AdaptiveClient

Throws: Error if AdaptivePlugin has not been installed.

Common patterns:

<script setup lang="ts">
import { useAdaptiveClient } from '@presage-kit/vue'
const client = useAdaptiveClient()
// Identify after authentication
onMounted(() => {
const user = getCurrentUser()
client.identify(user.id, {
role: user.role,
plan: user.plan,
signupDate: user.createdAt,
})
})
// Track actions
function handleExport() {
client.track('feature_used', { featureId: 'export' })
doExport()
}
// Evaluate rules imperatively
function getNavAction() {
return client.evaluateAction('sidebar-nav')
}
</script>
FeatureReactVue
Provider<AdaptiveProvider> componentAdaptivePlugin (Vue plugin)
Declarative component<Adaptive> + <Variant>Not included (use v-if with useAdaptive())
Adaptive navigation<AdaptiveNav> componentManual with evaluateAction()
Hook/composable returnPlain objectObject with reactive getters
State bridgeuseSyncExternalStore-styleref + atom subscribe()

The Vue adapter is intentionally leaner. Vue’s template syntax and reactivity system make it natural to use v-if/v-else with the composable return value, removing the need for wrapper components like <Adaptive>.