Migration from v-tooltip 2
floating-vue is a complete rewrite compared to v-tooltip. This migration guide will help you upgrade!
Breaking changes
Package renamed
v-tooltip => floating-vue
| floating-vue | NPM Tag | Vue compatibility |
|---|---|---|
| 2.x | latest | 3.x |
| 1.x | vue2 | 2.x |
Floating UI
The positioning library has changed from popperjs to floating-ui which is the spiritual successor.
Global configuration
The global configuration object has completely changed. Instead of having a lot of specific options it is now an object of default values for the props (like placement or distance). Additionally, it has a themes option to define themes.
defaultPlacement: useplacementdefaultClass: removeddefaultTargetClass: removeddefaultHtml: usehtmlin thetooltiptheme (or any theme that you use with the directive)defaultTemplate: removeddefaultArrowSelector: removeddefaultInnerSelector: removeddefaultDelay: usedelaydefaultTrigger: usetriggers,showTriggers,hideTriggersdefaultOffset: usedistanceand/orskiddingdefaultContainer: usecontainerdefaultBoundariesElement: useboundarydefaultPopperOptions: removeddefaultLoadingClass: removeddefaultLoadingContent: useloadingContentin thetooltiptheme (or any theme that you use with the directive)autoHide: unchangeddefaultHideOnTargetClick: usehideTriggersdisposeTimeout: unchangedpopover: removed, use themes instead
Before:
{
defaultPlacement: 'top',
defaultClass: 'vue-tooltip-theme',
defaultTargetClass: 'has-tooltip',
defaultHtml: true,
defaultTemplate: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
defaultArrowSelector: '.tooltip-arrow, .tooltip__arrow',
defaultInnerSelector: '.tooltip-inner, .tooltip__inner',
defaultDelay: 0,
defaultTrigger: 'hover focus',
defaultOffset: 0,
defaultContainer: 'body',
defaultBoundariesElement: undefined,
defaultPopperOptions: {},
defaultLoadingClass: 'tooltip-loading',
defaultLoadingContent: '...',
autoHide: true,
defaultHideOnTargetClick: true,
disposeTimeout: 5000,
popover: {
defaultPlacement: 'bottom',
defaultClass: 'vue-popover-theme',
defaultBaseClass: 'tooltip popover',
defaultWrapperClass: 'wrapper',
defaultInnerClass: 'tooltip-inner popover-inner',
defaultArrowClass: 'tooltip-arrow popover-arrow',
defaultOpenClass: 'open',
defaultDelay: 0,
defaultTrigger: 'click',
defaultOffset: 0,
defaultContainer: 'body',
defaultBoundariesElement: undefined,
defaultPopperOptions: {},
defaultAutoHide: true,
defaultHandleResize: true,
},
}After:
{
placement: 'top',
delay: 0,
distance: 0,
container: 'body',
boundary: undefined,
autoHide: true,
disposeTimeout: 5000,
themes: {
tooltip: {
html: true,
triggers: ['hover', 'focus'],
hideTriggers: triggers => [...triggers, 'click'],
loadingContent: '...',
},
dropdown: {
placement: 'bottom',
delay: 0,
triggers: ['click'],
distance: 0,
container: 'body',
boundary: undefined,
autoHide: true,
handleResize: true,
},
},
}TIP
You can use the example above to replicate the default config of v-tooltip v2.
Directive
The v-tooltip directive now uses a popper component internally. This means that there are no longer separate APIs between the components and the directive and you should now be using the components props on the directive object when needed. The directive has a few additional props tough.
Changed defaults:
htmlis nowfalseby default to help you void XSS attacks.
Renamed props:
triggertotriggers(see Trigger)showtoshownboundariesElementtoboundaryclassestopopperClass
The following directive options were also removed:
targetClassestemplatearrowSelectorinnerSelectorhideOnTargetClick(replaced byhideTriggers)loadingClass
Default component
<v-popper> component was removed. Instead use <VDropdown> or any other builtin (or custom) components.
Before:
<v-popper/>After:
<VDropdown/>Trigger
The trigger prop was renamed to triggers and is now an array of events.
Before:
<v-popper trigger="click focus"/>After:
<VDropdown :triggers="['click', 'focus']"/>The manual event was removed. Instead use an empty array:
Before:
<v-popper trigger="manual"/>After:
<VDropdown :triggers="[]"/>There are a range of new props accompanying triggers:
showTriggershideTriggerspopperTriggersshowPopperTriggershidePopperTriggers
Offset
The offset is now two separate props: distance and skidding.
Before:
<v-popper
offset="10 0"
/>After:
<VDropdown
distance="10"
skidding="0"
/>Renamed props
boundariesElementtoboundaryopentoshownopenGrouptoshowGrouppopoverClasstopopperClass
Plus the default component slot props:
isOpentoshown
Before:
<v-popper
boundaries-element="..."
open="..."
open-group="..."
>
<template #default="{ isOpen }">
<!-- ... -->
</template>
</v-popper>After:
<VDropdown
boundary="..."
shown="..."
show-group="..."
>
<template #default="{ shown }">
<!-- ... -->
</template>
</VDropdown>Renamed slots
popovertopopper
Before:
<v-popper>
<button>
Click me!
</button>
<template #popover>
I am a dropdown
</template>
</v-popper>After:
<VDropdown>
<button>
Click me!
</button>
<template #popper>
I am a dropdown
</template>
</VDropdown>Renamed directives
v-close-popovertov-close-popper
Removed props
The following props were removed and are no longer available:
popoverBaseClasspopoverWrapperClasspopoverArrowClasspopoverInnerClassopenClassmodifierspopperOptions
CSS classes
The structure of the HTML produced by the library has changed. Most classes are now using a BEM-like notation with the v-popper prefix. They are no longer customizable since they don't conflict with other libraries such as boostrap. You can add your own classes to the poppers with themes (recommended) or the popperClass prop.
Learn more about CSS classes
Changed classes:
v-popovertov-popperopen(default value) tov-popper--shown
Before:
<div class="v-popover open">
<div
class="trigger"
style="display: inline-block;"
>
<!-- Default slot -->
</div>
</div>After:
<div class="v-popper v-popper--shown">
<!-- Default slot -->
</div>Popper content
Changed classes:
tooltip popover(default value) tov-popper__popper.vue-tooltip-theme(default value) is replaced by theme classes.open(default value) tov-popper__popper--shownandv-popper__popper--hidden.wrapper(default value) tov-popper__wrapper.tooltip-inner popover-inner(default value) tov-popper__inner.tooltip-arrow popover-arrow(default value) tov-popper__arrow-outerandv-popper__arrow-inner.
New classes:
v-popper__arrow-container- on
v-popper__popper:v-popper__popper--skip-transitionv-popper__popper--show-fromv-popper__popper--show-tov-popper__popper--hide-fromv-popper__popper--hide-to
Before:
<div
class="tooltip popover vue-tooltip-theme open"
:style="{
visibility: isOpen ? 'visible' : 'hidden',
}"
>
<div class="wrapper">
<div
class="tooltip-inner popover-inner"
style="position: relative;"
>
<div>
<!-- Popover slot -->
</div>
</div>
<div class="tooltip-arrow popover-arrow" />
</div>
</div>After:
<div class="v-popper__popper">
<div class="v-popper__wrapper">
<div class="v-popper__inner">
<div>
<!-- Popper slot -->
</div>
</div>
<div class="v-popper__arrow-container">
<div class="v-popper__arrow-outer" />
<div class="v-popper__arrow-inner" />
</div>
</div>
</div>Directive
The v-tooltip directive now uses the same component and thus has the same HTML result as the other components such as VDropdown.
Before (default):
<div class="tooltip" role="tooltip">
<div class="tooltip-arrow"></div>
<div class="tooltip-inner">Text here</div>
</div>After:
<div class="v-popper__popper v-popper--theme-tooltip">
<div class="v-popper__wrapper">
<div class="v-popper__inner">
<div>
Text here
</div>
</div>
<div class="v-popper__arrow-container">
<div class="v-popper__arrow-outer" />
<div class="v-popper__arrow-inner" />
</div>
</div>
</div>The loading class on the popper element changed from tooltip-loading (default value) to v-popper--tooltip-loading.
Before:
<div class="tooltip tooltip-loading" role="tooltip">
<div class="tooltip-arrow"></div>
<div class="tooltip-inner">Loading...</div>
</div>After:
<div class="v-popper__popper v-popper--theme-tooltip v-popper--tooltip-loading">
<div class="v-popper__wrapper">
<div class="v-popper__inner">
<div>
Loading...
</div>
</div>
<div class="v-popper__arrow-container">
<div class="v-popper__arrow-outer" />
<div class="v-popper__arrow-inner" />
</div>
</div>
</div>On the target element, the has-tooltip (default value) is now v-popper--has-tooltip and is no longer customizable.
Before:
<button class="has-tooltip">After:
<button class="v-popper--has-tooltip">Default slot
The way the default slot works has been simplified. The event listeners (especially focus) and attributes (such as aria-described-by) are now applied to all the top-level elements found in the default slot instead of an internal div.
The component root element now has width: max-content set by default to use the content size instead of the browser default (usually the page width or available space).
Before:
<v-popper> <!-- Listeners & attributes added to internal div -->
<button>Click me!</button>
<button>Hey I'm another button!</button>
<template #popover>
Some info here
</template>
</v-popper>After:
<VDropdown>
<button>Click me!</button> <!-- Listeners & attributes added here -->
<button>Hey I'm another button!</button> <!-- Listeners & attributes added here -->
<template #popper>
Some info here
</template>
</VDropdown>Modifiers
floating-ui doesn't have a modifier system like popperjs. It has been replaced with new props.
Prevent overflow
New props:
preventOverflow(boolean)overflowPadding(px)shiftCrossAxis(boolean)
<!-- Before -->
<VDropdown :popper-options="{
modifiers: { preventOverflow: { enabled: false } }
}" />
<!-- After -->
<VDropdown :prevent-overflow="false" /><!-- Before -->
<VDropdown :popper-options="{
modifiers: { preventOverflow: { options: { padding: 10 } } }
}" />
<!-- After -->
<VDropdown :overflow-padding="10" /><!-- Before -->
<VDropdown :popper-options="{
modifiers: { preventOverflow: { options: { altAxis: true } } }
}" />
<!-- After -->
<VDropdown shift-cross-axis />Flip
New prop:
flip(boolean)
<!-- Before -->
<VDropdown :popper-options="{
modifiers: { flip: { enabled: false } }
}" />
<!-- After -->
<VDropdown :flip="false" />Arrow
New prop:
arrowPadding(px)
<!-- Before -->
<VDropdown :popper-options="{
modifiers: { arrow: { options: { padding: 12 } } }
}" />
<!-- After -->
<VDropdown :arrow-padding="12" />New features
The new package supports Vue 3 in addition to Vue 2.
Themes
Themes are a powerful and simple way to create multiple kinds of floating components. Application usually have many of them: tooltip, dropdown, menus, selects, etc. Each theme specify the default props values or/and the styling through the associated CSS classes.
Themes can extend each other:
app.use(FloatingVue, {
themes: {
select: {
$extend: 'dropdown', // builtin theme
triggers: ['click', 'touch', 'hover', 'focus'],
distance: 6,
delay: 0,
},
'multi-select': {
$extend: 'select',
triggers: ['click', 'touch'],
distance: 10,
},
},
})Global configuration
The global configuration is now simply an object of the popper props (except special properties starting with $ such as $extend and $resetCss, in addition to themes). The values will be used by default.
Unified API
Everything is simpler! The direct and the components now shares the same underlying Popper component with the same props (plus a few specific ones for the directive).
<button v-tooltip="{
triggers: ['click'],
distance: 12,
}">Action</button><VTooltip
:triggers="['click']"
:distance="12"
>
<button>Action</button>
</VTooltip>Built-in components
floating-ui ships with pre-built component and a minimal CSS file to help you get started:
import 'floating-vue/dist/style.css'<!-- 'dropdown' theme -->
<VDropdown>
<button>Click me!</button>
<template #popper>
Nice job!
</template>
</VDropdown>
<!-- 'menu' theme -->
<VMenu>
<button>Hover me!</button>
<template #popper>
More buttons here
</template>
</VMenu>
<!-- 'tooltip' theme -->
<VTooltip>
<button>Hover me!</button>
<template #popper>
Some information
</template>
</VTooltip>Auto min size
You can now let floating vue restrict the popper inner container to the reference size (using min-width or min-height). Usually when creating form inputs such as selects, you probably want to apply the minimum width of the input to the popper.
<VDropdown auto-min-size />Auto max size
You can now let floating vue resize the popper inner container to the available size (using max-width or max-height). It's very useful for a dropdown that should automatically shrink its size when it reaches the boundary.
<VDropdown auto-max-size />Compute Transform Origin
Computes the transform origin of the .v-popper__wrapper to allow zooming effects relative to the reference element.
Example:
<template>
<VDropdown compute-transform-origin />
</template>
<style>
.v-popper__wrapper {
transition: transform .15s;
}
.v-popper__popper.v-popper__popper--hidden .v-popper__wrapper {
transform: scale(.5);
}
</style>
Floating Vue