Creating expandable card components with React and CSS using accordion functionality

I am currently working on creating a card that will expand its blue footer when the "view details" link is clicked to show lorem text. However, I am encountering an issue where the blue bottom of the card does not expand along with the lorem text. You can view my sandbox here: https://codesandbox.io/s/wonderful-bohr-by01z?file=/src/App.js

App.js:

import { Card, Footer, Header } from "./styles";
import { useState } from "react";

export default function App() {
  const [expanded, setExpanded] = useState(false);

  return (
    <>
      <Card>
        <Header>last viewed: {null}</Header>
        <Footer>
          <span onClick={() => setExpanded(!expanded)}>View Details</span>
          {expanded && (
            <div className="accodion">
              Lorem, ipsum dolor sit amet consectetur adipisicing elit. Eos,
              facilis. Lorem, ipsum dolor sit amet consectetur adipisicing elit.
              Eos, facilis. Lorem, ipsum dolor sit amet consectetur adipisicing
              elit. Eos, facilis. Lorem, ipsum dolor sit amet consectetur
              adipisicing elit. Eos, facilis.
            </div>
          )}
        </Footer>
      </Card>
    </>
  );
}

styles.js:

import styled from "styled-components";

const Card = styled.div`
  background-color: ${({ isEmpty }) => (isEmpty ? "#FAFAFA" : "white")};
  height: 100%;
  border-radius: 20px;
  box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  margin: 8px;
`;

const DropDown = styled.div`
  background-color: lightblue;
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
`;

const Header = styled.div`
  display: flex;
  justify-content: space-between;
  margin-top: -40;
  font-size: 10px;
  color: #7894b0;
  margin: 16px;
`;
const Footer = styled.div`
  background-color: rgb(242, 247, 251);
  width: 100%;
  height: 50px;
  font-size: 12px;
  line-height: 12px;
  color: #4f4f4f;
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
  cursor: pointer;

  .accodion {
    padding: 30px;
  }
`;

export { Card, Header, Footer, DropDown };

Answer №1

To solve this problem, you need to add an additional switch class .show and use useRef to get the height of the current footer. You should also add a second useState to store the entire height of the footer. Check out this sandbox example.

Styled-components

const Card = styled.div`
  background-color: ${({ isEmpty }) => (isEmpty ? '#FAFAFA' : 'white')};
  height: 100%;
  border-radius: 20px;
  box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  margin: 8px;
`;

const DropDown = styled.div`
  background-color: lightblue;
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
`;

const Header = styled.div`
  display: flex;
  justify-content: space-between;
  margin-top: -40;
  font-size: 10px;
  color: #7894b0;
  margin: 16px;
`;
const Footer = styled.div`
  background-color: rgb(242, 247, 251);
  width: 100%;
  height: 35px; /* changed */
  font-size: 12px;
  line-height: 12px;
  color: #4f4f4f;
  display: flex;
  /* justify-content: center; */
  flex-direction: column;
  align-items: center;
  cursor: pointer;
  transition: all 0.3s ease-in-out; /* added */
  overflow: hidden; /* added */

  span {
    padding: 12px 0;
  }

  .accodion {
    padding: 10px 15px 15px; /* changed */
  }

  &.show {
    height: ${({ setHeight }) => setHeight}px;
  }
`;

App.js

import { Card, Footer, Header } from "./styles";
import { useState, useEffect, useRef } from "react";

export default function App() {
  const [expanded, setExpanded] = useState(false);
  const [accodionHeight, setAccodionHeight] = useState(0);
  const ref = useRef(null);

  const open = () => setExpanded(!expanded);

  useEffect(() => {
    const getHeight = ref.current.scrollHeight;
    setAccodionHeight(getHeight);
  }, [expanded]);

  return (
    <>
      <Card>
        <Header>last viewed: {null}</Header>
        <Footer
          onClick={open}
          className={expanded ? "show" : ""}
          setHeight={accodionHeight}
          ref={ref}
        >
          <span>View Details</span>
          <div className="accodion" ref={ref}>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit. Eos,
            facilis. Lorem, ipsum dolor sit amet consectetur adipisicing elit.
            Eos, facilis. Lorem, ipsum dolor sit amet consectetur adipisicing
            elit. Eos, facilis. Lorem, ipsum dolor sit amet consectetur
            adipisicing elit. Eos, facilis.
          </div>
        </Footer>
      </Card>
    </>
  );
}

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

How can I create a tooltip function in JavaScript/jQuery that uses the "this" keyword?

JSFiddle link: http://jsfiddle.net/lustre/awpnd6L1/1/ I am curious if it's possible to create a JavaScript function that consolidates the mouseenter code for a "More Info" tooltip. Rather than copying the code multiple times, is there a way to stream ...

What is the best way to start with maximum padding when in full screen mode, and then gradually decrease to minimum padding as the browser width decreases?

Trying to adjust my padding with the formula padding-left: clamp( 60px, calc( value - value ), 186px) but struggling to resize it correctly as I reduce my browser width ...

Please send the element that is specifically activated by the onClick function

This is the HTML code I am working with: <li class="custom-bottom-list"> <a onClick="upvote(this)"><i class="fa fa-thumbs-o-up"></i><span>upvote</span></a> </li> Here is my JavaScript function for Upvot ...

Is there a way to display the overall count of items in ReCharts?

I'm curious about how to access the additional data items within the 'payload' field of recharts when using material-ui. Despite my efforts to find relevant sources, I have not come across any references pertaining to accessing other group n ...

What could be causing my post request to function properly in POSTMAN but not in my React application?

Here are my POSTMAN headers along with the settings I used to send my POST. It only started working when I switched the Content-Type to application/json. https://i.stack.imgur.com/Xz2As.png https://i.stack.imgur.com/aJtbD.png This pertains to the server ...

styled-components is incompatible with material-ui

I have a question regarding the difference between these two methods of styling: import { styled } from "@mui/system"; and import styled from "styled-components"; --------------------------- Hello everyone, I am currently working o ...

Instantiate a fresh Date object in JavaScript by passing in my specific parameter

Check out this code snippet: $(function () { var timestamp = 1443563590; //Tue, 29 Sep 2015 21:53:10 GMT var today2 = moment.unix(timestamp).tz('America/New_York').toString(); alert(today2); //var dateinNewYork = new Date(wh ...

My PHP errors and success messages are not being displayed properly after an AJAX success

After making an AJAX call to submit a form, I would like to display either the PHP success message or error message upon completion. This is my current AJAX success function: success: function (data) { resultSuccess = $(data).find("#success") ...

What is the best way to keep a header row in place while scrolling?

I am looking to keep the "top" row of the header fixed or stuck during page scrolling, while excluding the middle and bottom rows. I have already created a separate class for the top row in my header code: view image description ...

Issue arises when component keeps re-rendering every time new data is received from the socket

Having an issue with rendering in React when subscribing to a socket.io event. The data comes in every 300ms as an array of objects, and my component gets re-rendered each time the data arrives from the socket, regardless of whether it's the same or d ...

Each keystroke is saved individually in an array, thanks to React, instead of storing the entire text

Hey everyone, I have a task to develop a full-stack web application that allows users to create meals with ingredients, preparation details, and cooking time. I am using MongoDB, Node.js, Express, and React for this project. Everything works fine when test ...

Importing libraries in TypeScript and JavaScript are not done in the same manner

As I create my own library, I aim for it to be compatible with both javascript and typescript. tsconfig.json { "compilerOptions": { "target": "es2017", "module": "commonjs", &qu ...

In Javascript, navigate to a specific section by scrolling down

Currently, I am in the process of enhancing my portfolio website. My goal is to incorporate a CSS class once the user scrolls to a specific section on the page. (I plan to achieve this using a JavaScript event). One approach I am considering is initially ...

How can I capture the 'ended' event from an HTML5 video tag using Ember in a controller?

I am having an issue with an hbs file that contains an html5 video tag: <video id="externalVideo" controls loop> <source src="../assets/videos/test.mp4" type="video/mp4"> Your browser does not support HTML5 video. </video> I am ...

Utilizing jQuery to send an Ajax GET request for a JSON file

Recently I have begun delving into the world of jQuery and Ajax, attempting to utilize both technologies to retrieve a JSON FILE. Below is the structure of the file: [ { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": f ...

JavaScript scripts are unable to function within an Angular directive's template due to compatibility issues

I'm facing an issue with a directive (function (angular) { 'use strict'; function digest(factory) { var directive = { restrict: 'E', templateUrl: '/js/app/digest/templates/digest.tem ...

Error message encountered: "When fetching JSON data in React Native, the error 'undefined

== UPDATE == I'm facing an issue with fetching a JSON data. I am trying to retrieve a JSON from Google Maps, but it is returning as undefined. Here is the code snippet: const [isLoading, setLoading] = useState(true); const [info, setInfo] = u ...

Guide to showcasing a component in reactjs based on a conditional statement?

Here is an example of code snippet. import React, { Component } from "react"; import Navpills from "./Navpills"; import Home from "./pages/Home"; import About from "./pages/About"; import Blog from "./pages/Blog"; import Contact from ". /pages/Contact"; ...

Enhance Your Search Bar with Ajax and JQuery for Dynamic Content Updates

My goal is to create a search bar that dynamically loads content, but I want the actual loading of content to start only after the user has finished typing. I attempted a version of this, but it doesn't work because it doesn't take into account ...

Do all the data get stored in Next.js SSR caching or just the data that is returned?

Working with an API that offers pagination but lacks the ability to sort data according to client requirements, I had to come up with a workaround. My solution involves fetching all the data from the API within getServerSideProps and returning only a subse ...