React Transition Group slide elements up

Callum Linington picture Callum Linington · Jul 25, 2017 · Viewed 8.1k times · Source

My current version is hiding each row, but it happens too quickly, as you can see here in my codepen. Repro by deleting the top element.

I would prefer if you the events unfolded like this:

  1. Fade out
  2. Slide up

I'm unsure how to do this using CSS transitions and the ReactTransitionGroup

If I can get to the stage that you see the element disappearing, then everything bunching up that would be a great start!!

My transition stuff:

const CustomerList = ({ onDelete, customers }) => {
  return (
    <div class="customer-list">
      <TransitionGroup>
        {customers.map((c, i) => 
          <CSSTransition
            key={i}
            classNames="customer"
            timeout={{ enter: 500, exit: 1200 }}
          >        
            <CustomerRow
              customer={c}
              onDelete={() => onDelete(i, c)}
            />
          </CSSTransition>
        )}  
      </TransitionGroup>
    </div>
  );
}

My CSS:

.customer-enter {
  opacity: 0.01;
}

.customer-enter.customer-enter-active {
  opacity: 1;
  transition: 500ms;
}

.customer-exit {
  opacity: 1;
}

.customer-exit.customer-exit-active {
  opacity: 0.01;
  transition: 1200ms;
}

Update

I've figured out with css you can have two transitions happening in sequence something like this

.something {

  width: 200px;
  height: 100px;
  background-color: black;

  transition: background-color 200ms ease, height 200ms ease 200ms;

}

.something:hover {
  height: 0px;
  background-color: blue;
}

So it is just a case of the <CSSTransition timeout={} /> actually waiting for it...

React Update

I have the "effect" working.... see codepen

But, obviously here, the elements still remain, which isn't the right functional behaviour

Answer

Callum Linington picture Callum Linington · Jul 25, 2017

So, I asked this question on the Github repo for this library, and got a reply with a proper working version. Until the guy who responded posts an answer here, I want to share his answer.

Hi there, you have two issues with the codepen. The first is you aren't using a stable key for your list items, so removing something in the middle of the list won't work right. The second is that your setup is correct, and the timeout is working and the animation is playing, but you don't see the animation for height play because you can't animate from height: auto with plain css transitions.

here https://codepen.io/anon/pen/dzPvEO?editors=0110 is a working pen but it requires setting an explicit hieght on the items (max-height isn't enough). One way of dealing with this neatly in a dynamic manner is to use the onExit callback to measure and set the height on the exiting item so it has an explicit height set while exiting

So the first thing was setting a more consistent key property value:

<CSSTransition
    key={c.name}
    classNames="customer"
    timeout={{ enter: 500, exit: 700 }}
>        
    <CustomerRow
        customer={c}
        onDelete={() => onDelete(i, c)}
    />
</CSSTransition>

Secondly was to make sure I set a height on the containing div class.