Permalink
Browse files

feat(tooltips+popovers): Add special blur "exit" trigger (#974)

* feat(tooltips+popovers): Add special blur "exit" trigger

Handy iof you want to show  tip on click, but want to close it on click anywhere (trigger element loses focus)

* Update tooltip.js

* Update popover.js

* Update README.md

* Update README.md

* Update README.md

* Update tooltip.js

* Update README.md

* Update README.md

* popover: Allow negative offsets

* tooltip: allow negative offsets

* Update tooltip.js
  • Loading branch information...
tmorehouse committed Aug 31, 2017
1 parent 50613bb commit 785b7a6cb3e23f66309abc0a371226944cec6681
@@ -8,6 +8,20 @@ Popovers are tooltips on steroids.
Use the `v-b-popover` directive on any **element** or **component** where you would
like a popover to appear.
## Overview
Things to know when using popovers:
- Popovers rely on the 3rd party library Popper.js for positioning. It is bundled with Bootstrap-Vue!
- Zero-length title and content values will never show a popover.
- Specify container: 'body' (default) to avoid rendering problems in more complex components (like input groups, button groups, etc).
- 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. Use white-space: nowrap; on your `<a>`s, `<b-link>`s or `<router-link>`s b to avoid this behavior.
- Popovers must be hidden before their corresponding elements have been removed from the DOM.
- When using a client side router, popovers will listen to changes in `$route` and automatically hide.
- Elements that trigger popovers should be in the document tab sequence. Add `tabinded="0"` if rquired.
```html
<template>
<b-container fluid>
@@ -27,7 +41,7 @@ like a popover to appear.
</b-col>
</b-row>
<h5 class="mt-4">Positioning</h5>
<b-row class="text-center3">
<b-row class="text-center">
<b-col md="3" class="py-3">
<b-btn v-b-popover.top="'Popover!'" variant="primary">Top</b-btn>
</b-col>
@@ -108,11 +122,11 @@ Where `<value>` can be (optional):
Where [modX] can be (all optional):
- Positioning: `top`, `bottom`, `left`, `right`, or `auto` (last one found wins, defaults to `right`)
- Event trigger: `click`, `hover`, `focus` (if none specified, defaults to `click`)
- Event trigger: `click`, `hover`, `focus`, `blur` (if none specified, defaults to `click`. The `blur` trigger is a close handler only, and if specified by itself, will be converted to `focus`)
- `nofade` to turn off animation
- `html` to enable rendering raw HTML. by default HTML is escaped and converted to text
- A delay value in the format of `d###` (where `###` is in ms, defaults to 0);
- An offset value in pixels in the format of `o###` (where `###` is the number of pixels, defaults to 0)
- An offset value in pixels in the format of `o###` (where `###` is the number of pixels, defaults to 0. Negative values allowed)
Where [container] can be (optional):
- An element ID (minus the #) to place the popover markup in when visible
@@ -155,5 +169,40 @@ v-b-popover.hover.bottom => Show on hover and place at bottom
v-b-popover.bottom.hover => Same as above
v-b-popover.bottom.click.html => Show on click and place at bottom with HTML content
```
### Dismiss on next click (self dimissing)
Use the `focus` trigger to dismiss popovers on the next click that the user makes.
`focus` also makes the popover activate on both `focus` and `click` (as a click makes
the element receive focus, assuming it is in the tab sequence of the page).
You can, however, specify your trigger as `click` and `blur`, which will make only
click activate the popover, and either a click on the element - _or losing foucus
to another element or part of the document_ - will close the popover.
This `blur` trigger must be used in combination with the `click` trigger.
Th following example shows the `click blur` use case. Popovers will only open on click
of the button, and will close either on click of the button, or a click anywhere else (or
a focus change via pressing the <kbd>TAB</kbd> key). Some call this behavior _self dismising_.
```html
<template>
<b-container fluid>
<b-row class="text-center">
<b-col md="3" class="py-3">
<b-btn v-b-popover.click.blur="'Content'" title="Popover" variant="primary">Click</b-btn>
</b-col>
<b-col md="3" class="py-3">
<b-btn v-b-popover.click.blur="'Content'" title="Popover" variant="primary">Click</b-btn>
</b-col>
<b-col md="3" class="py-3">
<b-btn v-b-popover.click.blur="'Content'" title="Popover" variant="primary">Click</b-btn>
</b-col>
<b-col md="3" class="py-3">
<b-btn v-b-popover.click.blur="'Content'" title="Popover" variant="primary">Click</b-btn>
</b-col>
</b-row>
</b-ccontainer>
</template>
Note: If a title and content are not provided, then the popover will not display.
<!-- popover-2.vue -->
```
@@ -4,7 +4,19 @@
styling and animations. Tooltips can be triggered by hovering, focusing, or clicking an element
Use the `v-b-tooltip` directive on any element or component where you would like a tooltip
to apear.
to appear.
## Overview
Things to know when using tooltips:
- Tooltips rely on the 3rd party library Popper.js for positioning. The library is bundled wit Bootstrap-Vue!
- Tooltips with zero-length titles are never displayed.
- Specify container: 'body' (default) to avoid rendering problems in more complex components (like input groups, button groups, etc).
- Triggering tooltips on hidden elements will not work.
- Tooltips for `disabled` elements must be triggered on a wrapper element.
- When triggered from hyperlinks that span multiple lines, tooltips will be centered. Use white-space: nowrap; on your `<a>`s, `<b-link>`s and `<router-link>`s to avoid this behavior.
- Tooltips must be hidden before their corresponding elements have been removed from the DOM.
```html
<template>
@@ -85,11 +97,11 @@ Where `<value>` can be (optional):
Where [modX] can be (all optional):
- Positioning: `top`, `bottom`, `left`, `right`, or `auto` (last one found wins, defaults to `top`)
- Event trigger: `click`, `hover`, `focus` (if none specified, defaults to `focus` and `hover`)
- Event trigger: `click`, `hover`, `focus`, `blur` (if none specified, defaults to `focus` and `hover`. `blur` is a close handler only, and if specified by itself, will be converted to `focus`)
- `nofade` to turn off animation
- `html` to enable rendering raw HTML. by default HTML is escaped and converted to text
- A delay value in the format of `d###` (where `###` is in ms, defaults to 0);
- An offset value in pixels in the format of `o###` (where `###` is the number of pixels, defaults to 0)
- An offset value in pixels in the format of `o###` (where `###` is the number of pixels, defaults to 0. Negative values allowed)
Where [container] can be (optional)
- An element ID (minus the #) to place the tooltip markup in
@@ -123,4 +135,11 @@ v-b-tooltip.hover.bottom => Show on hover and place at bottom
v-b-tooltip.bottom.hover => Same as above
```
Note: If a title is not provided, then the tooltip will not display.
### Dismiss on next click
Use both `click` and `blur` if you would like a tooltip that opens only on click of
the element, but will close when anything else in the document is clicked or
receives focus.
Note that your elment **must** be in the document tab sequence for this to work. If
your element is not tabable, add the `tabindex="0"` attribute to the element.
@@ -1,5 +1,5 @@
import Popper from 'popper.js';
import { assign } from '../utils/object';
import { assign, keys } from '../utils/object';
import { from as arrayFrom } from '../utils/array';
import { BvEvent } from './';
@@ -43,6 +43,7 @@ const Trigger = {
HOVER: 'hover',
FOCUS: 'focus',
CLICK: 'click',
BLUR: 'blur',
MANUAL: 'manual'
};
@@ -516,6 +517,9 @@ class ToolTip {
} else if (trigger === 'focus') {
this.$element.addEventListener('focusin', this);
this.$element.addEventListener('focusout', this);
} else if (trigger === 'blur') {
// Used to close $tip when element looses focus
this.$element.addEventListener('focusout', this);
} else if (trigger === 'hover') {
this.$element.addEventListener('mouseenter', this);
this.$element.addEventListener('mouseleave', this);
@@ -650,6 +654,11 @@ class ToolTip {
leave(e) {
if (e) {
this.$activeTrigger[e.type === 'focusout' ? 'focus' : 'hover'] = false;
if (e.type === 'focusout' && /blur/.test(this.$config.trigger)) {
// Special case for `blur`: we clear out the other triggers
this.$activeTrigger.click = false;
this.$activeTrigger.hover = false;
}
}
if (this.isWithActiveTrigger()) {
return;
@@ -12,7 +12,8 @@ const BVPO = '__BV_PopOver__';
const validTriggers = {
'focus': true,
'hover': true,
'click': true
'click': true,
'blur': true
};
@@ -58,8 +59,8 @@ function parseBindings(bindings) {
if (delay) {
config.delay = delay;
}
} else if (/^o\d+$/.test(mod)) {
// offset value
} else if (/^o-?\d+$/.test(mod)) {
// offset value (negative allowed)
const offset = parseInt(mod.slice(1), 10) || 0;
if (offset) {
config.offset = offset;
@@ -87,6 +88,10 @@ function parseBindings(bindings) {
// Sanitize triggers
config.trigger = keys(selectedTriggers).join(' ');
if (config.trigger === 'blur') {
// Blur by itself is useless, so convert it to focus
config.trigger = 'focus';
}
if (!config.trigger) {
// remove trigger config
delete config.trigger;
@@ -12,7 +12,8 @@ const BVTT = '__BV_ToolTip__';
const validTriggers = {
'focus': true,
'hover': true,
'click': true
'click': true,
'blur': true
};
// Build a ToolTip config based on bindings (if any)
@@ -57,8 +58,8 @@ function parseBindings(bindings) {
if (delay) {
config.delay = delay;
}
} else if (/^o\d+$/.test(mod)) {
// offset value
} else if (/^o-?\d+$/.test(mod)) {
// offset value. Negative allowed
const offset = parseInt(mod.slice(1), 10) || 0;
if (offset) {
config.offset = offset;
@@ -86,6 +87,10 @@ function parseBindings(bindings) {
// Sanitize triggers
config.trigger = keys(selectedTriggers).join(' ');
if (config.trigger === 'blur') {
// Blur by itself is useless, so convert it to 'focus'
config.trigger = 'focus';
}
if (!config.trigger) {
// remove trigger config
delete config.trigger;

0 comments on commit 785b7a6

Please sign in to comment.