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
: useplacement
defaultClass
: removeddefaultTargetClass
: removeddefaultHtml
: usehtml
in thetooltip
theme (or any theme that you use with the directive)defaultTemplate
: removeddefaultArrowSelector
: removeddefaultInnerSelector
: removeddefaultDelay
: usedelay
defaultTrigger
: usetriggers
,showTriggers
,hideTriggers
defaultOffset
: usedistance
and/orskidding
defaultContainer
: usecontainer
defaultBoundariesElement
: useboundary
defaultPopperOptions
: removeddefaultLoadingClass
: removeddefaultLoadingContent
: useloadingContent
in thetooltip
theme (or any theme that you use with the directive)autoHide
: unchangeddefaultHideOnTargetClick
: usehideTriggers
disposeTimeout
: 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:
html
is nowfalse
by default to help you void XSS attacks.
Renamed props:
trigger
totriggers
(see Trigger)show
toshown
boundariesElement
toboundary
classes
topopperClass
The following directive options were also removed:
targetClasses
template
arrowSelector
innerSelector
hideOnTargetClick
(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
:
showTriggers
hideTriggers
popperTriggers
showPopperTriggers
hidePopperTriggers
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
boundariesElement
toboundary
open
toshown
openGroup
toshowGroup
popoverClass
topopperClass
Plus the default component slot props:
isOpen
toshown
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
popover
topopper
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-popover
tov-close-popper
Removed props
The following props were removed and are no longer available:
popoverBaseClass
popoverWrapperClass
popoverArrowClass
popoverInnerClass
openClass
modifiers
popperOptions
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-popover
tov-popper
open
(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--shown
andv-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-outer
andv-popper__arrow-inner
.
New classes:
v-popper__arrow-container
- on
v-popper__popper
:v-popper__popper--skip-transition
v-popper__popper--show-from
v-popper__popper--show-to
v-popper__popper--hide-from
v-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>