3

I am trying to make a slide out drawer utilizing the npm package react-transition-group. For whatever reason, I cannot seem to get the drawer to slide out from left to right on clicking the additional criteria button. If you can solve this issue without using the package, that is ok too!

Here is the code I am trying to get to work as a React component:

{/* DeveloperSearch.js */}
      <CSSTransition
        in={sidebarClicked}
        appear
        timeout={1000}
        classNames="drawer"
        mountOnEnter
        unmountOnExit
      >
        <div className="DevSearch__additional-search-criteria">
          Additional Search Criteria
          <div className="DevSearch__additional-search-criteria-individual">
            <div
              style={{
                fontSize: '0.8rem',
                marginBottom: '5px',
                fontWeight: 'bold',
              }}
            >
              Only show people who match more than {criteriaMatch}% of all
              search criteria
            </div>
            <input
              className="form-control"
              type="number"
              value={criteriaMatch}
              onChange={(e) => setCriteriaMatch(e.target.value)}
              min={0}
              max={100}
              step={5}
            />
          </div>
        </div>
      </CSSTransition>

I also have a css file that is specifically for the CSS Transition component called DeveloperSearch.css:

.drawer-exit {
  width: 250px;
}

.drawer-exit.drawer-exit-active {
  width: 250px;
  transition: width 1000ms ease-in;
}

.drawer-exit-done {
  width: 0px;
}

.drawer-enter {
  width: 250px;
}

.drawer-enter.drawer-enter-active {
  width: 250px;
  transition: all 1000ms ease-in;
}

Unfortunately, my results are no where near what I was wanting, as the drawer does not seem to slide out at all...

Issue # 1

I also have replicated this issue in a codesandbox that can be found by clicking here. Thanks for your help!

klaurtar1
  • 700
  • 2
  • 8
  • 29

3 Answers3

2

Here is a pure css based solution but this is a bit hacky

  1. Markup
const Drawer = ({ transitionExit, handleExit }) => (
  <div
    onClick={handleExit}
    className={`drawer ${transitionExit ? "exit" : ""}`}
  >
    <p>Home</p>
    <p>About</p>
    <p>Contact</p>
    <p>Close Drawer</p>
  </div>
);

export default function App() {
  const [isOpen, setIsOpen] = useState(false);
  const [transitionExit, setTransitionExit] = useState(false);

  const handleExit = () => {
    setTransitionExit(true);
    setTimeout(() => {
      setIsOpen(false);
      setTransitionExit(false);
      // timeout should be less than animation time otherwise state might still be true
      // after animation ends and drawer appears for few milliseconds
    }, 450);
  };

  return (
    <div className="App">
      <div className="wrapper">
        <div className="sidebar_container">
          <button onClick={() => setIsOpen(true)}>open</button>
        </div>
        {isOpen && (
          <div className={`container ${transitionExit ? "exit" : ""}`}>
            <Drawer handleExit={handleExit} transitionExit={transitionExit} />
          </div>
        )}
      </div>
    </div>
  );
}
  1. CSS
.wrapper {
  height: 90vh;
  max-width: 60vw;
  display: grid;
  grid-template-columns: 30% 70%;
  overflow: hidden;
  margin: 40px;
}

.sidebar_container {
  width: 100px;
  height: 100%;
  background-color: rgb(250, 207, 213);
  padding: 30px;
  position: relative;
  z-index: 30;
}

@keyframes containerTransitionEnter {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
@keyframes drawerTransitionEnter {
  0% {
    opacity: 0;
    left: -10vw;
  }
  100% {
    opacity: 1;
    left: 0vw;
  }
}

@keyframes containerTransitionExit {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
@keyframes drawerTransitionExit {
  0% {
    opacity: 1;
    left: 0vw;
  }
  100% {
    opacity: 0;
    left: -10vw;
  }
}

.container {
  position: relative;
  z-index: 10;
  height: 90vh;
  animation: containerTransitionEnter 0.5s;
}
.drawer {
  box-sizing: border-box;
  position: relative;
  height: 90vh;
  width: 25vw;
  padding: 20px;
  background-color: rgb(4, 118, 156);
  border-right: 1px solid rgba(0, 0, 0, 0.3);
  animation: drawerTransitionEnter 0.5s;
}
p {
  margin-bottom: 10px;
  color: white;
}

.container.exit {
  animation: containerTransitionExit 0.5s;
}

.drawer.exit {
  animation: drawerTransitionExit 0.5s;
}

Here is the link to codesandbox

sathya reddy
  • 707
  • 3
  • 11
  • Solid answer man! Unfortunately, I can not use negative left animations on this issue as it is not on the edge of the page and will mess up the visuals. – klaurtar1 Jul 13 '21 at 00:08
  • I have updated the code according to your codesandbox visuals, if it still doesn't match. Then briefly explain the animation flow and position of elements in the layout. – sathya reddy Jul 13 '21 at 04:52
1

Since you are using react you can use Material UI for this Here

and you can try this in your case

<Drawer
            className={classes.drawer}
            variant=''
            anchor='left'
            open={open}
            classes={{
                paper: classes.drawerPaper,
            }}>
            <div className={classes.drawerHeader}>
                <IconButton onClick={handleDrawerClose}>
                    {theme.direction === 'ltr' ? (
                        <ChevronLeftIcon />
                    ) : (
                        <ChevronRightIcon />
                    )}
                </IconButton>
            </div>
            <Divider />
            <List>
                {arr.map((text, index) => (
                    <ListItem
                        button
                        key={text}
                        onClick={
                            text === 'Home'
                                ? goToHome
                                : text === 'About'
                                ? handleOpenAbout
                                : text === 'Contact'
                                ? goToContact
                                : text == 'Team'
                                ? goToMyTea,
                                : goToDashboard
                        }>
                        <ListItemIcon>
                            {text === 'Home' ? (
                                <HomeIcon />
                            ) : text === 'About' ? (
                                <NoteAddIcon />
                            ) : text === 'About' || text === 'Contact' ? (
                                <ListAltIcon />
                            ) : text === 'Dashboard' ? (
                                <DashboardIcon />
                            ) : (
                                <></>
                            )}
                        </ListItemIcon>
                        <ListItemText primary={text} />
                    </ListItem>
                ))}
            </List>
        </Drawer>
Shivam Suchak
  • 221
  • 3
  • 9
0

You should not delete div that has class="DevSearch__additional-search-criteria drawer-enter-done" from the DOM. In this case, Transition will not work. If you want to delete it, you must use css animation. In this way, after adding div to the DOM, put animation on it to enter as a slider