usePopover
The usePopover composable allows you to create and control popovers and tooltips dynamically from anywhere in your application. It provides methods to create, show, hide, and manage both popovers and tooltips programmatically.
Setup
To use usePopover, you need one of the following setup approaches:
BApp Component (Recommended)
The easiest way is to wrap your application with the BApp component, which automatically sets up the orchestrator and registry:
<template>
<BApp>
<RouterView />
</BApp>
</template> Due to how Vue's provide/inject system works, composables like useToast(), useModal(), and usePopover()cannot be called in the same component that declares <BApp>. They rely on values provided by BApp, and Vue's inject only works in child components — not in the component that calls provide itself.
Place <BApp> at least one component level above where these composables are called.
Plugin Setup (Legacy)
Alternatively, you can use the traditional plugin approach.
Note: As of v0.40, there are no separate toast/modal/popover controller plugins. If you stick with plugins, use the single orchestratorPlugin (or prefer BApp).
<BApp>, you must have initialized the createBootstrap plugin for this to work properly. Read hereCreating Popovers
Popovers and tooltips can be created using the popover or tooltip methods:
<template>
<BButton id="popover-basic-target" @click="showPopover"> Toggle popover </BButton>
</template>
<script setup lang="ts">
import { BButton } from 'bootstrap-vue-next/components/BButton'
import { usePopover } from 'bootstrap-vue-next/composables/usePopover'
const { popover } = usePopover()
const showPopover = async () => {
await using _ = await popover({
title: 'Hello World!',
body: 'This is a popover.',
target: 'popover-basic-target',
}).show()
}
</script>Reactivity Within popover and tooltip
The methods accept reactive properties using MaybeRef, allowing dynamic updates to the popover content.
<template>
<BButton id="reactive-tooltip-target" @click="showTooltip"> Toggle tooltip </BButton>
</template>
<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, watchEffect } from 'vue'
import type { TooltipOrchestratorCreateParam } from 'bootstrap-vue-next'
import { BButton } from 'bootstrap-vue-next/components/BButton'
import { usePopover } from 'bootstrap-vue-next/composables/usePopover'
const { tooltip } = usePopover()
const title = ref('foo')
let intervalId: ReturnType<typeof setInterval> | undefined
// `tooltip()`/`popover()` need a writable ref/plain object (they need to control `modelValue`
// themselves), so `reactive()` is not used here. Instead, derive the reactive pieces with
// `computed()`, then sync them onto a plain ref via `watchEffect()`.
const derivedTitle = computed(() => title.value)
const myTooltip = ref<TooltipOrchestratorCreateParam>({
title: derivedTitle.value,
target: 'reactive-tooltip-target',
modelValue: false,
})
watchEffect(() => {
myTooltip.value.title = derivedTitle.value
})
onMounted(() => {
intervalId = setInterval(() => {
title.value = title.value === 'foo' ? 'bar' : 'foo'
}, 2500)
})
onUnmounted(() => {
if (intervalId !== undefined) {
clearInterval(intervalId)
}
})
const showTooltip = async () => {
await using _ = await tooltip(myTooltip).show()
}
</script>Advanced Creation
For more control, you can use the component property to render a custom component or the slots property to define slot content dynamically.
<template>
<BButton id="advanced-popover-target" @click="showAdvancedPopover">
Toggle advanced popover
</BButton>
</template>
<script setup lang="ts">
import { h, markRaw } from 'vue'
import { BButton } from 'bootstrap-vue-next/components/BButton'
import { usePopover } from 'bootstrap-vue-next/composables/usePopover'
const { popover } = usePopover()
const showAdvancedPopover = async () => {
await using _ = await popover({
slots: {
default: (scope) => markRaw(h('div', null, `Custom content - Visible: ${scope.visible}`)),
},
target: 'advanced-popover-target',
title: 'Advanced Popover',
}).show()
}
</script>Return Value
The popover and tooltip methods return a controller object with instance methods:
show: () => Promise<BvTriggerableEvent & AsyncDisposable>hide: (trigger?: string) => voidtoggle: () => voidget: () => PopoverOrchestratorParam | undefinedset: (props: Partial<PopoverOrchestratorParam>) => voiddestroy: () => Promise<void>
Lifecycle
By default, the popover is destroyed when the current scope is exited. You can manually destroy it using the destroy method.
const pop = popover({ title: 'Hello World!' })
pop.show()
// do something
pop.hide()Alternatively, use await using in TypeScript 5.2+ to automatically destroy the popover when the scope is exited.
await using pop = await popover({ title: 'Hello World!' }).show()