Popover

The Popover feature, which provides a tooltip-like behavior, can be easily applied to any interactive element via the <BPopover> component or v-b-popover directive. Popovers can also be created and programmatically controlled via the usePopoverController

HTML
template
<div class="d-flex gap-2">
  <BButton
    v-b-popover.focus.top="'I am popover directive content!'"
    title="Popover Title"
  >
    Hover Me
  </BButton>

  <BPopover>
    <template #target> <BButton> Hover Me </BButton></template>
    <template #title>Popover Title</template>
    I am popover <b>component</b> content using the <b>#target</b> slot!
  </BPopover>

  <BButton id="overview-popover"> Hover Me </BButton>
  <BPopover target="overview-popover">
    <template #title>Popover Title</template>
    I am popover <b>component</b> content using the <b>target</b> prop!
  </BPopover>
</div>

Overview

Things to know when using the popover component:

  • Popovers rely on the 3rd party library floating-ui for positioning.
  • Use teleportTo and teleportDisabled to control where in the DOM the popover is rendered. See the Vue.js Docs for details. When using Nuxt, teleportTo defaults to #teleport, set teleportDisabled to disable this behavior. For non-nuxt environments, teleportTo defaults to undefined.
  • Triggering popovers on hidden elements will not work.
  • Popovers for disabled elements must be triggered on a wrapper element.
  • When triggered from hyperlinks that span multiple lines, popovers will be centered. Set the inline prop to improve the positioning see the Floating UI docs for details.

Target

The target is the trigger element (or component) that will trigger the popover. The target is specified via the target slot or prop, and can be any of the following:

The target prop may be any of the following:

  • A string identifying the ID of the trigger element (or ID of the root element of a component)
  • A string with querySelector. (ie. '#toolbar > div:first-child')
  • A reference (ref) to an HTMLElement or an SVGElement via a Template Ref
  • A reference (ref) to a component that has either an HTMLElement or SVGElement as its root element via Template Ref

NOTE

HTMLElement refers to standard HTML elements such as <div>, <button>, etc., while SVGElement refers to <svg> or supported child elements of SVGs.

Positioning

Twelve static options are available for the placement prop: top, top-left, top-right, bottom, bottom-start, bottom-end, left, left-start, left-end, right, right-start, right-end from @floating-ui/vue as well as three auto placement options auto, auto-start and auto-end.

Positioning is relative to the trigger element.

HTML
template
<BContainer>
  <BRow class="my-2">
    <BCol class="d-grid gap-2">
      <BPopover placement="top">
        <template #target><BButton>Top</BButton></template>
        <template #title>Popover Top</template>
        I am popover <b>component</b> content!
      </BPopover>
      <BPopover placement="top-start">
        <template #target><BButton>Top Start</BButton></template>
        <template #title>Popover Top Start</template>
        I am popover <b>component</b> content!
      </BPopover>
      <BPopover placement="top-end">
        <template #target><BButton>Top End</BButton></template>
        <template #title>Popover Top End</template>
        I am popover <b>component</b> content!
      </BPopover>
    </BCol>
    <BCol class="d-grid gap-2">
      <BPopover placement="bottom">
        <template #target><BButton>Bottom</BButton></template>
        <template #title>Popover Bottom</template>
        I am popover <b>component</b> content!
      </BPopover>
      <BPopover placement="bottom-start">
        <template #target><BButton>Bottom Start</BButton></template>
        <template #title>Popover Bottom Start</template>
        I am popover <b>component</b> content!
      </BPopover>
      <BPopover placement="bottom-end">
        <template #target><BButton>Bottom End</BButton></template>
        <template #title>Popover Bottom End</template>
        I am popover <b>component</b> content!
      </BPopover>
    </BCol>
    <BCol class="d-grid gap-2">
      <BPopover placement="left">
        <template #target><BButton>Left</BButton></template>
        <template #title>Popover Left</template>
        I am popover <b>component</b> content!
      </BPopover>
      <BPopover placement="left-start">
        <template #target><BButton>Left Start</BButton></template>
        <template #title>Popover Left Start</template>
        I am popover <b>component</b> content!
      </BPopover>
      <BPopover placement="left-end">
        <template #target><BButton>Left End</BButton></template>
        <template #title>Popover Left End</template>
        I am popover <b>component</b> content!
      </BPopover>
    </BCol>
    <BCol class="d-grid gap-2">
      <BPopover placement="right">
        <template #target><BButton>Right</BButton></template>
        <template #title>Popover Right</template>
        I am popover <b>component</b> content!
      </BPopover>
      <BPopover placement="right-start">
        <template #target><BButton>Right Start</BButton></template>
        <template #title>Popover Right Start</template>
        I am popover <b>component</b> content!
      </BPopover>
      <BPopover placement="right-end">
        <template #target><BButton>Right End</BButton></template>
        <template #title>Popover Right End</template>
        I am popover <b>component</b> content!
      </BPopover>
    </BCol>
  </BRow>
</BContainer>
<BContainer>
  <BRow class="my-2">
    <BCol class="d-grid gap-2">
      <BPopover placement="auto">
        <template #target><BButton>Auto</BButton></template>
        <template #title>Popover Auto</template>
        I am popover <b>component</b> content!
      </BPopover>
    </BCol>
    <BCol class="d-grid gap-2">
      <BPopover placement="auto-start">
        <template #target><BButton>Auto Start</BButton></template>
        <template #title>Popover Auto Start</template>
        I am popover <b>component</b> content!
      </BPopover>
    </BCol>
    <BCol class="d-grid gap-2">
      <BPopover placement="auto-end">
        <template #target><BButton>Auto End</BButton></template>
        <template #title>Popover Auto End</template>
        I am popover <b>component</b> content!
      </BPopover>
    </BCol></BRow
  ></BContainer
>

Triggers

By default, popovers are triggered by pointerenter (hover) and focus events and hidden by pointerleave and blur events on the target element. You can customize which triggers are active using the hover, focus, and click props.

Basic Trigger Configuration

  • Default behavior: Both hover and focus triggers are active
  • Click only: Add the click prop (<BPopover click>)
  • Hover only: Add the hover prop (<BPopover hover>)
  • Focus only: Add the focus prop (<BPopover focus>)
  • Multiple triggers: Combine props, e.g. <BPopover click hover focus>
  • Manual control: Set <BPopover manual> to disable all automatic triggers
HTML
template
<div class="d-flex flex-wrap gap-2">
  <!-- Default: Hover + Focus -->
  <BPopover>
    <template #target>
      <BButton variant="secondary">Default (hover/focus)</BButton>
    </template>
    Default triggers: hover and focus
  </BPopover>

  <!-- Click only -->
  <BPopover click>
    <template #target>
      <BButton variant="primary">Click Only</BButton>
    </template>
    Click to toggle
  </BPopover>

  <!-- Hover only -->
  <BPopover hover>
    <template #target>
      <BButton variant="success">Hover Only</BButton>
    </template>
    Hover to show (no focus)
  </BPopover>

  <!-- Focus only -->
  <BPopover focus>
    <template #target>
      <BButton variant="info">Focus Only</BButton>
    </template>
    Focus to show (no hover)
  </BPopover>

  <!-- Multiple triggers -->
  <BPopover
    click
    hover
    focus
  >
    <template #target>
      <BButton variant="warning">All Triggers</BButton>
    </template>
    Click, hover, or focus
  </BPopover>

  <!-- Manual control -->
  <BPopover
    v-model="manualShow"
    manual
  >
    <template #target>
      <BButton
        variant="danger"
        @click="manualShow = !manualShow"
      >
        Manual ({{ manualShow ? 'hide' : 'show' }})
      </BButton>
    </template>
    Controlled manually via v-model
  </BPopover>
</div>

Trigger Logic

The trigger system uses the following priority order:

  1. Manual mode: If manual="true", all automatic triggers are disabled
  2. Explicit configuration: If click,hover or focus props are explicitly set (true or false), those values are used
  3. Default behavior: Both hover and focus triggers are active

To take finer control of popover visibility, you can use the useToggle or usePopoverController. Alternately, you can set the manual prop and use the v-model or exposed functions to control visibility.

Content

The title and body content of a popover can be set via the title and body props or the title and default slots.

HTML
template
<div class="d-flex gap-2">
  <BPopover
    title="Prop Examples"
    body="Embedding content using properties is easy"
  >
    <template #target>
      <BButton variant="primary">Using properties</BButton>
    </template>
  </BPopover>
  <BPopover>
    <template #target>
      <BButton variant="primary">Using slots</BButton>
    </template>
    <template #title>Content via Slots</template>
    Embedding content <span class="text-danger">using slots</span> affords you
    <em>greater <strong>control.</strong></em> and HTML support.
  </BPopover>
</div>

Custom Classes and Variants

Custom classes can be applied to the popover's title <div> by using the title-class prop and to the popover's body <div> by using the body-class prop:

template
<div class="d-flex gap-2">
  <BPopover
    title-class="my-popover-title-class"
    body-class="my-popover-body-class"
  >
    <template #target>
      <BButton
        href="#"
        tabindex="0"
        >Button</BButton
      >
    </template>
    <template #title>Popover Title</template>
    Popover content
  </BPopover>
</div>

Similarly, use Bootstrap's Color and background utilities to change the variant of the popover.

HTML
template
<div class="d-flex gap-2">
  <BPopover
    title-class="text-bg-danger"
    class="text-bg-danger"
    title="Danger!"
    body="Danger variant popover"
  >
    <template #target>
      <BButton>Button</BButton>
    </template>
  </BPopover>
</div>

body-class and title-class are reactive and can be changed while the popover is open.

Refer to the popover directive docs on applying custom classes to the directive version.

For finer control, use the bootstrap 5 css variables to apply styles directly.

HTML
template
<div class="d-flex gap-2">
  <BPopover
    show
    title="Danger!"
    style="
      --bs-popover-header-bg: var(--bs-danger);
      --bs-popover-bg: var(--bs-danger-bg-subtle);
      --bs-popover-border-color: var(--bs-emphasis-color);
    "
  >
    <template #target>
      <BButton>Button</BButton>
    </template>
    This is <strong>important</strong>
  </BPopover>
</div>

Programmatic control via v-model

You can manually control the visibility of a popover via the v-model. Setting it to true will show the popover, while setting it to false will hide the popover.

Popover is hidden

HTML
vue
<template>
  <div class="d-flex flex-column text-md-center">
    <div class="p-2">
      <p>Popover is {{ model ? 'visible' : 'hidden' }}</p>
    </div>

    <div class="p-2">
      <BPopover
        v-model="model"
        placement="right"
        title="Popover"
      >
        <template #target>
          <BButton
            class="mx-2"
            @click="model = !model"
            >Toggle Popover</BButton
          >
        </template>
        Hello <strong>World!</strong>
      </BPopover>
    </div>
  </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'

const model = ref(false)
</script>

To make the popover shown on initial render, simply add prop show to <BPopover>:

HTML
template
<template>
  <div class="text-center">
    <BPopover
      show
      title="Popover"
    >
      <template #target>
        <BButton variant="primary">Button</BButton>
      </template>
      I start <strong>open</strong>
    </BPopover>
  </div>
</template>

Popovers can also be controlled via Exposed functions.

Close on Hide

The close-on-hide prop can be used to have the popover automatically close when the target is scrolled out of view. The boundary and boundary-padding props can be used to control what's considered clipping.

HTML
vue
<template>
  <div class="d-flex gap-2">
    <BPopover
      :click="true"
      :close-on-hide="true"
      :delay="{show: 0, hide: 0}"
    >
      <template #target>
        <BButton>Click me. Popover closes when clipped</BButton>
      </template>
      Scroll me out of view
    </BPopover>
    <BPopover
      :click="true"
      :close-on-hide="true"
      :delay="{show: 0, hide: 0}"
      :boundary-padding="{top: navHeight}"
    >
      <template #title>Scroll me out of view</template>
      <template #target>
        <BButton>This popover gets hidden by the top nav</BButton>
      </template>
    </BPopover>
  </div>
</template>

<script setup lang="ts">
import {computed, onMounted, ref} from 'vue'

const navRef = ref<Element | null>(null)
onMounted(() => {
  navRef.value = document.body.querySelector('#app > nav')
})
const navHeight = computed(() => navRef.value?.clientHeight)
</script>

Exposed functions

BPopover exposes several functions to allow manipulation of the state of the component. These are accessed through the template ref

HTML
vue
<template>
  <div class="d-flex flex-column text-md-center">
    <div class="p-2">
      <BButton
        id="popover-expose"
        variant="primary"
        >I have a popover</BButton
      >
    </div>

    <div class="p-2">
      <BButton
        class="mx-2"
        @click="show"
        >Show</BButton
      >
      <BButton
        class="mx-2"
        @click="hide"
        >Hide</BButton
      >
      <BButton
        class="mx-2"
        @click="toggle"
        >Toggle</BButton
      >

      <BPopover
        ref="myPopover"
        v-model="model"
        target="popover-expose"
        title="Popover"
      >
        Hello <strong>World!</strong>
      </BPopover>
    </div>
  </div>
</template>

<script setup lang="ts">
import {ref, useTemplateRef} from 'vue'
import {BPopover} from 'bootstrap-vue-next/components/BPopover'

const myPopover = useTemplateRef('myPopover')
const show = () => myPopover.value?.show()
const hide = () => myPopover.value?.hide()
const toggle = () => myPopover.value?.toggle()
const model = ref(false)
</script>

Component Reference

<BPopover>

PropTypeDefaultDescription
bodystringundefined Text to place in the body of the popover.
body-classClassValueundefined CSS class (or classes) to apply to the body
boundaryBoundary | RootBoundary'clippingAncestors' The boundary constraint of the popover, using members of `Boundary` or `RootBoundary`.
boundary-paddingPaddingundefined The number of pixels the popover stays away from the edge of the boundary element.
clickbooleanundefined Enable/disable click trigger. See [Triggers](#triggers) for details.
close-on-hidebooleanfalse Closes the popover when the target is hidden, if `noAutoClose` is set.
delaynumber | { show: number; hide: number }'() => ({show: 100, hide: 300})' Sets the show and hide delay. Use a number for both, or an object to set show and hide delays individually.
floating-middlewareMiddleware[]undefined Directly sets the Floating UI middleware behavior.
focusbooleanundefined Enable/disable focus trigger. See [Triggers](#triggers) for details.
hide-marginnumber0 The margin applied when hiding the popover on pointer leave, specifying how far the pointer can move off the target before hiding.
hoverbooleanundefined Enable/disable hover trigger. See [Triggers](#triggers) for details.
idstringundefined Used to set the `id` attribute on the rendered content, and used as the base to generate any additional element IDs as needed
initial-animationbooleanfalse When set, enables the initial animation on mount
inlinebooleanfalse Improves positioning for inline reference elements spanning multiple lines (from Floating UI).
lazybooleanfalse When set, the content will not be mounted until opened
manualbooleanfalse Disables all triggers, requiring the programmatic API to show or hide the popover.
model-valuebooleanfalse Controls the visibility of the component
no-animationbooleanfalse When set, disables the animation
no-auto-closebooleanfalse Disables automatic closing on click outside or scroll out of view, overriding `closeOnHide`.
no-fadebooleanfalse Alias for `noAnimation`
no-flipbooleanfalse Disables automatic flipping of the popover when it goes out of view.
no-hidebooleanfalse Prevents the popover from hiding based on `boundary` or `rootBoundary` constraints.
no-shiftbooleanfalse Disables automatic shifting of the popover to keep it in view.
no-sizebooleanfalse Disables automatic sizing of the popover to fit the clipping region.
noninteractivebooleanfalse Makes the popover non-interactive, preventing it from remaining open when hovered or focused.
offsetNumberish | nullnull Sets the offset of the popover in pixels from the target. If `null`, uses the size of the Bootstrap CSS arrow.
placementPopoverPlacement'top' Placement of a floating element
realtimebooleanfalse Updates the popover position on every animation frame if required. CPU-intensive; the default listens to browser events.
referencestring | ComponentPublicInstance | HTMLElement | nullnull The reference element to which the popover is anchored. If unspecified, the popover is positioned relative to the target element.
showbooleanfalse When set, and prop 'visible' is false on mount, will animate from closed to open on initial mount. Mainly to help with template show. Use model-value for reactive show/hide
strategyStrategy'absolute'
targetstring | ComponentPublicInstance | HTMLElement | nullnull The trigger and reference element for the popover, unless `reference` is defined.
teleport-disabledbooleanfalse Renders the popover in its defined location, disabling teleporting.
teleport-tostring | RendererElement | null | undefinedundefined Overrides the default teleport location.
titlestringundefined Text content to place in the title
title-classClassValueundefined CSS class (or classes) to apply to the title
tooltipbooleanfalse Renders the popover as a tooltip (used internally by `BTooltip`).
trans-propsTransitionPropsundefined Transition properties
unmount-lazybooleanfalse When set and `lazy` is true, the content will be unmounted when closed
visiblebooleanfalse When 'true', open without animation
EventArgsDescription
blur
value: BvTriggerableEvent
Emitted when the target element loses focus.
cancel
click-outside
value: BvTriggerableEvent
Emitted when the mouse is clicked outside the popover.
close-on-hide
value: BvTriggerableEvent
Emitted when the popover is closed due to being clipped.
hidden
value: BvTriggerableEvent
Always emits after the component is hidden
hide
value: BvTriggerableEvent - Call value.preventDefault() to cancel hide
Always emits just before the component has hidden. Cancelable (as long as component wasn't forcibly hidden)
hide-prevented
value: BvTriggerableEvent
Emitted when the component tried to close, but was prevented from closing. This occurs when preventDefault() is called on the event, the user clicks escape and no-close-onbackdrop is set to true, or the user clicks on the backdrop and no-close-onbackdrop is set to true.
ok
pointerleave
value: BvTriggerableEvent
Emitted when the pointer leaves the target element, but not when leaving the popover element.
show
value: BvTriggerableEvent - Call value.preventDefault() to cancel show
Always emits just before the component is shown. Cancelable
show-prevented
value: BvTriggerableEvent
Emitted when the component tried to open, but was prevented from opening. This occurs when preventDefault() is called on the event
shown
value: BvTriggerableEvent
Always emits just after component is shown.
toggle
value: BvTriggerableEvent - Call value.preventDefault() to cancel hide
Always emits just before the component is toggled via the exposed 'toggle()' function or useToggle composable . Cancelable (as long as component wasn't forcibly hidden)
toggle-prevented
value: BvTriggerableEvent
Emitted when the component tried to toggle, but was prevented from doing so. This occurs when preventDefault() is called on the event, the user clicks escape and no-close-onbackdrop is set to true, or the user clicks on the backdrop and no-close-onbackdrop is set to true.
update:model-value
value: boolean - New visibility state of the popover.
Emitted when the visibility of the popover changes.
NameScopeDescription
default
id: string - Unique ID for the component
show: () => void - Function to show the component
hide: (trigger?: string, noTriggerEmit?: boolean) => void - Function to hide the component. `trigger` is the trigger that caused the hide. `noTriggerEmit` prevents the emit of the trigger event.
toggle: () => void - Function to toggle the component visibility
active: boolean - Indicates if the component is active (starting show, before/after animations)
visible: boolean - Indicates if the component is visible (shown)
Content for the popover body.
target
id: string - Unique ID for the component
show: () => void - Function to show the component
hide: (trigger?: string, noTriggerEmit?: boolean) => void - Function to hide the component. `trigger` is the trigger that caused the hide. `noTriggerEmit` prevents the emit of the trigger event.
toggle: () => void - Function to toggle the component visibility
active: boolean - Indicates if the component is active (starting show, before/after animations)
visible: boolean - Indicates if the component is visible (shown)
Content for the target or trigger element.
title
id: string - Unique ID for the component
show: () => void - Function to show the component
hide: (trigger?: string, noTriggerEmit?: boolean) => void - Function to hide the component. `trigger` is the trigger that caused the hide. `noTriggerEmit` prevents the emit of the trigger event.
toggle: () => void - Function to toggle the component visibility
active: boolean - Indicates if the component is active (starting show, before/after animations)
visible: boolean - Indicates if the component is visible (shown)
Content for the popover title.