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

What steps should I take to enable Google Maps style on mobile devices?

Hi there! I'm having some trouble styling my Google map. Sometimes the style loads correctly in browsers, and sometimes it doesn't. Another issue I've noticed is that when I view the page on mobile platforms like Android Chrome, iOS Safari, ...

I am getting NaN as the output from my function, but I am unsure of the reason behind

For pracitce, I have created this code to calculate the total amount spent on gas and food using arrays. However, I am encountering an issue where it is returning NaN. const gas = [20, 40, 100]; const food = [10, 40, 50]; function total(gas, food) { ...

Creating a button component in React that spans the entire width

I have integrated a logging component in React and need all buttons to be the same width across the available space. You can view my implementation here. Below is the code snippet: export default function Login (props: any) { return( <Box ...

What is the best way to align content at the center on mobile using Bootstrap 5?

I'm struggling to center elements on mobile devices, even though they look fine on desktop. Desktop: https://i.sstatic.net/I6Rtf.png Mobile: https://i.sstatic.net/4a1zS.png Desired mobile: https://i.sstatic.net/uMrEa.png I am using Bootstrap 5.3 ...

Exploring the wonders of React Native Storybook and Nativewind

I have a React Native project that I am working on, and I am trying to utilize storybook for component documentation. However, I'm facing an issue where the nativewind styles do not apply when viewing components in storybook. This results in seeing un ...

Insert a div element into the JavaScript file

I have a JavaScript code snippet that needs to be inserted after the "Artwork" section. Here is the code: <div class="image-upload"> <label for="files"> <img src="ohtupload.jpg"> </label> </di ...

What is the process for importing a JavaScript export file created from the webpack.config file?

Issue at Hand In the process of testing APIs, I encountered a dilemma in setting up either the DEV or Production environment. This involved configuring API endpoints for local testing and preparing them for production use. To achieve this, I utilized NOD ...

tips for utilizing namespaced getter filtering within a Vuex module in vueJs

In my custom module named ShopItemCategory, I have a Getter getters: { shopItemsCategories: state => state.ShopItemsCategories.data, }, Inside the component, there is a computed function I defined computed: { shopItemsCategories ...

Troubleshooting: MongoDB/mongoose post save hook does not execute

My current setup involves the following model/schema: const InvitationSchema = new Schema({ inviter: {type: mongoose.Schema.Types.ObjectId, ref: 'Account', required: true}, organisation: {type: mongoose.Schema.Types.ObjectId, ref: 'Orga ...

What is the proper way to implement an if-else statement within objects?

Is there a way to convert the code below into an object structure so I can access nodID and xID keys from different files? The issue lies in the if statement within the code. My idea is to use export const testConfig = {} and import testConfig into any fil ...

What could be causing the remaining part of the template to not render when using an Angular directive?

After adding my custom directive to a template on an existing page, I noticed that only the directive was rendering and the rest of the template was not showing up as expected. Even though the controller seemed to have executed based on console logs and B ...

During the installation of a package, npm encountered a require stack error with the code MODULE_NOT_FOUND

Whenever I attempt to install something using the npm install command, it throws an error saying "require stack" and "code MODULE_NOT_FOUND" C:\Users\dell>npm audit fix node:internal/modules/cjs/loader:1075 const err = new Error(message); ...

Guide on exporting data from ejs files to a pdf file using pdfkit in a node js environment

Below is the code from my result.ejs file: <div style="width: 50%; margin: auto;"> <table class="table"> <thead> <tr> <th>SUBJECT</ ...

Having trouble with the background condition in the quiz? Try implementing bootstrap for a smooth

I've created a quiz app where users can click on answers. I'm trying to add a green background if the user selects the correct answer, and a red background if they select the wrong answer. The green background is working fine, but for some reason ...

Is there a way for my component to function seamlessly within another component without the need for redundant code?

Is there a way to avoid repeating code when using my component inside another component? For example, in the file NextPage.js, the <LogoutButton/> component does not perform its function. How can I ensure that the <LogoutButton/> behaves the s ...

Creating a vertical bar chart in D3 with a JSON data source embedded within the code

Struggling to generate a stacked bar graph in D3.js. The axes are displaying correctly, but the data on the graph is not showing up. Any suggestions on what could be causing this issue? JS: var svg = d3.select("#recovery__table"), margin = {top: 20, ...

Executing JavaScript code in the Selenium IDE

I'm having trouble figuring out how to execute JavaScript within the Selenium IDE. The objective is to enter text into an input field, with a backend setup that verifies the current time in the input field for testing purposes: Here's the input f ...

Obtaining User Input in React JS within the Fetch Statement

I've written a code to fetch weather data from an API. Currently, the location is set to "chennai" in the link provided. I'd like to make this location user-dependent. How can I achieve this using React? import React,{useState,useEffect} from ...

What is the best way to display data retrieved from a GET request in Angular?

Spending too much time on a development issue is causing me frustration. After extensive research, I find myself stuck at this point. The problem lies in making a GET request from a service which is called by a controller. Below is the code for the servi ...

How can I use query to swap out elements within a div when clicked?

I have a project with two separate div classes named demo-heart and demo-coal. The goal is to implement functionality that allows the user to click on the fa-heart icon and have it switch to fa-coal, and vice versa when clicking on fa-coal. <div class ...