Tippyjs: AJAX image tooltip with arrow - allow image to be seen inside arrow

Created on 10 Jan 2019  Â·  18Comments  Â·  Source: atomiks/tippyjs

Here is a code pen replicating the issue

It's based on the codepen demo for dynamic animation of image content. The only change is adding arrow: true. On some images (especially lighter images) you can see the arrow is hidden behind the popup. This is the original codepen

💡 question 📄 docs

Most helpful comment

Working example!: https://codepen.io/anon/pen/yGQLLe

Super rough code atm.

Notes:

  • border-radius not working, when using border-radius on the SVG, it doesn't round off the two top corners because that's the clipping, only the bottom two, any ideas?
  • Static. Only places itself in the center. But I'll work on making it dynamic...
  • How to make it work with a round arrow? I'm assuming we can't use a polygon but rather a custom path. That would make it really hard to make dynamic probably (position & size wise)

All 18 comments

There is a comment on line 42 (js file) about this. Remove overflow: hidden from .tippy-tooltip.ajax-theme.

Thank you I spent a while on this and I knew I was missing something. I'll close this.

Wikipedia does something funky by allowing the image to appear inside the arrow. Also I think Twitter does it too. Last time I investigated they were using SVG or something. Anyone want to try to make a demo with that?

Here's what I mean:

img

In the demo, you'll notice the arrow is just the standard black color.

@atomiks here's svg twitter uses for the arrow

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="100" viewBox="0 0 600 200">
  <defs>
    <clipPath id="clipping">
      <polygon points="50,10 60,0 70,10 50,10"></polygon>
    </clipPath>
  </defs>
  <image xlink:href="https://pbs.twimg.com/profile_banners/1513002752/1544211789/600x200" width="600" height="200" clip-path="url(#clipping)"></image>
</svg>

There's also a div 300x190 with the same image as a background.

So should we allow arrowType (or arrow?) to be a string of markup / element so the user can use their own?

Oddly enough I was trying to replicate Wikipedia page previews on some of my markdown notes which led me to this library. Ideally, I wanted to also replicate the image in the arrow, but unless there are other use cases I don't think that the API needs to change for this.

I noticed on Wikipedia the arrow only displays a portion of the image when the tip is below the hovered element and displays the background color when the tip is above the hovered element. One option that crosses my mind would be to create a function like OnArrowShow where you could modify the content of the arrow. This could be useful when the contents of the arrow have to be set dynamically. I think the current simplicity of arrowType and arrow are nice especially for newcomers to the library.

I spent 20 minutes trying to hack the SVG @KubaJastrz posted in the demo but couldn't get it positioned correctly =[

Anyone else want to try?

I can do it when I finally get some free time, so Soonâ„¢

I'm very new to all of this so this may not be the best example but I stole it from wikipedia.

<svg xmlns="http://www.w3.org/2000/svg" width="320" height="200">
    <clipPath id="mwe-popups-mask" transform="matrix(1 0 0 1 0 0)">
    <polygon
        points="0 8, 10 8, 18 0, 26 8, 1000 8, 1000 1000, 0 1000"
    ></polygon>
    </clipPath>
    <image
    href="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Collage_of_Nine_Dogs.jpg/640px-Collage_of_Nine_Dogs.jpg"
    x="0"
    y="-40.5"
    width="320"
    height="281"
    clip-path="url(#mwe-popups-mask)"
    ></image>
    <polyline
    stroke="rgba(0,0,0,0.1)"
    points="0 199 320 199"
    stroke-width="1"
    ></polyline>
</svg>

Here is a codepen rendering it

That's interesting, looks like it's doing an "inverse cut out" of the image instead. It's not an actual separate element. I guess that could work if you don't want a dynamic arrow and just statically place it to the left.

Edit: Maybe you could even modify the clip path values based on what Popper positions the arrow as, allowing you to make it dynamic :o

I looked at it a little more and I simplified it as much as I could while retaining the same effect.

    <!--  width and height are necessary to make the image look pretty  -->
    <!--  these correspond to the original width and height of the image itself  -->
    <svg xmlns="http://www.w3.org/2000/svg" width="320" height="281">
      <clipPath id="arrow-mask">
        <!--   This polygon makes the arrow, the points start from
           the top of the arrow and then wrap around clockwise around the image -->
        <polygon
          points="0 8, 10 8, 18 0, 26 8, 1000 8, 1000 1000, 0 1000"
        ></polygon>
      </clipPath>
      <image
        href="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Collage_of_Nine_Dogs.jpg/640px-Collage_of_Nine_Dogs.jpg"
        width="320"
        height="281"
        clip-path="url(#arrow-mask)"
      ></image>
    </svg>

Is there some kind of visualization tool I can use to modify the values to see the effect?

Check this out I've simply replaced with 1000s with 50s so that it fits on the grid. You can also modify codepen, and get live updates there.

Going to reopen and investigate this technique to see if we can get it working in the demo example. Also, dynamically as well by reading the left/top on a hidden(?) arrow value produced by Popper's positioning

Working example!: https://codepen.io/anon/pen/yGQLLe

Super rough code atm.

Notes:

  • border-radius not working, when using border-radius on the SVG, it doesn't round off the two top corners because that's the clipping, only the bottom two, any ideas?
  • Static. Only places itself in the center. But I'll work on making it dynamic...
  • How to make it work with a round arrow? I'm assuming we can't use a polygon but rather a custom path. That would make it really hard to make dynamic probably (position & size wise)

That's awesome! I can look at those issues later today. For top and bottom you would probably need to generate separate svgs. Wikipedia solves this by using different clippings and then referencing the correct clipping by its id based on where the arrow is going to be positioned i.e. left right, top or bottom. They define the clippings earlier on the page and then reference them in the svg. I simply moved the clipping definition into the svg to simplify it. Not sure about dynamic or border radius.

I don't have time to fix this up right now but in case you're interested these are the different clippings they use.

<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
   <defs>
      <clipPath id="mwe-popups-mask" transform="matrix(1 0 0 1 0 0)">
         <polygon points="0 8, 10 8, 18 0, 26 8, 1000 8, 1000 1000, 0 1000"></polygon>
      </clipPath>
      <clipPath id="mwe-popups-mask-flip">
         <polygon points="0 8, 274 8, 282 0, 290 8, 1000 8, 1000 1000, 0 1000"></polygon>
      </clipPath>
      <clipPath id="mwe-popups-landscape-mask">
         <polygon points="0 8, 174 8, 182 0, 190 8, 1000 8, 1000 1000, 0 1000"></polygon>
      </clipPath>
      <clipPath id="mwe-popups-landscape-mask-flip">
         <polygon points="0 0, 1000 0, 1000 242, 190 242, 182 250, 174 242, 0 242"></polygon>
      </clipPath>
   </defs>
</svg>

I don't know if the dimensions are dynamically generated based on the image but this is for the same image I posted earlier.

If someone wants to make docs for this that would be great

Was this page helpful?
0 / 5 - 0 ratings