Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tooltip+popover): ability to programmatically show and hide tooltip and popover #1366

Merged
merged 19 commits into from
Nov 20, 2017
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/form-textarea/form-textarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
directives: [
{ name: 'model', rawName: 'v-model', value: t.localValue, expression: 'localValue' }
],
domProps: { value: t.value },
attrs: {
id: t.safeId(),
name: t.name,
Expand Down
190 changes: 184 additions & 6 deletions src/components/popover/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ export default {
'topright', 'top', 'topleft',
'bottomright', 'bottom', 'bottomleft',
'righttop', 'right', 'lefttop',
'rightbottom', 'left', 'leftbottom'
'rightbottom', 'left', 'leftbottom',
'auto'
]
}
}
Expand All @@ -226,14 +227,172 @@ export default {
| `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`, `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.
| `placement` | `'auto'` | Positioning of the popover, relative to the trigger element. | `auto`, `top`, `bottom`, `left`, `right`, `topleft`, `topright`, `bottomleft`, `bottomright`, `lefttop`, `leftbottom`, `righttop`, `rightbottom`
| `sync` | `false` | Programmatic control of the Popover display state. Recommended to use with [sync modifier](https://vuejs.org/v2/guide/components.html#sync-Modifier). | `true`, `false`
| `triggers` | `'click'` | Space separated list of which event(s) will trigger open/close of popover using built-in handling | `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. Can also be specified as an object in the form of `{ show: 100, hide: 400 }` allowing different show and hide delays | `0` and up, integers only.
| `offset` | `0` | Number of pixels to shift the center of the popover. Also affects the position of the popover arrow. | Any negative or positive integer
| `container` | `null` | String ID of element to append rendered popover into. If `null` or element not found, popover is appended to `<body>` (default) | Any valid in-document unique element ID.


### Programmatically show and hide popover

You can manually control the visibility of a popover via the syncable Boolean `show` prop.
Setting it to `true` will show the popover, while setting it to `false` will hide the popover.

```html
<template>
<div class="d-flex flex-column">
<div class="p-2">
<b-btn id="popoverButton-sync" variant="primary">I have a popover</b-btn>
</div>
<div class="p-2">
<b-btn class="px-1" @click="show = !show">Toggle Popover</b-btn>

<b-popover :show.sync="show" target="popoverButton-sync" placement="right" title="Popover">
Hello <strong>World!</strong>
</b-popover>
</div>
</div>
</template>
<script>
export default {
data: {
show: false
}
}
</script>

<!-- popover-show-sync.vue -->
```

Programmatic control can also be affected by submitting `'open'` and `'close'` events to the popover by reference.

```html
<template>
<div class="d-flex flex-column">
<div class="p-2">
<b-btn id="popoverButton-event" variant="primary">I have a popover</b-btn>
</div>
<div class="p-2">
<b-btn class="px-1" @click="onOpen">Open</b-btn>
<b-btn class="px-1" @click="onClose">Close</b-btn>
</div>

<b-popover ref="popover" target="popoverButton-event" placement="right" title="Popover">
Hello <strong>World!</strong>
</b-popover>
</div>
</template>
<script>
export default {
methods: {
onOpen() {
this.$refs.popover.$emit('open')
},
onClose() {
this.$refs.popover.$emit('close')
}
}
}
</script>

<!-- popover-show-event.vue -->
```

To make the popover shown on initial render, simply add the `show` prop
on `<b-popover>`:

```html
<div class="text-center">
<b-btn id="popoverButton-open" variant="primary">Button</b-btn>

<b-popover show target="popoverButton-open" title="Popover">
I start <strong>open</strong>
</b-popover>
</div>

<!-- popover-show-open.vue -->
```

A popover which is opened via the 'show' property or by an event call can only be
closed by an event call. Built-in triggers will not work... until a trigger event
tries to open the popover even though it is already open. In the below example, when
the leftmost Popover is opened with the 'open' event, it will take two on-button
clicks to close it. Play with the below demo to understand this. When you desire
graceful handling of both programmatic control external to the Popover component as
well as user interaction triggers, you should disable built-in triggers and handle
control yourself as demonstrated by the rightmost Popover.

```html
<template>
<div class="d-flex flex-column">
<div class="p-2">
<b-btn id="exPopoverManual1" variant="primary" ref="button">
Unreliable
</b-btn>
<b-popover target="exPopoverManual1"
:show.sync="pop1"
triggers="click"
placement="right"
ref="popover1">
I can be stubborn sometimes.
</b-popover>
</div>
<div class="p-2">
<b-btn id="exPopoverManual2" variant="primary" ref="button" @click="pop2 = !pop2">
Comfortably Numb
</b-btn>
<b-popover target="exPopoverManual2"
:show.sync="pop2"
triggers=""
placement="right"
ref="popover2">
I do believe it's working, good.
</b-popover>
</div>
<div class="p-2">
<b-btn class="px-1" @click="popOpen">
Open
</b-btn>
<b-btn class="px-1" @click="popClose">
Close
</b-btn>
<b-btn class="px-1" @click="popToggle">
Toggle
</b-btn>
</div>
</div>
</template>

<script>
export default {
data: {
pop1: false,
pop2: false
},
methods: {
popOpen() {
this.pop1 = this.pop2 = true;
},
popClose() {
this.pop1 = this.pop2 = false;
},
popToggle() {
this.pop1 = !this.pop1;
this.pop2 = !this.pop2;
}
}
}
</script>
<!-- popover-advanced-caution.vue -->
```

You can also use `$root` events to trigger the showing and hiding of popover(s).
See the **Hiding and showing popovers via $root events** section below for details.


## `v-b-popover` Directive usage

Just need quick popovers without too much markup? Use the
Expand Down Expand Up @@ -433,15 +592,34 @@ small screens can be harder to deal with on mobile devices (such as smart-phones
<!-- popover-advanced-1.vue -->
```

## Closing popovers
You can close all open popovers by emitting the `bv::hide::popover` event on $root:
## Hiding and showing popovers via $root events
You can close (hide) all open popovers by emitting the `bv::hide::popover` event on $root:

```js
this.$root.$emit('bv::hide::popover');
```

To close a specific popover, pass the trigger element's `id` as the first argument:

```js
this.$root.$emit('bv::show::popover', 'my-trigger-button-id');
```

To open (show) a specific popover, pass the trigger element's `id` as the first argument when
emitting the `bv::show::popover` event:

```js
this.$root.$emit('bv::show::popover', 'my-trigger-button-id');
```

These events work for both the component and directive versions of popover.

Note the trigger element must exist in the DOM and be in a visible state in order for the
popover to show.


## Accessibility
Popovers, in their current state, are not overly accessible when used as interactive
Popovers, in their current implementation, are not overly accessible when used as interactive
components. Content may not be activly read to screen reader users, and the popover
markup not be located close to the trigger element in the DOM (as popovers usually
get appended to the end of `<body>`).
Expand Down
2 changes: 1 addition & 1 deletion src/components/popover/popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default {
},
placement: {
type: String,
default: 'right'
default: 'auto'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bootstrap V4 uses a default of 'right' for their popovers.

Copy link
Member Author

@tmorehouse tmorehouse Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I was never overly fond of it being 'right', unless the trigger element is on the far left.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine to match Bootstrap V4, I fussed with it after noticing the docs didn't match the actual as-defined default. I'll change it to match V4.

}
},
methods: {
Expand Down
68 changes: 66 additions & 2 deletions src/components/tooltip/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,51 @@ The default position is `top`. Positioning is relative to the trigger element.
| `container` | `null` | String ID of element to append rendered tooltip into. If `null` or element not found, tooltip is appended to `<body>` (default) | Any valid in-document unique element ID.


### Programmatically show and hide tooltip

You can manually control the visibility of a tooltip via the syncable Boolean `show` prop.
Setting it to `true` will show the tooltip, while setting it to `false` will hide the tooltip.

```html
<template>
<div class="text-center">
<b-btn id="tooltipButton-1" variant="primary">I have a tooltip</b-btn>
<br><br>
<b-btn @click="show = !show">Toggle Tooltip</b-btn>

<b-tooltip :show.sync="show" target="tooltipButton-1" placement="top">
Hello <strong>World!</strong>
</b-tooltip>
</div>
</template>
<script>
export default {
data: {
show: true
}
}
</script>

<!-- tooltip-show-sync.vue -->
```

To make the tooltip shown on initial render, simply add the `show` prop
on `<b-tooltip>`:

```html
<div class="text-center">
<b-btn id="tooltipButton-2" variant="primary">Button</b-btn>
<b-tooltip show target="tooltipButton-2">
I start open
</b-tooltip>
</div>

<!-- tooltip-show-open.vue -->
```

You can also use `$root` events to trigger the showing and hiding of tooltip(s).
See the **Hiding and showing tooltips via $root events** section below for details.


## `v-b-tooltip` Directive Usage

Expand Down Expand Up @@ -190,11 +235,30 @@ The `v-b-tooltip` directive makes adding tooltips even easier, without additiona
Refer to the [`v-b-tooltip` documentation](/docs/directives/tooltip) for more information
and features of the directive format.

## Closing tooltips
You can close all open tooltips by emitting the `bv::hide::tooltip` event on $root:
## Hiding and showing tooltips via $root events
You can close (hide) all open tooltips by emitting the `bv::hide::tooltip` event on $root:

```js
this.$root.$emit('bv::hide::tooltip');
```

To close a specific tooltip, pass the trigger element's `id` as the first argument:

```js
this.$root.$emit('bv::show::tooltip', 'my-trigger-button-id');
```

To open a specific tooltip, pass the trigger element's `id` as the first argument when
emitting the `bv::show::tooltip` $root event:

```js
this.$root.$emit('bv::show::tooltip', 'my-trigger-button-id');
```

These events work for both the component and directive versions of tooltip.

Note the trigger element must exist in the DOM and be in a visible state in order for the
tooltip to show.


## Component Reference
25 changes: 22 additions & 3 deletions src/directives/popover/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,15 +375,34 @@ v-b-popover.bottom.hover => Same as above
v-b-popover.bottom.click.html => Show on click and place at bottom with HTML content
```

## Closing all opened popovers
You can close all open popovers by emitting the `bv::hide::popover` event on $root:
## Hiding and showing popovers via $root events
You can close (hide) all open popovers by emitting the `bv::hide::popover` event on $root:

```js
this.$root.$emit('bv::hide::popover');
```

To close a specific popover, pass the trigger element's `id` as the first argument:

```js
this.$root.$emit('bv::show::popover', 'my-trigger-button-id');
```

To open (show) a specific popover, pass the trigger element's `id` as the first argument when
emitting the `bv::show::popover` event:

```js
this.$root.$emit('bv::show::popover', 'my-trigger-button-id');
```

These events work for both the component and directive versions of popover.

Note the trigger element must exist in the DOM and be in a visible state in order for the
popover to show.


## See also
- [`v-b-tooltip` directive](/docs/diretives/tooltip)
- [`v-b-tooltip` directive](/docs/directives/tooltip)
- [`<b-popover>` component](/docs/components/popover)
- [`<b-tooltip>` component](/docs/components/tooltip)

Expand Down
23 changes: 21 additions & 2 deletions src/directives/tooltip/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,13 +302,32 @@ v-b-tooltip="{title: 'Title', placement: 'bottom'}"
```


## Closing all tooltips
You can close all open tooltips by emitting the `bv::hide::tooltip` event on $root:
## Hiding and showing tooltips via $root events
You can close (hide) all open tooltips by emitting the `bv::hide::tooltip` event on $root:

```js
this.$root.$emit('bv::hide::tooltip');
```

To close a specific tooltip, pass the trigger element's `id` as the first argument:

```js
this.$root.$emit('bv::show::tooltip', 'my-trigger-button-id');
```

To open a specific tooltip, pass the trigger element's `id` as the first argument when
emitting the `bv::show::tooltip` $root event:

```js
this.$root.$emit('bv::show::tooltip', 'my-trigger-button-id');
```

These events work for both the component and directive versions of tooltip.

Note the trigger element must exist in the DOM and be in a visible state in order for the
tooltip to show.


## See also
- [`v-b-popover` directive](/docs/directives/popover)
- [`<b-tooltip>` component](/docs/components/tooltip)
Expand Down
Loading