Permalink
Browse files

feat(tooltip+popover): Eight new placement options (#1081)

* [tooltip.js]: Add new placement options

* [toolpop mixin] Add new placements

* [ttoltip directive] Add new placement options

* [popover directive] Add new placement options

* [popover component] Docs update

* [ttoltip component] Docs update

* [tooltip directive] Docs update

* [popover directive] docs update

* Update README.md

* Update tooltip.js

* Update README.md
  • Loading branch information...
tmorehouse committed Sep 20, 2017
1 parent b3489d0 commit dae7855bb8b77cb770cf0b87a56647d63c62c2b7
@@ -46,16 +46,16 @@ using the `v-b-popover` directive and enable the `html` modifer if needed._
<h5 class="my-3">Placement</h5>
<b-row>
<b-col md="3" class="py-4 text-center"
v-for="placement in ['top', 'left', 'right', 'bottom']" :key="placement">
<b-col md="4" class="py-4 text-center"
v-for="placement in placements" :key="placement">
<b-btn :id="'exPopover1-'+placement" variant="primary">
{{ placement }}
</b-btn>
<b-popover :target="'exPopover1-'+placement"
:placement="placement"
title="Popover!"
triggers="hover focus"
:content="placement">
:content="`Placement ${placement}`">
</b-popover>
</b-col>
</b-row>
@@ -84,6 +84,19 @@ using the `v-b-popover` directive and enable the `html` modifer if needed._
</b-container>
</template>
<script>
export default {
data: {
placements: [
'topright', 'top', 'topleft',
'bottomright', 'bottom', 'bottomleft',
'righttop', 'right', 'lefttop',
'rightbottom', 'left', 'leftbottom'
]
}
}
</script>
<!-- popover-1.vue -->
```
@@ -94,7 +107,7 @@ using the `v-b-popover` directive and enable the `html` modifer if needed._
| `target` | `null` | String ID of element, or a reference to an element or component, that you want to trigger the popover. **Required** | Any valid, in-document unique element ID, or in-document element/component reference
| `title` | `null` | Title of popover (text only, no HTML). if HTML is required, place it in the `title` named slot | Plain text
| `content` | `null` | Content of popover (text only, no HTML). if HTML is required, place it in the default slot | Plain text
| `placement` | `'top'` | Positioning of the popover, relative to the trigger element. | `top`, `bottom`, `left`, `right`, `auto`
| `placement` | `'top'` | Positioning of the popover, relative to the trigger element. | `top`, `bottom`, `left`, `right`, `auto`, `topleft`, `topright`, `bottomleft`, `bottomright`, `lefttop`, `leftbottom`, `righttop`, `rightbottom`
| `triggers` | `'click'` | Space separated list of which event(s) will trigger open/close of popover | `hover`, `focus`, `click`. Note `blur` is a special use case to close popover on next click.
| `no-fade` | `false` | Disable fade animation when set to `true` | `true` or `false`
| `delay` | `0` | Number of milliseconds to delay showing and hidding of popover | `0` and up, integers only.
@@ -70,7 +70,7 @@ prop does not have this behavior. For simple tooltips, we recommend using the
| ---- | ------- | ----------- | ----------------
| `target` | `null` | String ID of element, or a reference to an element or component, that you want to trigger the tooltip. **Required** | Any valid, in-document unique element ID, element reference or component reference
| `title` | `null` | Content of tooltip (text only, no HTML). if HTML is required, place it in the default slot | Plain text
| `placement` | `top` | Positioning of the tooltip, relative to the trigger element. | `top`, `bottom`, `left`, `right`, `auto`
| `placement` | `top` | Positioning of the tooltip, relative to the trigger element. | `top`, `bottom`, `left`, `right`, `auto`, `topleft`, `topright`, `bottomleft`, `bottomright`, `lefttop`, `leftbottom`, `righttop`, `rightbottom`
| `triggers` | `hover focus` | Space separated list of which event(s) will trigger open/close of tooltip | `hover`, `focus`, `click`. Note `blur` is a special use case to close tooltip on next click, usually used in conjunction with `click`.
| `no-fade` | `false` | Disable fade animation when set to `true` | `true` or `false`
| `delay` | `0` | Number of milliseconds to delay showing and hidding of tooltip | `0` and up, integers only.
@@ -129,7 +129,7 @@ Where `<value>` can be (optional):
- An object containing more complex configuration of popover, See Bootstrap docs for possible values/structure)
Where [modX] can be (all optional):
- Positioning: `top`, `bottom`, `left`, `right`, or `auto` (last one found wins, defaults to `right`)
- Positioning: `top`, `bottom`, `left`, `right`, `auto`, `topleft`, `topright`, `bottomleft`, `bottomright`, `lefttop`, `leftbottom`, `righttop`, or `rightbottom` (last one found wins, defaults to `right`)
- 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
@@ -104,7 +104,7 @@ Where `<value>` can be (optional):
- An object containing more complex configuration of tooltip, See Bootstrap docs for possible values/structure)
Where [modX] can be (all optional):
- Positioning: `top`, `bottom`, `left`, `right`, or `auto` (last one found wins, defaults to `top`)
- Positioning: `top`, `bottom`, `left`, `right`, `auto`, `topleft`, `topright`, `bottomleft`, `bottomright`, `lefttop`, `leftbottom`, `righttop`, or `rightbottom` (last one found wins, defaults to `top`)
- 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
@@ -1,7 +1,7 @@
import Popper from 'popper.js';
import { assign } from '../utils/object';
import { from as arrayFrom } from '../utils/array';
import { closest, select, isVisible, isDisabled, addClass, removeClass, hasClass, setAttr, removeAttr, getAttr, eventOn, eventOff } from '../utils/dom';
import { closest, select, isVisible, isDisabled, getCS, addClass, removeClass, hasClass, setAttr, removeAttr, getAttr, eventOn, eventOff } from '../utils/dom';
import BvEvent from './BvEvent';
const NAME = 'tooltp';
@@ -19,7 +19,31 @@ const AttachmentMap = {
TOP: 'top',
RIGHT: 'right',
BOTTOM: 'bottom',
LEFT: 'left'
LEFT: 'left',
TOPLEFT: 'top',
TOPRIGHT: 'top',
RIGHTTOP: 'right',
RIGHTBOTTOM: 'right',
BOTTOMLEFT: 'bottom',
BOTTOMRIGHT: 'bottom',
LEFTTOP: 'left',
LEFTBOTTOM: 'left'
};
const OffsetMap = {
AUTO: 0,
TOPLEFT: -1,
TOP: 0,
TOPRIGHT: +1,
RIGHTTOP: -1,
RIGHT: 0,
RIGHTBOTTOM: +1,
BOTTOMLEFT: -1,
BOTTOM: 0,
BOTTOMRIGHT: +1,
LEFTTOP: -1,
LEFT: 0,
LEFTBOTTOM: +1
};
const HoverState = {
@@ -58,6 +82,7 @@ const Defaults = {
html: false,
placement: 'top',
offset: 0,
arrowPadding: 6,
container: false,
fallbackPlacement: 'flip',
callbacks: {}
@@ -222,7 +247,7 @@ class ToolTip {
const placement = this.getPlacement();
const attachment = this.constructor.getAttachment(placement);
this.addAttachmentClass(this.constructor.getAttachment(attachment));
this.addAttachmentClass(attachment);
// Create a cancelable BvEvent
const showEvt = new BvEvent('show', {
@@ -233,6 +258,7 @@ class ToolTip {
this.emitEvent(showEvt);
if (showEvt.defaultPrevented) {
// Don't show if event cancelled
this.$tip = null;
return;
}
@@ -244,7 +270,7 @@ class ToolTip {
// Refresh popper
this.removePopper();
this.$popper = new Popper(this.$element, tip, this.getPopperConfig(attachment));
this.$popper = new Popper(this.$element, tip, this.getPopperConfig(placement, tip));
// Transitionend Callback
const complete = () => {
@@ -400,13 +426,15 @@ class ToolTip {
return container === false ? (closest(MODAL_CLASS, this.$element) || body) : (select(container, body) || body);
}
// Will be overritten by popover if neede
addAriaDescribedby() {
// Add aria-describedby on trigger element, without removing any other IDs
let desc = getAttr(this.$element, 'aria-describedby') || '';
desc = desc.split(/\s+/).concat(this.$id).join(' ').trim();
setAttr(this.$element, 'aria-describedby', desc);
}
// Will be overritten by popover if neede
removeAriaDescribedby() {
let desc = getAttr(this.$element, 'aria-describedby') || '';
desc = desc.replace(this.$id, '').replace(/\s+/g,' ').trim();
@@ -722,11 +750,11 @@ class ToolTip {
}, this.$config.delay.hide);
}
getPopperConfig(attachment) {
getPopperConfig(placement, tip) {
return {
placement: attachment,
placement: this.constructor.getAttachment(placement),
modifiers: {
offset: { offset: this.$config.offset || 0 },
offset: { offset: this.getOffset(placement, tip) },
flip: { behavior: this.$config.fallbackPlacement },
arrow: { element: '.arrow' }
},
@@ -743,6 +771,22 @@ class ToolTip {
};
}
getOffset(placement, tip) {
if (!this.$config.offset) {
const arrow = select(Selector.ARROW, tip);
const arrowOffset = parseFloat(getCS(arrow).width) + parseFloat(this.$config.arrowPadding);
switch (OffsetMap[placement.toUpperCase()]) {
case +1:
return `+50%p - ${arrowOffset}px`;
case -1:
return `-50%p + ${arrowOffset}px`;
default:
return 0;
}
}
return parseFloat(this.$config.offset);
}
getPlacement() {
const placement = this.$config.placement;
if (typeof placement === 'function') {
@@ -50,7 +50,7 @@ function parseBindings(bindings) {
} else if (/^nofade$/.test(mod)) {
// no animation
config.animation = false;
} else if (/^(auto|top|bottom|left|right)$/.test(mod)) {
} else if (/^(auto|top(left|right)?|bottom(left|right)?|left(top|bottom)?|right(top|bottom)?)$/.test(mod)) {
// placement of popover
config.placement= mod;
} else if (/^d\d+$/.test(mod)) {
@@ -49,7 +49,7 @@ function parseBindings(bindings) {
} else if (/^nofade$/.test(mod)) {
// no animation
config.animation = false;
} else if (/^(auto|top|bottom|left|right)$/.test(mod)) {
} else if (/^(auto|top(left|right)?|bottom(left|right)?|left(top|bottom)?|right(top|bottom)?)$/.test(mod)) {
// placement of tooltip
config.placement = mod;
} else if (/^d\d+$/.test(mod)) {
@@ -9,9 +9,17 @@ import { observeDom } from '../utils';
const PLACEMENTS = {
top: 'top',
topleft: 'topleft',
topright: 'topright',
right: 'right',
righttop: 'righttop',
rightbottom: 'rightbottom',
bottom: 'bottom',
bottomleft: 'bottomleft',
bottomright: 'bottomright',
left: 'left',
lefttop: 'lefttop',
leftbottom: 'leftbottom',
auto: 'auto'
};

0 comments on commit dae7855

Please sign in to comment.