ember-power-select icon indicating copy to clipboard operation
ember-power-select copied to clipboard

Top dropdown position shifted

Open sebastianhelbig opened this issue 8 years ago • 6 comments

Couldn't find an issue about that, altough I have been noticing it for quite some time:

When the dropdown opens on top, it is shifted 1px to the bottom. It fixes itself after scrolling on the page. You can see on the first screen that the top border of the trigger is behind the dropdown. This is visible on ember-power-select.com. Tested with current Opera and Chrome on OS X.

After open: 2017-05-19 01-57-22

After scroll on page: 2017-05-19 01-57-56

sebastianhelbig avatar May 19 '17 00:05 sebastianhelbig

Actually I noticed it too but It's not clear to me why it happens. I dedicated like 1h to find but I couldn't and it never bothered me enough to keep digging, as I tent to use a CSS theme where the content is ~4px away of the box (like the bootstrap one) and the bug is not noticeable.

cibernox avatar May 19 '17 12:05 cibernox

I labeled as a bug but I don't expect to have time to debug this anytime soon as I am between homes (🏡 🚚 📦📦📦)

cibernox avatar May 19 '17 12:05 cibernox

I have noticed, that algorithm for calculation position doesn't include border width for first render. E.g. when I have changed ember-power-select-dropdown border width from : from border-top: 1px solid #aaa; to border-top: 15px solid #aaa;

And for first render it has top: 448.75px; inline style. And after mouse scroll and re-render position changed to top: 433.75px;.

So, 448.75 - 433.75 = 15 - border width.

image

@cibernox - Can you suggest how to fix this? It is issue related to ember-power-select addon or to ember-basic-dropdown?

lesyk-lesyk avatar Oct 17 '17 08:10 lesyk-lesyk

Actually this is a bug that has bothered me for a long time but I don't know why on first render it doesn't take into account the border. What I can is point you to where the position is calculated, which is not in this repo but in ember-basic-dropdown: https://github.com/cibernox/ember-basic-dropdown/blob/master/addon/utils/calculate-position.js#L28

@okachynskyy If you are able to find what exactly makes the positioning function ignore the border only on first render I'd be super happy!

cibernox avatar Oct 17 '17 08:10 cibernox

@cibernox, I have some thoughts. I have added a debuggers on start and finish at _appendToDestination() method from wormhole addon like this:

  _appendToDestination() {
    debugger;
      ...
    debugger;
  },

I have noticed, that at the start of this function (first debugger) dropdown content initially renders at ember-basic-dropdown-content-wormhole-origin container (like in-place behavior), and it does not have any content--below or content--above classes, and at the end of this function (second debugger) dropdown content also doesn't have this classes, but at his moment content is already positioned above trigger. So, after that our addon have added a content--above class with border-top, and so content is shifted down for 1 pixel. During scroll - recalculation works fine because we already have content--above class with 1px border. That`s mean any styles which we add or remove after positioning above trigger cause dropdown shifting, e.g. borders, list items padding, etc.

E.g. - if you have your trigger on the save level with ul tag,

<div class="parent">
  {{#power-select}}{{/power-select}}
  <ul>
    <li></li>
  </ul>
</div>

and you have some sass styles like

.parent {
  ul {
    li {
      padding: 10px;
    }
  }
}

i.e. without classes/ids, only tag selectors Power select items will be rendered with 10px padding for first time (inside ember-basic-dropdown-content-wormhole-origin), and ember-basic-dropdown-content will have a big height and top style will be calculated including this padding (but no more than max-height: 224px; by default), and after moving content from .parent .ember-basic-dropdown-content-wormhole-origin to ember-basic-dropdown-wormhole styles from .parent will not be applied, but top inline style value still will be like before moving, and dropdown will be shifted, and again, page scroll run recalculate position and dropdown content will be rendered good.

P/s: one more example Just add this styles to app.scss to fresh project with dropdown:

.ember-basic-dropdown-content-wormhole-origin {
  .ember-power-select-dropdown {
    border-top: 100px solid red;
  }
}

.ember-power-select-options[role="listbox"] {
  max-height: none;
}

And you will see shifted dropdown for 99 pixels above trigger without red border. Because it initially renders with border-top inside ember-basic-dropdown-content-wormhole-origin container, then addon calculates content height including this border, and after that dropdown will be moved to ember-basic-dropdown-wormhole, border-top disapear, but calculating top value still includes 100px border-top. After that addon adds class with border top 1px and we have 100 - 1 = 99px;

lesyk-lesyk avatar Oct 17 '17 20:10 lesyk-lesyk

@okachynskyy thanks for dissecting the issue. I think that the reason why the above/below class is not present is because we don't know if the content is going to fit until we measure things, but at the same time if we measure things without the class we might be ignoring the changes in the dimmensions that adding those classes can cause.

I'll check if if there is a way of doing it. If I find that there is no way, or the fix would be too expensive (causing a render reflow) an scape valve would be to, instead of adding a border, make the border be always there but changing the color from transparent to solid.

cibernox avatar Oct 18 '17 07:10 cibernox