ElemeFE / element

A Vue.js 2.0 UI Toolkit for Web
https://element.eleme.io/
MIT License
54.12k stars 14.64k forks source link

[Bug Report] el-collapse-transition: overflow not reset when switching to fast #15792

Open aure-olli opened 5 years ago

aure-olli commented 5 years ago

Element UI version

2.9.0

OS/Browsers version

Chrome

Vue version

2.6.10

Reproduction Link

https://jsfiddle.net/aurelienlt89/mp27wuhb/10/

Steps to reproduce

Click on the "Try" button

What is Expected?

The overflow should be reset to its original value (undefined)

What is actually happening?

The overflow stays to "hidden"

This is due to the functions enter and beforeLeave not checking the state while saving the current overflow in oldOverflow. Because of that, oldOverflow is set to "hidden" when it should be untouched because in transition already. It is also the case for other saved styles: padding-top and padding-bottom

aure-olli commented 5 years ago

This fixes it

import { addClass, removeClass } from 'element-ui/src/utils/dom';

class Transition {
  beforeEnter(el) {
    addClass(el, 'collapse-transition');
    if (!el.dataset) el.dataset = {};

    if (!('oldPaddingTop' in el.dataset)) {
      el.dataset.oldPaddingTop = el.style.paddingTop;
      el.dataset.oldPaddingBottom = el.style.paddingBottom;
    }

    el.style.height = '0';
    el.style.paddingTop = 0;
    el.style.paddingBottom = 0;
  }

  enter(el) {
    if (!('oldOverflow' in el.dataset)) {
      el.dataset.oldOverflow = el.style.overflow;
    }
    if (el.scrollHeight !== 0) {
      el.style.height = el.scrollHeight + 'px';
      el.style.paddingTop = el.dataset.oldPaddingTop;
      el.style.paddingBottom = el.dataset.oldPaddingBottom;
    } else {
      el.style.height = '';
      el.style.paddingTop = el.dataset.oldPaddingTop;
      el.style.paddingBottom = el.dataset.oldPaddingBottom;
    }
    delete el.dataset.oldPaddingTop;
    delete el.dataset.oldPaddingBottom;

    el.style.overflow = 'hidden';
  }

  afterEnter(el) {
    // for safari: remove class then reset height is necessary
    removeClass(el, 'collapse-transition');
    el.style.height = '';
    el.style.overflow = el.dataset.oldOverflow;
    delete el.dataset.oldOverflow;
  }

  beforeLeave(el) {
    if (!el.dataset) el.dataset = {};
    if (!('oldPaddingTop' in el.dataset)) {
      el.dataset.oldPaddingTop = el.style.paddingTop;
      el.dataset.oldPaddingBottom = el.style.paddingBottom;
    }
    if (!('oldOverflow' in el.dataset)) {
      el.dataset.oldOverflow = el.style.overflow;
    }

    el.style.height = el.scrollHeight + 'px';
    el.style.overflow = 'hidden';
  }

  leave(el) {
    if (el.scrollHeight !== 0) {
      // for safari: add class after set height, or it will jump to zero height suddenly, weired
      addClass(el, 'collapse-transition');
      el.style.height = 0;
      el.style.paddingTop = 0;
      el.style.paddingBottom = 0;
    }
  }

  afterLeave(el) {
    removeClass(el, 'collapse-transition');
    el.style.height = '';
    el.style.overflow = el.dataset.oldOverflow;
    el.style.paddingTop = el.dataset.oldPaddingTop;
    el.style.paddingBottom = el.dataset.oldPaddingBottom;
    delete el.dataset.oldOverflow;
    delete el.dataset.oldPaddingTop;
    delete el.dataset.oldPaddingBottom;
  }
}

export default {
  name: 'ElCollapseTransition',
  functional: true,
  render(h, { children }) {
    const data = {
      on: new Transition()
    };

    return h('transition', data, children);
  }
};
stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

aure-olli commented 4 years ago

Is there any reason to not apply this patch ?

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

iNeoO commented 2 years ago

I up this again since someone provided a solution