DoneDeal0
DoneDeal0

Reputation: 6257

Why does this react-spring animation change its margin-top during an animation?

I have a react-spring animation that consists in make a component appear while sliding. But during this animation, the component change its margin top before going back to normal. How to fix this?

Here is the code & a sandbox:

import React, { useEffect, useMemo, useState } from "react";
import styled, { css, keyframes } from "styled-components";
import { animated, useTransition } from "react-spring";

const Tabs = styled.div`
  display: flex;
  margin-bottom: 12px;
`;

const Tab = styled.button<{ active: boolean }>`
  margin: 0 4px;
  border-bottom: 1px solid transparent;
  font-weight: ${({ active }) => active && 600};
  cursor: pointer;
  background: transparent;
  border: 0;
  &:focus {
    outline: none !important;
  }
`;

export default function Inbox() {
  const [tab, setTab] = useState(0);

  const transitions = useTransition(tab, (p) => p, {
    from: { opacity: 0, transform: "translate3d(100%,0,0)" },
    enter: { opacity: 1, transform: "translate3d(0%,0,0)" },
    leave: { opacity: 0, transform: "translate3d(-50%,0,0)" }
  });

  const getList = (name: string) => <div>{name}</div>;

  const pages = [
    ({ style }) => (
      <animated.div style={style}>{getList("test 1")}</animated.div>
    ),
    ({ style }) => (
      <animated.div style={style}>{getList("test 2")}</animated.div>
    )
  ];

  return (
    <>
      <Tabs>
        <Tab onClick={() => setTab(0)} active={tab === 0}>
          Unread
        </Tab>
        <Tab onClick={() => setTab(1)} active={tab === 1}>
          All
        </Tab>
      </Tabs>
      {transitions.map(({ item, props, key }) => {
        const Page = pages[item];
        return <Page key={key} style={props} />;
      })}
    </>
  );
}

The sandbox: https://codesandbox.io/s/amazing-ride-hwbv2?file=/src/App.tsx

Upvotes: 0

Views: 983

Answers (1)

Peter Ambruzs
Peter Ambruzs

Reputation: 8213

It is not the margin top you see. It is the old component moving to the left side and changing opacity, but it is still there. Finally it is unmounted in that moment the new component is taking its vertical place. Most of the time we use absolute positionig that the old and new components are on top of each other. This way there is no bump at the unmount. Something like this:

from: { opacity: 0, transform: "translate3d(100%,0,0)", position: "absolute" },

Upvotes: 1

Related Questions