简体   繁体   中英

Use Css modules add conditional transition styling to my side navigation

I would like to add some transition styling to my side navigation on my app. I am able to do this using normal classes however in this tutorial they use css modules and i am unsure how to do this using css modules.

I would like my nav to glide in and out, at the moment it jumps statically when the onClick function fires - toggleSideDrawer .

I have used this logic but I am not sure if it is doing anything:

className={props.toggleSideDrawer ? classes.SideDrawerOpen : classes.SideDrawer

Essentially i want that when the user clicks the toggle, the transform property switches from translateX(-100%) to translateX(0) but this is not happening.

Side nav code:

import React from "react";
import Logo from "../../Logo/Logo";
import NavigationItems from "../NavigationItems/NavigationItems";
import Backdrop from "../../UI/Backdrop/Backdrop";
import Aux from "../../../hoc/Aux";

import classes from "./SideDrawer.css";

const SideDrawer = props => {
  return (
    <Aux classname={classes.SideDrawer}>
      <Backdrop
        showBackdrop={props.showSideDrawer}
        clicked={props.toggleSideDrawer}
      />
      {props.showSideDrawer && (
        <div
          onClick={props.toggleSideDrawer}
          className={
            props.toggleSideDrawer ? classes.SideDrawerOpen : classes.SideDrawer
          }
        >
          <div className={classes.Logo}>
            <Logo />
          </div>

          <nav>
            <NavigationItems />
          </nav>
        </div>
      )}
    </Aux>
  );
};

export default SideDrawer;

Where the code is used in my Layout component:

import React, { useState } from "react";
import Aux from "../Aux";

import classes from "./Layout.css";
import Toolbar from "../../components/Navigation/Toolbar/Toolbar";
import SideDrawer from "../../components/Navigation/SideDrawer/SideDrawer";

const layout = props => {
  const [showSideDrawer, setShowSideDrawer] = useState(false);

  return (
    <Aux>
      <SideDrawer
        showSideDrawer={showSideDrawer}
        toggleSideDrawer={() => {
          setShowSideDrawer(!showSideDrawer);
        }}
      />
      <Toolbar
        onMenuClick={() => {
          setShowSideDrawer(!showSideDrawer);
        }}
      />
      <main className={classes.mainContent}> {props.children} </main>
    </Aux>
  );
};
export default layout;

CSS:

.SideDrawer {
  position: fixed;
  width: 280px;
  max-width: 70%;
  height: 100%;
  left: 0;
  top: 0;
  z-index: 200;
  background-color: white;
  padding: 32px 16px;
  box-sizing: border-box;
  transform: translateX(-100%);
}
@media (min-width: 500px) {
  .SideDrawer {
    display: none;
  }
}

.Logo {
  height: 11%;
  text-align: center;
}
.SideDrawerOpen {
  position: fixed;
  width: 280px;
  max-width: 70%;
  height: 100%;
  left: 0;
  top: 0;
  z-index: 200;
  padding: 32px 16px;
  box-sizing: border-box;
  background-color: red;
  transform: translateX(0);
  transition: transform 0.3s ease-out;
}

The thing is that you need the element will has the transition rule all the time .

My suggestion is to set a static class which which will hold all the styles and addd another one only for overriding transform to make it move.

Something like that (it uses scss but it's easy to do it with css)

.SideDrawer {
  position: fixed;
  width: 280px;
  max-width: 70%;
  height: 100%;
  left: 0;
  top: 0;
  z-index: 200;
  background-color: white;
  padding: 32px 16px;
  box-sizing: border-box;
  transition: transform .3s ease;
  transform: translateX(-100%);

  &.show {
    transform: translateX(0);
  }
}
export const App = () => {
  const [showSideDrawer, setShowSideDrawer] = useState(false);
  const sidebarClasses = classname([
    styles.SideDrawer,
    {
      [styles.show]: showSideDrawer
    }
  ]);
  const ToggleSidebar = () => {
    return (
      <button onClick={() => setShowSideDrawer(!showSideDrawer)}>
        Toggle Sidebar
      </button>
    );
  };

  return (
    <Fragment>
      <h1>App</h1>
      <div className={sidebarClasses}>
        <div>Sidebar content</div>
        <ToggleSidebar />
      </div>
      <ToggleSidebar />
    </Fragment>
  );
};

https://codesandbox.io/s/xenodochial-framework-04sbe?file=/src/App.jsx

@MoshFeu helped me fix this.

The problem is that you render the drawer only when showSideDrawer so before it becomes true, the sidebar is not in the DOM yet so the transition is not affecting it.

The solution is to keep it in the DOM all the time but toggle. Open class to change the style.

There are libraries that knows to make the transition works even for elements that are not in the DOM but it's a bit more complicated.

code fix for SideDrawer.js without the conditional within the return

class SideDrawer extends Component {
  render() {
    let sideDrawerClass = [classes.SideDrawer];
    // SideDrawer will now be an array  with the side drawer classes and the open class
    if (this.props.showSideDrawer) {
      sideDrawerClass.push(classes.Open);
    }
    return (
      <Aux classname={classes.SideDrawer}>
        <Backdrop
          showBackdrop={this.props.showSideDrawer}
          clicked={this.props.toggleSideDrawer}
        />
        <div
          className={sideDrawerClass.join(" ")}
          onClick={this.props.toggleSideDrawer}
        >
          <div className={classes.Logo}>
            <Logo />
          </div>

          <nav>
            <NavigationItems />
          </nav>
        </div>
      </Aux>
    );
  }
}

export default SideDrawer;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM