Exploring the art of div transitions and animations using React and Tailwind CSS

I successfully implemented the sidebar to appear upon clicking the hamburger icon with a transition. However, I am now facing the challenge of triggering the transition when the close button is clicked instead. I have attempted using conditional operations within the render itself, but it did not yield the desired outcome. The code snippet below represents my latest attempt. Any advice on how to achieve this transition would be greatly appreciated. Thank you in advance.

Screenshot Sample

https://i.sstatic.net/DUZxX.gif

Home.jsx


/*
  notes:

  date created: 15/03/2023
*/

import React, { useState, useRef, useEffect } from 'react';
import { Sidebar, UserProfile } from '../components';
import Pins from './Pins';
import { client } from '../client';
import myLogo from '../assets/logoCropped.png';
import { userQuery, fetchUserFromLocalStorage } from '../utils/data';
import { HiMenu } from 'react-icons/hi';
import { AiFillCloseCircle } from 'react-icons/ai';
import { Link, Route, Routes } from 'react-router-dom';

// TODO: added this along the way. continue doing this until it works
const hiddenSidebar = 'fixed w-1/2 bg-black h-screen overflow-y-auto shadow-md z-10 animate-slide-in duration-75';
const activeSidebar = 'bg-red-500 z-10 transition transition-all ';

const Home = () => {

  const [toggleSideBar, setToggleSideBar] = useState(false);
  const [user, setUser] = useState(null);
  const scrollRef = useRef(null);

  // const userInfo = localStorage.getItem('user') !== 'undefined' ? JSON.parse(localStorage.getItem('user')) : localStorage.clear();
  const userInfo = fetchUserFromLocalStorage();

  // set up scroll to be at the top of the sidebar
  useEffect(() => {
    scrollRef.current.scrollTo(0, 0)
  }, [])

  // retrieve data using a query from data.js
  useEffect(() => {
    // sub is the google id
    const query = userQuery(userInfo?.sub)

    client.fetch(query)
      .then((data) => {
        setUser(data[0]);
      })
  })

  return (
    <div className='flex bg-gray-50 md:flex-row flex-col h-screen transition-height duration-75 ease-out'>

      {/* desktop sidebar */}
      <div className='hidden md:flex h-screen flex-initial'>
        <Sidebar user={user && user} />
      </div>

      {/* mobile sidebar */}
      <div className='flex md:hidden flex-row'>
        <div className='p-2 w-full flex flex-row justify-between items-center shadow-md'>
          <HiMenu fontSize={40} className="cursor-pointer" onClick={() => setToggleSideBar(true)} />
          <Link to='/'>
            <img src={myLogo} alt="logo" className='w-16' />
          </Link>
          <Link to={`user-profile/${user?._id}`}>
            <img src={user?.image} alt="logo" className='w-16' />
          </Link>
        </div>

        {
          toggleSideBar && (
            // TODO: modify this
          <div className={toggleSideBar ? hiddenSidebar : activeSidebar}>
            <div className='absolute w-full flex justify-end items-center p-2 '>
              <AiFillCloseCircle fontSize={30} className="cursor-pointer" onClick={() => 
              {
                setToggleSideBar(false)
              }
                } />
            </div>
            <Sidebar user={user && user} closeToggle={setToggleSideBar} />
          </div>
        )} 
      </div>

      {/* routes */}
      <div className='pb-2 flex-1 h-screen overflow-y-scroll' ref={scrollRef}>
        <Routes>
          <Route path="user-profile/:userId" element={<UserProfile />} />
          <Route path='/*' element={<Pins user={user && user} />} />
        </Routes>
      </div>

    </div>
  )
}

export default Home

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
  darkMode: false, // or media or class

  content: [],
  theme: {
    extend: {
      margin: {
        320: '320px',
      },
      width: {
        190: '190px',
        275: '275px',
        300: '300px',
        340: '340px',
        350: '350px',
        656: '656px',
        880: '880px',
        508: '508px',
      },
      height: {
        80: '80px',
        340: '340px',
        370: '370px',
        420: '420px',
        510: '510px',
        600: '600px',
        685: '685px',
        800: '800px',
        '90vh': '90vh',
      },
      flex: {
        0.7: '0.7 1 0%',
      },
      maxHeight: {
        370: '370px',
      },

      // further tweeks
      minWidth: {
        210: '210px',
        350: '350px',
        620: '620px',
      },

      // change this for personalization
      textColor: {
        lightGray: '#F1EFEE',
        primary: '#FAFAFA',
        secColor: '#efefef',
        navColor: '#BEBEBE',
      },

      // change this for personalization
      backgroundColor: {
        mainColor: '#FBF8F9',
        secondaryColor: '#F0F0F0',
        blackOverlay: 'rgba(0, 0 ,0 ,0.7)',
      },
      /*
        TODO: create slide-out keyframne and animation config for tailwindcss
        basically a reverse of slide in
      */ 
      keyframes: {
        'slide-in': {
          '0%': {
            '-webkit-transform': 'translateX(-200px)',
            transform: 'translateX(-200px)',
          },
          '100%': {
            '-webkit-transform': 'translateX(0px)',
            transform: 'translateX(0px)',
          },
        },
        
        // TODO: added this out
        'slide-out': {
          '0%': {
            '-webkit-transform': 'translateX(0px)',
            transform: 'translateX(0px)',
          },
          '100%': {
            '-webkit-transform': 'translateX(-200px)',
            transform: 'translateX(-200px)',
          },
        },

        'slide-fwd': {
          '0%': {
            '-webkit-transform': 'translateZ(0px)',
            transform: 'translateZ(0px)',
          },
          '100%': {
            '-webkit-transform': 'translateZ(160px)',
            transform: 'translateZ(160px)',
          },
        },

        
      },
      animation: {
        'slide-in': 'slide-in 0.5s ease-out',
        'slide-fwd': 'slide-fwd 0.45s cubic-bezier(0.250, 0.460, 0.450, 0.940) both',

        // TODO: added this
        'slide-out' : 'slide-out 0.5s ease-out',
      },
      transitionProperty: {
        height: 'height',
      },
    },
    cursor: {
      'zoom-in': 'zoom-in',
      pointer: "pointer",
    },
  },
  variants: {
    // backgroundColor: ['active']
    extend: {
      
    }
  },


  plugins: [],
};

Answer №1

Eliminate the toggleSideBar condition and only retain the className change that controls the visibility of the menu. If toggleSideBar is false during rendering, the component will be removed without displaying any transition animation.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The issue I'm facing is that the ng-click functionality in Angular JS is not functioning properly when the

Upon loading the page, my JavaScript function creates a tree structure from JSON data and generates a list of anchor tags which look like this: <a ng-click="shareParent(4619)">Some data</a> Despite associating the ng-click directive with the ...

Add the text received from the Ajax request to an array specifically designed for AmCharts

Hello, I'm new to JavaScript and seeking assistance. My goal is to create a chart with real-time data from my MCU, but I'm unsure about pushing a string into an array. Currently, the Array (chart.dataProvider) in this code remains undefined. var ...

Inline display with automatic margin

I am seeking guidance from someone with more experience to help identify the source of this margin. Your assistance is greatly appreciated! https://i.stack.imgur.com/46k7k.png Below is the CSS code in question: .logo-icon { background-image: url(&ap ...

What is the best way to align a div to the bottom of a table cell?

I need help with positioning a div inside a table cell that has 100% height. How can I align this div to the bottom of the cell? Furthermore, there are other divs within the same cell that I would like to position in the middle and at the top. ...

Verify record removal without a PHP click

My website features a navigation menu that streamlines the browsing experience: <form action="../"> <select onchange="window.open(this.options[this.selectedIndex].value,'_top')"> <option value="" selected="selected">Navigate< ...

I'm caught in a never-ending cycle as I navigate through sending information to my Python API and subsequently utilizing that information in the Next.js application to execute the Python script

I am encountering an issue with the response message, getting "Error sending data." The problem seems to arise when trying to retrieve data in server.py that is already specified in the code. For example, instead of using "msg_user", I should use ...

The jqueryMobile Dialog persistently opens during pageshow, despite having the cookie already set

My jQuery mobile dialog keeps opening every time the page is refreshed, despite having a cookie set to open it only once. I can't figure out why it's loading without any triggers. Any assistance would be greatly appreciated. JAVASCRIPT function ...

Steps to prevent button activation until user input is provided and is exactly 5 characters in length

I am looking to make modifications to the code below: <Modal.Body className="modalBody"> Are you sure you want to unsubscribe? <Form> <Form.Control type="text" placeholder="Why do you want to unsubscribe?" ...

The personalized confirmation dialog is experiencing malfunctions

I have designed my own custom dialogs using Bootstrap and jQuery, such as Alert and ConfirmDialog. Here is a sample: http://jsfiddle.net/eb71eaya/ The issue I am facing is that in the callback function, I make an AJAX call. If it returns true, I want to ...

I am looking to append a new value to an array within the state in React

development environment ・ react ・ typescript In this setup, state groups are stored as arrays. If you want to add a group to the array of groups when the onClickGroups function is called, how should you go about implementing it? interface ISearc ...

Material UI Paper component does not extend to full viewport height

My React component includes a Material UI <Paper> component that acts as a background. This <Paper> is nested inside a <ThemeProvider>, which in turn is nested within a <div>, and then further nested inside the <body>. I have ...

Automated navigation to login page following a serverside request on Next.js application router

Seeking advice on how to handle server-side requests to fetch user data authenticated via cookies. Missing details include forwarding cookies through the cookies function (not shown here). If authentication fails with a 401 error, I am looking to redirect ...

The MUI DataGrid Pagination has been replaced due to an error: validateDOMNesting(...): <td> should not be nested within a <div>

I'm struggling with replacing the pagination in my DataGrid component from Material-UI. Every time I try, I encounter this console error: Warning: validateDOMNesting(...): <td> cannot appear as a child of <div> I've double-checked my ...

Establish the starting value for the material ui select component

One issue I'm facing is with a TextField in Material UI used as Select. While the MenuItems are functioning correctly in the form, I am struggling to pre-select an option based on data stored in a previously populated state. For instance, I have this ...

Utilizing iOS Local Storage for Efficient Form Submission Handling

I feel like my brain is on the verge of exploding. I just can't seem to get this to work as intended, and I'm struggling to pinpoint the issue. Currently, I have a form that needs to be processed using AJAX. Before proceeding with that, I want ...

Basic AngularJS framework with minimal external dependencies

I have been searching for an AngularJS skeleton to set up my project, but it seems like all the skeletons I find online require the installation of numerous dependencies through npm and/or bower. Due to security concerns at the firm where I am working on ...

Adjust the alignment of the text to match the orientation of the image

When creating a layout with text and an image, I want them to be contained within a parent element that has a specified height, such as 100px. The text should adjust to the content, whether it's a short phrase or a lengthy paragraph, without a fixed ...

Discovering whether an image contains a caption with the help of JavaScript

There are various websites that display captions on images in paragraphs, h1 tags, or contained within a div along with the image. I am interested in learning how to determine if an image has an associated caption using JavaScript, especially when the cap ...

Ways to display an image within a div when hovering over a specific element?

I am working on recreating a specific effect found at in the section titled 'Capture and share anything quickly'. The effect involves displaying an image in the right block when hovering over the left text. I have successfully implemented this e ...

Is there a way to trigger a modal popup when hovering over a Bootstrap 5 card?

After coming across a handy template online, I decided to implement a modal pop-up feature when hovering over cards using Bootstrap 5. Here's what I have so far: class SavedEpisodes extends Component { $(function() { $('[data-toggle=&qu ...