Skip to content

Components

For more advanced use cases such as dropdowns, you can use the components instead of the v-tooltip directive.

The most basic component included by default is the VDropdown component:

html
<VDropdown
  :distance="6"
>
  <!-- This will be the popover reference (for the events and position) -->
  <button>Click me</button>

  <!-- This will be the content of the popover -->
  <template #popper>
    <input class="tooltip-content" v-model="msg" placeholder="Tooltip content" />
    <p>
      {{ msg }}
    </p>

    <!-- You can put other components too -->
    <ExampleComponent char="=" />
  </template>
</VDropdown>

As shown in the above example, the popper content must be passed to the popper slot.

The VDropdown uses the dropdown theme.

Tooltip

If you want to display a tooltip with components and more advanced content, you can use the VTooltip component that uses the tooltip theme (just like the v-tooltip directive).

html
<VTooltip>
  <a>Sponsor me</a>

  <template #popper>
    Help me fund my Open Source work!
  </template>
</VTooltip>

Hover Menu

There is a VMenu variant with the menu theme which extends the dropdown theme. It overrides triggers and delay to be usable on mouse over.

html
<VMenu>
  <button>Documentation</button>

  <template #popper>
    <button>Guide</button>
    <button>API Reference</button>
  </template>
</VMenu>

Placements

The available placements are:

  • 'auto'
  • 'auto-start'
  • 'auto-end'
  • 'top'
  • 'top-start'
  • 'top-end'
  • 'right'
  • 'right-start'
  • 'right-end'
  • 'bottom'
  • 'bottom-start'
  • 'bottom-end'
  • 'left'
  • 'left-start'
  • 'left-end'

Triggers

Triggering a popper means either showing it or hiding it. A trigger describes events that should toggle the popper visibility.

These are the available triggers:

  • click
  • hover (uses mouseenter and mouseleave)
  • focus (uses focus and blur)
  • touch (uses touchstart and touchend)

Those events will be listened on the elements in the default slot inside the popper component (the reference elements).

To customize how the popper is shown or hidden, use the triggers prop. It must be an array of triggers from the list above.

html
<VDropdown
  :triggers="['hover', 'focus']"
>

If you want to manually trigger the popper, use an empty array: :triggers="[]" and the shown prop:

html
<VDropdown
  :triggers="[]"
  :shown="isOpen"
  :autoHide="false"
>

TIP

If autoHide is true, the popper will be hidden when clicked outside of it. That's why it's forced to false in the previous snippet.

You can specify different triggers for the showing or hiding action of the popper with the showTriggers and hideTriggers props:

html
<VDropdown
  :showTriggers="['hover']"
  :hideTriggers="['click']"
>

Using functions allows you to reuse the triggers list:

html
<VDropdown
  :triggers="['focus']"
  :showTriggers="triggers => [...triggers, 'hover']"
  :hideTriggers="triggers => [...triggers, 'click']"
>

You can also use the popperTriggers, popperShowTriggers and popperHideTriggers props which will add the event listeners on the popper container itself (instead of the reference elements).

This can be useful if you want to popper to stay open when the mouse hovers it:

html
<VDropdown
  :triggers="['hover']"
  :popperTriggers="['hover']"
>

Offset

Offsetting the popper means moving it relative to its computed position on the page. You can do this with the distance and skidding props.

This example will move the popper away from the reference by 64 pixels:

html
<VDropdown
  :distance="64"
>

This example will move the popper 32 pixels alongside the reference:

html
<VDropdown
  :skidding="32"
>

You can also use negative value, since it's a relative offset.

html
<VDropdown
  :distance="32"
  :skidding="-16"
>

Arrow padding

If you use tooltips that are positionned on the edge of the reference, you may need to specify an "arrow padding". This padding will prevent the arrow from glitch out of the tooltip:

html
<VDropdown :skidding="-32" />

To fix this, specify the padding option of the arrow modifier. In the following example, we prevent the arrow from going to the edges of the tooltip with a 8px limit:

html
<VDropdown
  :skidding="-32"
  :arrow-padding="8"
/>

Hide from slot

Use the hide slot prop to close the popper:

html
<VDropdown>
  <button>Click me</button>

  <template #popper="{ hide }">
    <button @click="hide()">Close</button>
  </template>
</VDropdown>

Close directive

Use the v-close-popper directive on an element inside the dropdown to close it when the element is clicked (or touched on mobile):

html
<VDropdown>
  <button>Click me</button>

  <template #popper>
    <button v-close-popper>Close</button>
  </template>
</VDropdown>

The directive works even in nested components in the popper slot.

You can also set it to true or false to enable or disable the directive (enabled by default):

html
<button v-close-popper="false">Close</button>
<button v-close-popper="true">Close</button>

You can also use a property:

html
<button v-close-popper="myBooleanProp">Close</button>
js
data () {
  return {
    myBooleanProp: true,
  }
}

Close all the poppers in the page with the all modifier:

html
<a v-close-popper.all>Close All</a>

Nesting poppers inside other popper will automatically prevent the parents from hiding when any child is shown:

Floating Vue will automatically fix the diagonal submenu problem for you by detecting if the mouse is aiming at the popper content from the reference:

popper aim debug example

After a one second delay, the lock applied because of aiming will expire.

Disable popper

Disabling a popper will prevent it from being shown.

html
<VDropdown :disabled="isDisabled"></VDropdown>
js
data () {
  return {
    isDisabled: true,
  }
}

Mobile

You can also just disable the positioning of the popper with positioningDisabled:

html
<VDropdown :positioning-disabled="isMobile"></VDropdown>

It can for example be useful on the mobile version of your app if you want to apply a fixed position to the popper with CSS.

html
<script>
let count = 0

export default {
  data () {
    return {
      isMobile: false,
    }
  },

  methods: {
    onShow () {
      if (count === 0) {
        document.body.classList.add('no-scroll')
      }
      count++
    },

    onHide () {
      count--
      if (count === 0) {
        document.body.classList.remove('no-scroll')
      }
    },
  },
}
</script>

<template>
  <div class="example">
    <label>
      <input v-model="isMobile" type="checkbox">
      Is mobile
    </label>

    <VDropdown
      :positioning-disabled="isMobile"
      @apply-show="isMobile && onShow()"
      @apply-hide="isMobile && onHide()"
    >
      <button>Click me</button>

      <template #popper="{ hide }">
        <div>This is awesome!</div>
        <button v-if="isMobile" @click="hide()">Cancel</button>
      </template>
    </VDropdown>
  </div>
</template>

<style>
body.no-scroll {
  overflow: hidden;
}

.v-popper__popper--no-positioning {
  position: fixed;
  z-index: 9999;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: flex-end;
}

.v-popper__popper--no-positioning .v-popper__backdrop {
  display: block;
  background: rgba(0 0 0 / 90%);
}

.v-popper__popper--no-positioning .v-popper__wrapper {
  width: 100%;
  pointer-events: auto;
  transition: transform .15s ease-out;
}

.v-popper__popper--no-positioning.v-popper__popper--hidden .v-popper__wrapper {
  transform: translateY(100%);
}
</style>

Made by Guillaume Chau with ❤️