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

Content rendered via v-popup flickers #103

Closed
kellym opened this issue Feb 16, 2018 · 7 comments
Closed

Content rendered via v-popup flickers #103

kellym opened this issue Feb 16, 2018 · 7 comments

Comments

@kellym
Copy link

kellym commented Feb 16, 2018

When content is rendered via v-tooltip, its positioning is correct on initial render. However, when using v-popup to render content, there is a clear tick of the content being incorrectly positioned before it corrects itself. This is most obvious when there is no opacity transition set for the tooltips.

I'm trying to investigate, but it may take me longer to isolate than someone else.

@4ver
Copy link
Contributor

4ver commented Feb 23, 2018

Having the same issue with the v-popover component.

Edit: Example

@sarahdayan
Copy link

sarahdayan commented Feb 23, 2018

Having the same issue with v-popover. The position doesn't change (the top and left CSS properties don't move at all) but there clearly is a "jump".

See bug in action

@4ver
Copy link
Contributor

4ver commented Mar 5, 2018

@Akryum Have looked into this but can't find the root of the problem 😢 any ideas?

@kellym
Copy link
Author

kellym commented Mar 5, 2018

I hate to say this, but my solution was to roll my own popover component. It seems isolated to popover and not to the tooltip directive. It ended up looking something like this:

<template>
  <div v-tooltip="opts" ref="tooltip">
    <slot />
    <div ref="content" v-show="false">
      <slot name="tooltip"></slot>
    </div>
  </div>
</template>
<script>
export default {
  props: ['options'],
  data() {
    return {
      template: ''
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.template = this.$refs.content && this.$refs.content.innerHTML;
    });
  },
  updated() {
    this.template = this.$refs.content && this.$refs.content.innerHTML;
  },
  computed: {
    opts() {
      return Object.assign({ content: this.template }, this.options);
    }
  }
};
</script>

@4ver
Copy link
Contributor

4ver commented Mar 5, 2018

Mad. Thanks so much for the message @kellym!

TBH, I ended up writing my own tooltip directive too

Did you use popper for your own tooltip directive? Be great to see it on github at some point 😄

@kellym
Copy link
Author

kellym commented Mar 5, 2018

Did you use popper for your own tooltip directive?

You know, I spent several hours trying to use popper but cleaner handling for dynamic content wasn't in npm yet (it was in master, but there was no recent release), which made me hesitate on the project for production use. I ended up going with tether because despite its "lack of maintenance" it ended up being more capable.

I'll probably revisit popper if I see some releases come down the pipeline, though.

@thomicdk
Copy link

I did some investigation, and found the popper offset (size) was wrong when popper.js was doing its first update. The size was very small, which suggests the popper element was empty. This results in the initial position of the popper to be wrong. My guess is Vue is not done rendering the content of the popover node at this point, but once it is, popper.js detects the change, calculates a new (correct) position which we see as a blink/flicker.

Then I started playing around, and almost accidentally stumbled upon a workaround, that removes the initial flickering. I call it a workaround, because I'm not sure whether it's actually a valid fix to the problem?

The "fix": The <v-popover> component uses inline styling to toggle the display property to show/hide the popover (source). If I change it to toggling the visibility property instead of display, the flickering is gone!

<div ref="popover"
     :style="{ visibility: isOpen ? 'visible' : 'hidden' }"

Here is a copy/paste-able patch. Please try it out, and tell me if it works for you guys?

import Vue from 'vue';
import VTooltipPlugin from 'v-tooltip';

Vue.use(VTooltipPlugin);

applyVTooltipPatch();

/**
 * Patch to fix flickering issue:
 * https://github.com/Akryum/v-tooltip/issues/103
 * Tested with v-tooltip 2.0.0-rc.31
 */
function applyVTooltipPatch() {
    const comp = Vue.component("v-popover");
    comp.options.render = function() {
        var _vm = this;var _h = _vm.$createElement;var _c = _vm._self._c || _h;return _c('div', { staticClass: "v-popover", class: _vm.cssClass }, [_c('span', { ref: "trigger", staticClass: "trigger", staticStyle: { "display": "inline-block" }, attrs: { "aria-describedby": _vm.popoverId } }, [_vm._t("default")], 2), _vm._v(" "), _c('div', { ref: "popover", class: [_vm.popoverBaseClass, _vm.popoverClass, _vm.cssClass], style: {
            /* ==== PATCH START ==== 
             * Original:
             *   display: _vm.isOpen ? '' : 'none'
             */
            visibility: _vm.isOpen ? 'visible' : 'hidden'
            /* ==== PATCH END ==== */
        }, attrs: { "id": _vm.popoverId, "aria-hidden": _vm.isOpen ? 'false' : 'true' } }, [_c('div', { class: _vm.popoverWrapperClass }, [_c('div', { ref: "arrow", class: _vm.popoverArrowClass }), _vm._v(" "), _c('div', { ref: "inner", class: _vm.popoverInnerClass, staticStyle: { "position": "relative" } }, [_c('div', [_vm._t("popover")], 2), _vm._v(" "), _vm.handleResize ? _c('ResizeObserver', { on: { "notify": _vm.$_handleResize } }) : _vm._e()], 1)])])]);
    }
}

4ver added a commit to 4ver/v-tooltip that referenced this issue Mar 15, 2018
4ver added a commit to 4ver/v-tooltip that referenced this issue Mar 15, 2018
Akryum pushed a commit that referenced this issue May 6, 2018
@Akryum Akryum closed this as completed May 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants