DEV Community

loading...
Cover image for React - create simple animated expander

React - create simple animated expander

Dirask-React
We share coding tips and tricks in React ❀️ πŸ’» πŸ™‚. We help to solve React problems at http://dirask.com
Originally published at dirask.com ・Updated on ・2 min read

Hi there! πŸ‘‹ 😊

Today, I was thinking about creating an animated expander in React and I came up with the following solution. πŸ”½

Before we start, I would highly recommend you to check out runnable examples for the solution on our website:
How to create simple animated expander in React

Effect of this short post:image

In the example below, I've created a simple expander that displays Fruits πŸ‰ and Vegetables πŸ… lists on click event. I've used a modern approach that involves the use of functional components and React hooks. In this case useState hook stores the state of my expander. πŸ”ΊπŸ”»

Practical example:

import React from 'react';

const expanderStyle = {
    margin: '6px 0',
    padding: '2px',
    border: '1px solid #85C1E9'
};

const headerStyle = {
    display: 'flex',
    cursor: 'pointer'
};

const titleStyle = {
    padding: '3px',
    flex: 'none'
};

const spacerStyle = {
    flex: '1'
};

const iconStyle = {
    padding: '3px',
    flex: 'none'
};

const contentStyle = {
    overflow: 'hidden',
    transition: 'all 0.3s'
};

const contentExpandedStyle = {
    ...contentStyle,
    padding: '4px 0',
    border: '1px solid #85C1E9',
    height: 'auto',
    filter: 'opacity(1)'
};

const contentCollapsedStyle = {
    ...contentStyle,
    padding: '0 0',
    border: '1px solid transparent',
    height: '0',
    filter: 'opacity(0)'
};

const Expander = ({title, children}) => {
    const [expanded, setExpanded] = React.useState(false);
    const handleHeaderClick = () => {
        setExpanded(expanded => !expanded);
    };
    return (
      <div style={expanderStyle}>
        <div style={headerStyle} onClick={handleHeaderClick}>
          <div style={titleStyle}>{title}</div>
          <div style={spacerStyle} />
          <div style={iconStyle}>{expanded ? 'πŸ”Ί' : 'πŸ”»'}</div>
        </div>
        <div style={expanded ? contentExpandedStyle : contentCollapsedStyle}>
          {children}
        </div>
      </div>
    );
};

// Usage example:

const App = () => {
  return (
    <div style={{height: '260px'}}>
      <Expander title="🍏🍌🍊 Fruits">
        <ul>
          <li>🍏 Apple</li>
          <li>🍌 Banana</li>
          <li>🍊 Orange</li>
        </ul>
      </Expander>
      <Expander title="πŸ₯•πŸ₯’πŸ… Vegetables">
        <ul>
          <li>πŸ₯• Carrot</li>
          <li>πŸ₯’ Cucumber</li>
          <li>πŸ… Tomato</li>
        </ul>
      </Expander>
    </div >
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

You can run this example here

Let me know if you like it or not in the comment section! 😊


Write to us!

If you have any problem to solve or questions that no one can answer related to a React or JavaScript topic, or you're looking for a mentoring write to us on dirask.com -> Questions

Discussion (2)

Collapse
theonejonahgold profile image
Jonah Meijers

Did you know that you can make an expander using native HTML elements? With <details> and <summary> you don’t need any JavaScript to create the same result as above. With CSS you can style all parts of the details element, including the little dropdown arrow.

It’s sadly not animatable as the example you’re displaying, but it does alleviate a lot of unnecessary JavaScript, and it’s semantically correct(!!!) 😁

Here’s some more information about it: developer.mozilla.org/en-US/docs/W...

Collapse
diraskreact profile image
Dirask-React Author

Thank you for the tips! 😊πŸ”₯

Forem Open with the Forem app