Vue 3 + Pinia — Composable-Driven Integration
A frontend-only Vue 3 app where several unrelated components need to know whether analytics is granted. Rather than calling useConsent()in every one of them, it's wrapped once in a Pinia store — Pinia's setup-store syntax can call composables directly, so this is a thin wrapper, not a reimplementation.
What this demonstrates
- Registering the widget once with
setConsentiWidget() - A Pinia setup store built directly on top of
useConsent() - A derived, memoized getter (
analyticsEnabled) any component can read
1. Create and register the widget
main.ts
ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { ConsentiSetup } from '@consenti/ui'
import { setConsentiWidget } from '@consenti/ui/vue'
import App from './App.vue'
const widget = new ConsentiSetup({ compliance: { type: 'opt-in' } })
setConsentiWidget(widget)
createApp(App).use(createPinia()).mount('#app')ℹ️Using Nuxt 3? Do this inside a
.client.ts plugin instead of main.ts — see @consenti/ui/vue in the Frameworks reference.2. Wrap useConsent() in a Pinia store
stores/consent.ts
ts
import { computed } from 'vue'
import { defineStore } from 'pinia'
import { useConsent } from '@consenti/ui/vue'
export const useConsentStore = defineStore('consent', () => {
const { hasConsent, consent, isCookieGranted, showModal, grantAll, denyAll } = useConsent()
const analyticsEnabled = computed(() => isCookieGranted('analytics'))
const marketingEnabled = computed(() => isCookieGranted('marketing'))
return { hasConsent, consent, analyticsEnabled, marketingEnabled, showModal, grantAll, denyAll }
})hasConsent, consent, bannerVisible, and modalVisible from useConsent() are Vue Refs — Pinia auto-unwraps them at the store boundary, so components read them without .value.
3. Use it anywhere
components/AnalyticsGate.vue
vue
<script setup lang="ts">
import { useConsentStore } from '@/stores/consent'
const consent = useConsentStore()
</script>
<template>
<button v-if="!consent.analyticsEnabled" @click="consent.showModal()">
Enable Analytics
</button>
<span v-else class="text-sm text-slate-400">Analytics enabled</span>
</template>Related documentation