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.

View Source Edit this page on GitHub

Setup

To use usePopover, you need one of the following setup approaches:

The easiest way is to wrap your application with the BApp component, which automatically sets up the orchestrator and registry:

vue
<template>
  <BApp>
    <RouterView />
  </BApp>
</template>

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).

Creating Popovers

Popovers and tooltips can be created using the popover or tooltip methods:

HTML
vue
<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.

HTML
vue
<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.

HTML
vue
<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) => void
  • toggle: () => void
  • get: () => PopoverOrchestratorParam | undefined
  • set: (props: Partial<PopoverOrchestratorParam>) => void
  • destroy: () => Promise<void>

Lifecycle

By default, the popover is destroyed when the current scope is exited. You can manually destroy it using the destroy method.

ts
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.

ts
await using pop = await popover({ title: 'Hello World!' }).show()